Opracowuję silnik fizyki do platformy 2D. Używam twierdzenia o osi oddzielającej do wykrywania kolizji. Powierzchnia ziemi jest zbudowana z zorientowanych ramek ograniczających, a odtwarzacz jest ramką ograniczającą wyrównaną do osi. (W szczególności używam algorytmu z książki „Wykrywanie kolizji w czasie rzeczywistym”, która wykonuje wykrywanie przeciągnięcia kolizji dla OBB za pomocą SAT). Używam dość małego (bliskiego zeru) współczynnika restytucji w odpowiedzi na kolizję, aby upewnić się, że obiekty dynamiczne nie przenikają do środowiska.
Silnik w większości działa dobrze, po prostu martwię się o niektóre przypadki, które mogą wystąpić. Na przykład na schemacie A, B i C oznaczają powierzchnię ziemi. Gracz zmierza w lewo wzdłuż B w kierunku A. Wydaje mi się, że z powodu niedokładności, pole gracza może znajdować się nieco poniżej pola B, gdy jest kontynuowane w górę i w lewo. Kiedy więc osiągnie A, lewy dolny róg gracza może zderzyć się z prawą stroną A, co byłoby niepożądane (ponieważ celem gracza jest płynne przesuwanie się nad górą A). Wygląda na to, że podobny problem może się zdarzyć, gdy gracz znajdzie się na polu C i przesunie się w lewo w kierunku B - najbardziej skrajny punkt B może zderzyć się z lewą stroną odtwarzacza zamiast lewego dolnego rogu gracza przesuwającego się w górę i w lewo powyżej B.
Box2D wydaje się radzić sobie z tym problemem, przechowując informacje o łączności dla swoich kształtów krawędzi, ale nie jestem do końca pewien, w jaki sposób wykorzystuje te informacje do rozwiązania problemu, a po zapoznaniu się z kodem tak naprawdę nie rozumiem, co robi.
Wszelkie sugestie będą mile widziane.
Odpowiedzi:
Platformowanie i fizyka
Te przypadki krawędzi są liczne. Dobra zabawa platformówki nie zachowują się w żaden fizycznie dokładny sposób, a kontrola i zachowanie, których gracze oczekują po latach „perfekcyjnych” platformówek, takich jak Mario, są niezwykle trudne do wdrożenia za pomocą ogólnych technik, takich jak w Box2D lub innych silnikach fizycznych. Większość dobrych platformówek nie używa żadnej ogólnej fizyki ani reakcji na kolizję w swoich kontrolerach graczy.
Generuj kadłuby
Jeśli chodzi o konkretne pytanie, najlepszym rozwiązaniem jest zaprzestanie używania skrzynek jako podstawy. Użyj szeregu połączonych segmentów linii (kadłuba). Pozwala to silnikowi na wykrywanie kolizji skupić się tylko na powierzchniach, na których można chodzić, i nie patrzeć na „fałszywą” krawędź istniejącą między AB a BC. Tak właśnie działa Box2D. Kształty są używane do generowania zewnętrznych powierzchni, które są połączone ze sobą, tworząc kadłub.
Potrzebujesz tego nawet w grach opartych na kafelkach lub w sytuacjach, w których dwa inne obiekty AABB obok siebie działają jak podłoga. Silnik kolizji podniesie te pionowe krawędzie i spowoduje, że gracz złapie je. Są hacki, które mogą pomóc, ale nie wyeliminować problemu. Rozwiązaniem jest posiadanie pojedynczego segmentu linii reprezentującego powierzchnię zamiast pełnego pola 2D.
Kadłuby można generować w ogólnym przypadku, przycinając wielokąty i łącząc punkty klipu w listę krawędzi.
Ukośne powierzchnie
Ponieważ twój przykład zawiera nachylenie i wspominasz restytucję i inne właściwości fizyczne, przedstawię kilka innych problemów, które wkrótce zauważysz, co dodatkowo ilustruje, dlaczego ogólne wykrywanie kolizji i reakcja nie działa dobrze dla platformówek. Najpierw spróbuj stać na pochylonej platformie, podskoczyć, a następnie wylądować. Prawdopodobnie zauważysz, że postać trochę się „ześlizgnie” podczas lądowania. Problem polega na tym, że normalny kontakt, który generujesz, zwykle będzie wskazywał z nachylonej powierzchni. Następnie podczas rozstrzygania kolizji gracz jest wypychany w tym kierunku. Mimo że postać spadła prosto w dół, zostanie wyrzucona i lekko w prawo podczas lądowania, co spowoduje poślizg. Można to zhakować, biorąc pod uwagę względne prędkości,
Drugim problemem, który zauważysz, a który jest o wiele trudniejszy do rozwiązania, jest to, co dzieje się, gdy próbujesz szybko zjechać z rampy. Gracz „zeskoczy” z rampy. Jest to bardzo widoczne nawet w większości dzisiejszych gier AAA. Nie tylko wygląda to głupio, ale jeśli twoja gra wymaga od gracza stania na ziemi, aby skoczyć, utrudnia zbieganie po pochylni i skakanie w połowie, ponieważ gracz kontaktuje się z rampą tylko przez niewielką część czas spędzony na schodzeniu. Prostszym rozwiązaniem jest po prostu wykonanie niektórych rzutów promieniami, gdy gracz się porusza, i przyciągnięcie pozycji gracza do najbliższej powierzchni (jeśli jest bardzo blisko gracza), jeśli gracz nie skacze i był wcześniej na ziemi.
Może się również okazać, że gracz rzuca się w powietrze, gdy wjeżdża na rampę, jeśli spróbujesz modelować prędkość, tarcie i restytucję odtwarzacza tak, jakby był normalnym sztywnym ciałem. Ruch gracza powinien być ograniczony do ruchu poziomego, chyba że spada / skacze. Oczywiście, jeśli grasz w starsze platformówki ze złotego wieku, możesz zauważyć, że pozioma prędkość gracza jest często stała między poziomymi i nachylonymi powierzchniami. Należy to wziąć pod uwagę również podczas chodzenia po zboczach.
Będzie też wiele innych nieparzystych skrzynek narożnych, na które też się natkniesz. Jeśli próbujesz stworzyć dobrą platformówkę, naprawdę najlepiej jest zaimplementować kontroler odtwarzacza platformówki niezależnie od fizyki i zakodować pożądane zachowanie ruchowe i kontrolne, zamiast polegać na ogólnej fizyce i algorytmie reakcji na kolizję.
źródło
Wydaje mi się, że oba problemy można rozwiązać, traktując swoje skrzynki dla celów reagowania na zderzenia, tak jakby miały zaokrąglone rogi (o promieniu podobnym do twojego błędu numerycznego). Sprawi to, że efektywna łączna powierzchnia narożników spotkania między A i B oraz B i C będzie gładsza.
Zatem jeśli GRACZ poruszający się w lewo trafi w narożnik A, normalna kolizja byłaby ukośna, a nie wyłącznie w prawo, umożliwiając kontynuację ruchu w lewo iw górę.
Jednak bardziej typowym rozwiązaniem, po przejrzeniu tego, co wiem o fizyce platformówki, jest nadanie graczowi bardziej zaokrąglonego kształtu i pozostawienie terenu w spokoju. W szczególności rozważ uczynienie kształtu gracza kapsułą (rozciągniętym w środkowym kole (2D) / kuli (3D)) - wtedy normalne kolizje będą naturalnie prawie pionowe, eliminując wszelkie problemy z chwytaniem.
Mówisz, że używasz algorytmu kolizji specjalnie dla OBB, ale po znalezieniu kolizji OBB-OBB nadal powinieneś być w stanie przeprowadzić kolejny test na kształcie, który jest całkowicie w OBB.
źródło