W grze platformowej 2D, w jaki sposób zapewnić płynne poruszanie się gracza po pochyłym terenie?

18

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.

Nick Kovac
źródło
Ogólny silnik fizyki doskonale nadaje się do efektów i spadających skrzynek, ale nie do fizyki postaci, zgodnie z opisem w sekcji odpowiedzi. Rozważ napisanie „statycznej” fizyki dla swojej postaci, abyś mógł mieć 100% kontroli, a resztę używać odpowiednio symulowanej dynamiki.
Domi

Odpowiedzi:

14

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ę.

Sean Middleditch
źródło
Dzięki za odpowiedź. Zastanawiałem się nad zmniejszeniem pól reprezentujących ziemię do linii, ale tak naprawdę nie sądzę, że samo to rozwiąże problem. Na przykład, jeśli pola naziemne są teraz liniami, a jeśli gracz stoi na linii C i podróżuje w lewo w kierunku B, z powodu niedokładności możliwe jest, że pole gracza znajduje się nieco poniżej linii C. Następnie lewa krawędź pola gracza nadal może kolidować z linią B i powodować niepożądane zderzenie,
Nick Kovac
chyba że istnieje jakiś inny mechanizm, aby temu zapobiec. To nie fakt, że Box2D używa linii zamiast pól, które rozwiązuje problem, to fakt, że Box2D używa kształtu łańcucha, który wykorzystuje informacje o łączności między segmentami linii, aby zapobiec niektórym kolizjom. Obecnie głównym problemem jest to, że nie do końca rozumiem szczegóły tego, jak to dokładnie robi.
Nick Kovac
Podniosłeś kilka innych naprawdę dobrych uwag na temat problemów z pobieraniem pomysłów z silników fizyki ogólnej i stosowaniem ich w grach platformowych. Widziałem podobne silniki, które realizują omawiane pomysły (modyfikowanie normalnej kolizji na zboczach i zasysanie gracza na zboczu), więc przynajmniej te problemy można dość łatwo rozwiązać. Głównym punktem spornym są dla mnie trudne przypadki krawędzi związane z błędami numerycznymi.
Nick Kovac
@Kovsa: ponownie, te konkretne błędy znikają, gdy pozbywasz się krawędzi, które nie powinny być częścią kolizji. Połącz krawędzie, aby uzyskać nieprzerwany kształt. Podczas projektowania poziomu zalecam również łączenie wierzchołków, aby nie było żadnych małych szczelin na powierzchni. Nie inaczej, niż sposób projektowania poziomu w edytorze siatek 3D.
Sean Middleditch
Hmm ... nie sądzę, żebym podążał. Na moim schemacie, jeśli połączę ze sobą krawędzie, aby uzyskać nieprzerwany kształt, uzyskałbym kształt złożony z trzech segmentów linii: góra pól A, B i C, prawda? Mimo że jest to pojedynczy kształt, nadal musiałbym przeprowadzić wykrywanie kolizji osobno względem linii A, a następnie B, a następnie C, prawda? Chyba że masz na myśli algorytm, który może wykryć kolizję między pudełkiem a tym połączonym kształtem? Zakładam, że nie byłby to wtedy SAT, ponieważ seria krawędzi może być wklęsła?
Nick Kovac
5

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.

Kevin Reid
źródło
Hmm, ciekawy pomysł ... jak byś go wdrożył? Jest to jednak sprzeczne z prostotą korzystania z pudełek: (Zgadzam się, że wydaje się, że powinien to być powszechny problem z ostatecznym rozwiązaniem, ale nie mogę znaleźć żadnego pokrycia na ten temat naprawdę ... poza tym, co jest robione w Box2D. Zadałem podobne pytanie na ich forum, aby, mam nadzieję, uzyskać więcej informacji
Nick Kovac
Niestety nie mam żadnych szczegółów implementacyjnych, przepraszam - nie jestem ekspertem od tego rodzaju kodu silnika fizyki. Miałem jednak lepszy pomysł na rozwiązanie, które nie opiera się na czynnikach krówki - patrz moja edycja.
Kevin Reid
1
Pamiętaj, że chociaż korzystanie z zaokrąglonych kształtów działa, jest ono zarówno bardziej złożone matematycznie, jak i może powodować nieoptymalne zachowanie platformówek. Gracze oczekują na przykład niemal perfekcyjnej kontroli pikseli nad postaciami stojącymi na półkach, których zaokrąglone kształty będą mniej lub bardziej niemożliwe, a postacie niespodziewanie ześlizgną się z półek.
Sean Middleditch
Półki: D'oh! OK, nie tak proste jak myślałem.
Kevin Reid
Tak, po przemyśleniu, podejście kapsułowe wydaje się być bardziej odpowiednie dla gry 3D niż platformówki 2D. Perfekcyjne sterowanie pikselami jest dla mnie zdecydowanie priorytetem (tak jak miało to miejsce w przypadku wszystkich starych platformówek 2D). Ale musi istnieć rozwiązanie, które pozwala na używanie skrzynek!
Nick Kovac