Jak radzić sobie z kolizjami narożnymi w 2D?

22

Piszę odgórną grę XNA 2d. Od początku staram się pisać fizykę i kolizje, aby się tego nauczyć.

Ilekroć moja postać sprite'a gracza próbuje przejść do pozycji, w której jej granice przecinają się z krawędzią ściany, wymyślam kąt odbicia (kąt padania = kąt odbicia) i zmuszam gracza do odbicia się od ściany i unikania kolizji .

Mam problem z ustaleniem, jak poradzić sobie z sytuacją mojego duszka przecinającego się z dwiema krawędziami ściany jednocześnie, chociaż np. Uderza w narożnik.

zderzenie narożne

Mój kod mówi mi obecnie, że dwie krawędzie ściany zostały przecięte, ale nie wiem, która krawędź uderzyłaby jako pierwsza, a zatem która krawędź odskoczyła.

Jaki jest test matematyczny, aby wybrać, która krawędź ma się odbić? Patrząc na to z łatwością widać, ale staram się wymyślić test matematyczny.

TerryB
źródło
Dzięki Tetrad. Widziałem to, ale wyglądało na to, że kula zachowuje się inaczej niż mój prostokątny problem. W przypadku pokazanym powyżej prostokątny duszek uderzyłby w dolną krawędź ściany i odbiłby się od niej. Boczna krawędź ściany nigdy nie wchodziłaby w równanie. Po prostu nie wiem, jak to wyrazić w kodzie i podjąć taką decyzję.
TerryB

Odpowiedzi:

9

Jeśli obliczyć, jak daleko w został przeniesiony, prawdopodobnie można oprzeć go na delcie xiy współrzędne narożników, które są przecinające się. Mam nadzieję, że to ma sens, nie mogę wymyślić lepszego sposobu na sformułowanie tego.WallPlayer Sprite

Na przykład, jeśli spojrzysz na diagram. Weź xwartość lewego górnego rogu Player Sprite(po przeniesieniu) i odejmij xwartość prawego dolnego rogu Wall. Zrób to samo dla ywartości, a następnie sprawdź, która z nich jest większa. Kluczem jest to, że jeśli jeden jest większy od drugiego, Player Spriteprawdopodobnie przecinają się po tej stronie.

Oto przykład obrazu (jest to podsekcja twojego obrazu z dodanymi moimi liniami):

przykład skrzyżowania

Teraz widzisz tutaj, że niebieska linia jest większa niż zielona linia. W tym przypadku niebieska linia znajduje się również po tej stronie, z Player Spritektórej można się spodziewać odbicia.

Jeśli dwie wartości są równe, trafiają w róg.

Teraz jest niewielki problem z robieniem tego w ten sposób. Jeśli Player Spritepodróż odbywa się bardzo szybko lub kolizja znajduje się bardzo blisko rogu, możliwe, że Player Spritemoże pójść dalej Wallw złym kierunku. W takim przypadku prawdopodobnie będziesz musiał sprawdzić prędkość poruszającego się obiektu. (Zobacz odpowiedź Nathana Reeda ).

Uwaga: Myślę, że w zasadzie staram się opisać wykrywanie kolizji SAT, o którym wspomniał @Blau, ale spędziłem dużo czasu na pisaniu tego, więc i tak go opublikuję. Mam nadzieję, że ci to pomoże.

Richard Marskell - Drackir
źródło
Dzięki Drackir! I sądzę, że jeśli moja ściana jest obrócona względem duszka, jest to nieco trudniejsze, ale obowiązuje ta sama zasada. Poszukaj wektora przesunięcia o minimalnej długości, który oznaczałby, że duszek nie zderzyłby się ze ścianą. Następnie użyj ściany, która jest normalna dla tego wektora, jako mojej, aby się odbić.
TerryB
@TerryB - Rotacja dodaje nieco więcej złożoności. Możesz przeczytać na wyrównanych do osi obwiedniach (AABB). Zasadniczo nadal używasz tej samej zasady, co powyżej, testując najmniejsze pudełko, w którym zmieści się obrócony obiekt, ale którego osie są wyrównane do osi kartezjańskich. Wyobraź sobie, że masz kwadrat i obróciłeś go o 45 stopni, aby zrobić z niego diament. Obliczenie kolizji byłoby trudne i kosztowne, więc najpierw sprawdź, czy obiekt jest w pobliżu, używając AABB, który byłby kwadratem, w którym każdy punkt diamentu dotyka każdej strony pośrodku.
Richard Marskell - Drackir
Następnie, gdy wiesz, że jest w pobliżu, możesz wykonać bardziej kosztowne obliczenia, aby sprawdzić, czy przecinają się pod kątem (co prawdopodobnie powinno być zupełnie innym pytaniem :)).
Richard Marskell - Drackir
1
-1, ponieważ minimalne przesunięcie nie zawsze daje prawidłową odpowiedź na „która krawędź zderzyła się pierwsza”; zobacz moją odpowiedź.
Nathan Reed,
@NathanReed - Dlatego wspomniałem o sprawdzeniu prędkości w moim akapicie „Teraz jest niewielki problem z robieniem tego w ten sposób”.
Richard Marskell - Drackir
15

Minimalne przemieszczenie nie zawsze daje właściwą odpowiedź, dla której krawędzi trafiono jako pierwszą. Rozważ ten przypadek:

przypadek, który łamie algorytm najkrótszego przemieszczenia

Dzieje się tak, gdy prędkość jest na tyle duża, że ​​blok przesuwa się dość daleko podczas jednej klatki. Aby poprawnie wykryć, która krawędź została trafiona jako pierwsza, musisz skonfigurować równanie liniowe, aby rozwiązać czas zderzenia z każdą krawędzią. W tym przypadku opisanym na schemacie PO odpowiednie równania to:

timeXCollision = (player.left - wall.right) / -player.velocity.x
timeYCollision = (wall.bottom - player.top) / player.velocity.y

(Zakłada się, że układ współrzędnych X-y, Y-up.) Ogólnie rzecz biorąc, będziesz musiał użyć znaków elementów X i Y player.velocity, aby określić, która para krawędzi musi zostać przetestowana. W każdym razie, po obliczeniu czasów kolizji, wcześniejszą z nich jest kolizja, którą trzeba poradzić.

Nathan Reed
źródło
1
Czy możesz podać przykład, w jaki sposób można zaimplementować dwie zmienne?
BjarkeCK
1

Potrzebujesz wykrycia kolizji SAT

Zasadniczo musisz poszukać wektora minimalnego przesunięcia, który został odjęty od jednego z obiektów, aby nie przecinały się.

Na twoim obrazie minimalnym przesunięciem jest pomarańczowy segment.

wprowadź opis zdjęcia tutaj

Blau
źródło
4
-1, ponieważ minimalne przesunięcie nie zawsze daje prawidłową odpowiedź na „która krawędź zderzyła się pierwsza”; zobacz moją odpowiedź.
Nathan Reed,
kto o to pyta?
Blau,
Pytanie to zadaje. „Mój kod mówi mi obecnie, że dwie krawędzie ściany zostały przecięte, ale nie wiem, która krawędź uderzyłaby jako pierwsza, a zatem która krawędź się odbiła ”.
Nathan Reed,
pierwszy? problemem nie jest to, co jest pierwsze, koliduje on jednocześnie z dwoma krawędziami, ... chodzi o to, która krawędź się odbija, wybrałeś jedną metodę, która jest dla ciebie dobra, wybrałem metodę, która jest dobrze dla mnie, oba są ważne
Blau
1
Jeśli chcesz podjąć decyzję projektową, aby obiekty prześlizgnęły się obok siebie w taki sposób, jakby były zaokrąglone lub fazowane na rogach, to twoja decyzja i może być właściwa dla twojej gry. Ale nie sądzę, że pytanie dotyczy decyzji projektowej; pyta matematycznie, jak odbić od siebie prostokąty osi. To nie jest kwestia interpretacji; ten problem matematyczny ma jasną i poprawną odpowiedź na jaką krawędź się odbić.
Nathan Reed
0

Odpowiedziałem na podobne pytanie tutaj

Możesz rozważyć sprawdzenie poprzednich pozycji

Na przykład: jeśli lewa strona znajdowała się wcześniej na prawo od prawej strony i kolidujesz, nastąpiło zderzenie z prawą ręką.

Jeśli to zrobisz, po prostu rozwiąż kolizje osi y, sprawdź, czy kolidujesz z czymś, a następnie rozwiąż kolizje osi x.

ultifinitus
źródło