Gdzie należy umieścić logikę wykrywania kolizji?

19

Rozwijam mały silnik do gier 2D. Znaki mają metodę malowania, która obecnie wykonuje następujące czynności:

  1. Oblicz nową pozycję postaci według jej prędkości itp.
  2. Zaktualizuj komórkę siatki kolizyjnej **
  3. Narysuj postać na nowej pozycji

** Utworzyłem siatkę kolizyjną, aby zmniejszyć liczbę kontroli skrzyżowań

Podstawowym algorytmem, który myślałem o wykrywaniu kolizji, jest:

For Each Character
    Check intersection with characters in surrounding 8 cells

Mogę po prostu umieścić ten kod w metodzie malowania. Ale oto problem, który przewiduję.

Załóżmy, że dwa znaki A i B leżą w sąsiednich komórkach w siatce kolizyjnej. Teraz zgodnie z powyższym algorytmem w iteracji znaku A wykryje, że zderzył się z B. W iteracji znaku B wykryje, że zderzył się z A.

Mam jednak pomysł, że gdy A wykryje, że zderzył się z B, powinien poinformować B, że zderzył się z A. To zaoszczędziłoby wielu porównań, gdy zderza się więcej niż 2 aktorów. Ale nie jestem pewien, jak sobie z tym poradzić. Myślę, że zamiast każdej postaci sprawdzającej kolizję, powinienem sprawdzić kolizję w pętli gry.

Czy takie podejście byłoby prawidłowe? Jak poradziłeś sobie z tego rodzaju problemem? Sam pomyślałem o siatce kolizyjnej. Czy są jakieś alternatywy dla logiki siatki kolizji?

Krakers
źródło
Przykro mi, że wyrywam, ale w specjalistycznej bibliotece fizyki 2D. Fizyka gry jest zwykle bardzo przybliżona, więc każde rozwiązanie, które nie powoduje, że gra nie jest odtwarzana, jest w porządku, ale jeśli chcesz rozwiązać to poprawnie, po prostu użyj specjalistycznej fizyki, takiej jak Box2D ... :-D
user712092

Odpowiedzi:

14

Zwykle podejście do wykrywania kolizji polega na tym, aby nie wykrywać kolizji A lub B samodzielnie.

Zamiast tego najpierw przesuwasz wszystkie obiekty, a następnie osobny system kolizji szuka kolizji między wszystkimi parami obiektów, informując każdy obiekt o przedmiotach, z którymi się zderzył, a następnie renderuje wszystkie obiekty.

Zasadniczo zamiast wykonywać ruch, sprawdzać kolizje, rysować wewnątrz funkcji Paint (), dzielisz ruch i rysujesz na osobne funkcje, które wywołujesz osobno (najpierw „ruch” dla każdego obiektu, a następnie „rysuj” dla każdego obiektu). A między nimi sprawdź kolizje.

Uwaga zaawansowana: Jeśli którykolwiek z twoich obiektów porusza się w reakcji na wykryte kolizje, może być konieczne powtórzenie kroku „szukaj kolizji między wszystkimi parami obiektów”, na wypadek, gdyby reakcja kolizji obiektu spowodowała kolejną kolizję.

Trevor Powell
źródło
To jest właściwy sposób robienia rzeczy. Pozwól obiektom wywiązać się ze swoich obowiązków, a system kolizji powinien zdecydować, co stanie się, gdy napotka przeszkodę. Możesz również mieć prostokąt kolizji / cylinder (2d / 3d) wokół swoich postaci, jako rodzaj wczesnego wyzwalacza.
James P.
Świetny! Jeśli chodzi o uwagę zaawansowaną, czy kolizje nie powinny być sprawdzane ponownie tylko pod kątem obiektów, które poruszają się w reakcji na kolizję i obiektów, z którymi zderzają się w nowej pozycji? Będzie łańcuch sprawdzeń, ale pozwoli to uniknąć kolizji wszystkich obiektów.
Cracker
Jak sobie z tym poradzić - gamedev.stackexchange.com/questions/13076/…
Cracker
1

Prowadzę pętlę dla wszystkich moich postaci w pętli gry, tak jak mówisz.

Sposób, w jaki to robię, polega na stanie na każdej z moich postaci, więc jeśli A i B zderzą się, podczas gdy A sprawdza, czy kolizja A i B są ustawione na uderzenie. na początku pętli B sprawdza, czy jest już trafiony, jeśli tak, id nie uruchamia pętli.

Umieszczam kod afektu w pętli, więc wszelkie działania, które należy podjąć na B, miały miejsce w pętli A, więc B nie powinien mieć powodu do sprawdzania, ponieważ mogłoby to zepsuć wynik kolizji, może to być jednak inne dla ciebie .

Skeith
źródło
Ale w tym przypadku, gdy A wykryje przecięcie z B, B.hit zostanie ustawione na true, więc B nie będzie sprawdzać ŻADNEGO przecięcia. Ale jeśli inny znak C przecina się z B, B go nie wykryje?
Krakers
Przepraszam, rozumiem Ponieważ A nie przecina się z C, C.hit nadal będzie fałszywy. B nie będzie sprawdzał kolizji. Ale C sprawdzi i przekaże B informację, że istnieje kolizja między B i C. Cool!
Krakers
Ale myślę, że jeśli wszystkie A, B i C przecinają się ze sobą, byłby problem. A ustawi B.hit i C.hit na true. B i C będą wiedzieli, że zderzyli się z A. Ale ponieważ ich właściwość trafienia jest prawdą, nie sprawdzą kolizji. Zderzenie między B i C pozostanie niezauważone.
Cracker
Możesz zakraść się w podobny sposób, umieszczając każdy możliwy obiekt kolizyjny w jakiejś kolekcji, a następnie sprawdzając tylko kolizję z rzeczami, które występują po obiekcie w kolekcji. IE: Czeki A względem B, C, D; Kontrole B względem C, D; C sprawdza się w porównaniu z D. Każde z tyłu nie musi być sprawdzane, ponieważ zostało już sprawdzone od kolejki z tyłu. Nie tak szybko, jak całkowite pominięcie kolizji elementu, ale mimo to przydatne.
Lunin