Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Algorytm/ARM - Symulacja odbić kulki od przeszkód na STM32F103VCT6

piotrva 06 Aug 2013 12:33 3015 12
  • #1
    piotrva
    VIP Meritorious for electroda.pl
    Witam serdecznie Kolegów!
    Aktualnie jestem w trakcie pisania gry typu labirynt z kulką na procesor ARM STM32F103VCT6. Wszystko mam pięknie i ładnie obsłużone (symulacja odbić od powierzchni płaskich, detekcja kontaktu z otworami) no ale zostało jeszcze najważniejsze - symulacja odbić kulki od kantów prostokąta. I tu niestety zaczynają się schody.

    Z punktu widzenia fizycznego sprawa jest prosta, wręcz banalna, mianowicie:
    1. Warunkiem #1 zderzenia jest poruszanie się piłki w kierunku danego kantu (czyli dowolna ze składowych prędkości ma wartość wskazującą na zbliżanie się kuli do rogu.
    2. Warunkiem #2 zderzenia jest to, że kula znajduje się w odległości równej swojemu promieniowi od kantu (czyli jej powierzchnia styka się z kantem).

    3. Kula przy odbiciu zachowuje się tak, jakby odbijała się od powierzchni zawartej w stycznej do jej powierzchnii w miejscu kontaktu. W 2 wymiarach załóżmy, że powierzchnia ta jest prostą o równaniu y=a1x+b1 Punkt końcowy ruchu w danym przedziale czasu należy zatem odbić w symetrii względem tej prostej, natomiast prędkości vx i vy zgodnie z takimi zależnościami opisanymi w programie:
    
    ball_xt=2.0*(atanf(a1)+atanf(vx/vy));
    ball_yt=cosf(ball_xt);
    ball_xt=sinf(ball_xt);
    								
    vxn=vy*ball_xt+vx*ball_yt;
    vyn=vx*ball_xt+vy*ball_yt;
    


    Starałem się przenieść te zależności do programu, dodając jeszcze warunek zapobiegający zapętleniu się przy sprawdzaniu odbicia od danego kantu, jednak nie do końca działa to tak jak powinno (na razie obsługuję tylko lewy górny kant) - po pierwsze kulka znacząco spowalnia w momencie kontaktu z kantem (ale to można zrzucić na jeszcze niezoptymalizowane obliczenia i nie stablicowane funkcje trygonometryczne atan i sin oraz cos), a po drugie i najważniejsze - czasem przelatuje na drugą stronę kantu (wlatuje w przeszkodę).

    Sam algorytm główny działa tak jak rosowanie linii. Czyli na początku na podstawie przyspieszenia z akcelerometru wyliczamy prędkość, potem na jej podstawie przesunięcie kulki. I potem od puntku aktualnego do nowego położenia posuwamy sie piksel po pikselu, za każdym razem sprawdzając, czy nie zderzamy się z przeszkodą.

    Nie oczekuję oczywiście na gotowca (choć po tygodniu zmagań z algorytmem odbić chciałbym jaknajszybciej przejść do wczytywania poziomów i ich obsługi), ale na naprowadzenie jak to zapisać lub (jeśli ktoś znajdzie lub zna coś ciekawego) wskazanie takiego algorytmu w sieci (trochę stron przejrzałem, ale algorytmu jakie znalazłem nie obsługiwały odbić - po prostu kulka po zderzeniu otrzymywała v=0).

    Mile widziane także sugestie dot. samego algorytmu wykrywania odbić.

    Z góry dziękuję za pomoc i uwagi merytoryczne.

    --------------------------------------------------------
    Kod funkcji obsługującej grę:
    Code: c
    Log in, to see the code


    Kod całego programu (poza bibliotekami):
    Code: c
    Log in, to see the code
  • Helpful post
    #2
    nsvinc
    Level 35  
    Kulka wlatująca w przeszkodę to najpewniej efekt pracy na intach. Jesli miałbyś FPU, to problem byłby rozwiązany - po prostu brakuje Ci ułamków...
    Spróbuj wykonywać operację na u64 fixed point, przesuwając przecinek na np 40sty bit -> Q23.40... Funkcje trygonometryczne powinieneś wtedy tez mieć stablicowane w tym formacie, ale dodatkowo owinąć LUT w funkcje interpolujące, aby ten LUT miał sensowną wielkosć...

    Albo najpierw sprawdź, czy będzie działać dla zmiennej 32bitowej, czyli operacje wykonuj na Q11.20 ;]
  • #3
    piotrva
    VIP Meritorious for electroda.pl
    Hmm, ale ja pracuję na floatach nawet - na razie piszę algorytmy, zeby sprawdzić działanie, potem będę optymalizował szybkość...
    Przy zmianie warunku odbicia na sqrt(...)<=8.0 też to samo...
  • #4
    Anonymous
    Anonymous  
  • #5
    piotrva
    VIP Meritorious for electroda.pl
    Jak to?
    Układ współrzędnych zaczyna mi się w prawym górnym rogu ekranu. Czyli jeśli ma się kula zbliżać do lewego górnego rogu to vx>0 lub vy>0...
  • Helpful post
    #6
    Anonymous
    Anonymous  
  • #7
    piotrva
    VIP Meritorious for electroda.pl
    rogi wklęsłe mam załatwione algorytmem odbić od powierzchni - nie ma potrzeby tego opisywać osobno - chodzi tylko o rogi wypukłe...
  • Helpful post
    #8
    Freddie Chopin
    MCUs specialist
    Myślę że dobrą opcją byłoby uogólnienie algorytmu na taki punktowy - wykrywanie kolizji + obliczanie nowego kierunku ruchu. Tym sposobem jeden kod załatwia zarówno odbicia od ścian jak i od wierzchołków.

    4\/3!!
  • #9
    piotrva
    VIP Meritorious for electroda.pl
    Hmm, w sensie, że po ruchu o każdy piksel badamy czy kulka nie styka się z punktem przeszkody i jeśli tak, to od tego punktu wykonujemy odbicie?
    Idea fajna - rzeczywiście wtedy jedna dobrze napisana funkcja załatwiałaby wszystkie odbicia - w tym od przeszkód ustawionych pod kątem, które na razie zostawiłem na później... Tylko zastanawiam się nad implementacją wyszukiwania takich punktów i reprezentacji przeszkód.
    Mam teraz takie pomysły:
    1. Korzystać z pamięci GRAM wyświetlacza (czyli ustalić kolor przeszkód i odczytywać dane o danych pikselach z wyświetlacza.
    2. W pamięci RAM umieścić tablicę i reprezentować dane w formie binarnej - dla poprawy szybkości można by posłużyć się dostępem atomowym. - zajmie 9600B
  • Helpful post
    #10
    dondu
    Moderator on vacation ...
    Na Spectrum-ie pod koniec lat 80-tych robiłem Arkanoida - bardzo fajnie działało, choć nie był tak rozbudowany jak te oryginalne wersje (nie miał spadających bonusów), ale obsługiwał dowolne kąty łącznie z trafieniem w ostry róg cegiełki pod dowolnym kątem oraz "podkręcanie" piłki rakietką. Oj męczyłem się z tym wtedy strasznie - brak źródeł wiedzy - tyko matematyka + assembler + ambicje :-)

    Robiłem to na zasadzie wykrywania kolizji - coś w tym stylu: http://www.wildbunny.co.uk/blog/2011/04/20/collision-detection-for-dummies/

    Ale niedawno gdzieś mignął mi bardzo fajny angielskojęzyczny artykuł o wektorowym podejściu do analizy trasy kulki i stwierdzaniu jej przyszłej kolizji z przeszkodą. Niestety nie potrafię go w tej chwili odnaleźć. Ale może ktoś wskaże.
  • #11
    piotrva
    VIP Meritorious for electroda.pl
    Podążyłem tropem algorytmu punktowego.
    Na razie w 100% ze powodzeniem przeniosłem algorytm odbić od powierzchni płaskich na algorytm punktowy - przypadki odbić prostopadłych rozpatruję osobno (obliczenia bez funkcji trygonometrycznych będą szybsze, poza tym od razu pozbywamy się potencjalnego dzielenia przez zero w obliczeniach) - teraz zostało tylko napisać prawidłowo odbicia od krzywizn kulki.
    A potem oczywiście optymalizacja kodu, przyspieszenie obliczeń funkcji trygonometrycznych...
    Code: c
    Log in, to see the code
  • #12
    piotrva
    VIP Meritorious for electroda.pl
    I kontynuuję temat.
    Na razie kod taki:
    Code: c
    Log in, to see the code


    I tak:
    1.Warunkiem odbicia od powierzchni innej niż prostopadła do osi X i Y jest to, że kąt zawarty między wektorem prędkości wypadkowej a półprostą wyznaczaną przez środek kuli i punkt zderzenia jest mniejszy lub równy 90* (co do wartości bezwzględnej).
    2. Pozostałe zasady generowania odbicia pozostają bez zmian
    3. Sam algorytm jest taki, że mam matrycę w której 1 oznacza przeszkodę, a 0 jej brak. I teraz przy ruchu piłki o każdy piksel między punktem początkowym i końcowym dla danego odcinka czasu sprawdza (zapisane w tablicy) wszystkie punkty z otoczenia piłki.

    Ogólnie jest już lepiej - kulka nie przelatuje przez rogi i kanty, ale... czasem w nie wnika...
    Czyli coś jest nie tak z wykrywaniem kolizji nadal...

    Z góry dziękuję za pomoc...
  • #13
    TWl
    Level 21  
    piotrva wrote:

    I kontynuuję temat.

    Na razie kod taki:

    Czyli coś jest nie tak z wykrywaniem kolizji nadal...



    A moze prosty algorytm wektorowy - mniej wiecej tak z kolizjami radza sobie nowsze gry...

    Code: c
    Log in, to see the code


    TWl