Jeśli dwa obiekty wchodzą w interakcje, co zawiera kod interakcji?


28

Pomyśl o kuli i wrogu lub o graczu i podłodze. Jeśli te obiekty oddziałują, co zawiera kod interakcji?


2
Interakcja w jaki sposób? Masz na myśli wykrywanie kolizji? Jeśli tak, to najprawdopodobniej zaimplementujesz zarówno klasę wykrywania kolizji, jak i menedżera rozwiązywania kolizji.
CaptainRedmuff

Częściowo tak, jestem zainteresowany zarówno kolizją, jak i tym, co dzieje się po kolizji. Czy kula sprawdza, czy jest blisko wroga, czy na odwrót? A co dzieje się po zderzeniu, czy obiekt pociskowy może po prostu powiedzieć obiektowi wroga, że ​​został trafiony? Jak widać, jestem dość zdezorientowany co do całości, co sprawia, że ​​niektóre bardzo trudno jest odczytać kod.
ThatOneGuy

Odpowiedzi:


23

TL; DR:

Twoje obiekty w grze nie znają się nawzajem, ani nie sprawdzają innych obiektów. Tworzysz wzór wykrywania kolizji i rozdzielczości kolizji, który sprawdza obiekty w grze i wykonuje odpowiednie działania w celu symulacji fizyki gry.

Dobre rzeczy

Po poprzednich próbach napisania wykrycia kolizji i przeczytaniu tej książki istnieją dwa etapy wykrywania kolizji i rozwiązywania kolizji. Pierwszy etap (wykrywanie kolizji) to wczesne przejście, w którym określasz, czy dwa obiekty mogą mieć potencjalną kolizję. Jeśli jakiekolwiek dwa obiekty tworzą potencjalną kolizję, następnie przekazujesz te obiekty do drugiego etapu (rozdzielczość kolizji), aby przeprowadzić dokładniejsze sprawdzenie drobnoziarniste względem obiektów i spróbować rozwiązać kolizję.

Gdzieś w silniku / grze znajdziesz szereg wszystkich obiektów w twoim świecie. W każdej ramce zapętlasz tablicę i sprawdzasz każdy obiekt względem każdego innego obiektu za pomocą prostego wykrycia kolizji ramki / kuli.

Pseudo kod:

dectectCollisions(objects)
{
    for(objectA in objects)
    {
        for(objectB in objects)
        {
            if(objectA != objectB) //ignore self
            {
                if(BoundingSpheresIntersect(objectA, objectB))
                {
                    collisionResolver.addObjects(objectA, objectB);
                }
            }
        }
    }
}

Ten rodzaj pętli jest raczej nieefektywny, ale pozostawia miejsce na ulepszenia dzięki zastosowaniu podziału przestrzennego jako wczesnego rozwiązania dla obiektów, które z pewnością są zbyt daleko od siebie, aby się zderzyć.

Po sprawdzeniu dwóch obiektów pod kątem potencjalnej kolizji (tj. Oba obiekty są wystarczająco blisko, aby kolidować), obiekty są przekazywane dalej, aby wykonać bardziej precyzyjną procedurę wykrywania kolizji.

Wyobraź sobie, że masz dwa wielokąty o losowych kształtach i rozmiarach, które są wystarczająco blisko, aby potencjalnie się przecinać, ale nie ze względu na ich geometrię:

Obraz znaleziony przez Google

Przy użyciu sfer ograniczających te dwa obiekty stworzyłyby fałszywy alarm dla potencjalnej kolizji. W tym miejscu należy wykonać dokładniejsze przejście w celu ustalenia, czy dwa obiekty rzeczywiście się przecinają.

Po znalezieniu prawdziwej kolizji krok rozwiązywania kolizji wykonałby odpowiednie działanie w celu rozwiązania obiektów poprzez zastosowanie sił lub momentów w zależności od szczegółowości i potrzeb fizyki gry.

Mając to na uwadze, możesz wyodrębnić cały proces wykrywania i rozwiązywania kolizji, aby Twoje obiekty nie wiedziały o sobie ani procesu wymaganego do ustalenia i rozwiązania kolizji. Dwie klasy / menedżery, które zajmują się tym za Ciebie, muszą tylko znać podstawowe właściwości każdego obiektu, aby wykonać szybkie i brudne sprawdzenie kolizji, a następnie dokładniejsze sprawdzenie, jeśli to konieczne.


2
W szczególności odpowiedni byłby wzór projektowy Mediator. Wzorzec obserwatora byłby dobrą alternatywą, która ma zupełnie inne przeznaczenie. Całkiem dobre podsumowanie można znaleźć w tym wpisie Stackoverflow .
kurtzbot

12

Jednym ze sposobów, w jaki Unreal Engine 3 sobie z tym radzi:

Kula otrzymuje komunikat o kolizji, mówiąc, że coś trafił, a argument mówi, co trafił. Następnie może wywołać objectHit.takeDamage (self). Następnie cel otrzymuje komunikat TakeDamage ze wskaźnikiem na rzecz, która go trafiła, i podejmuje odpowiednią akcję.

Osobiście podoba mi się to podejście, ponieważ oznacza, że ​​kula może podejmować specjalne działania (takie jak wywoływanie efektu wybuchu w zależności od rodzaju trafionej rzeczy), a cel może podejmować specjalne działania w zależności od rodzaju kuli.

Możliwe jest również, że kula wie, co robi z celami i może wywoływać na niej funkcję, na przykład objectHit.freeze (self). Następnie cel wie, że został trafiony przez coś, co go zamraża i jaki to był obiekt.

EDYCJA: Ta odpowiedź ma na celu ogólny obraz tego, jak może ona działać, ponieważ prawdopodobnie nie pracujesz z UE3. :)


10

Złodziej zrobił to bardzo dobrze w Dark Engine ze źródłami i receptorami. Obiekt może mieć obie te właściwości z różnymi typami. Na przykład strzałka wody miałaby źródło dla WaterStim przy kontakcie. Eksplozja miałaby AoE FireStim.

Kiedy Strzałka Wody uderza w obiekt, obiekt docelowy przeszukuje swoje Receptrony w poszukiwaniu wszystkiego, co szuka WaterStim o odpowiednich wartościach intensywności. Następnie wykonuje dowolne związane z nim polecenie (w tym przypadku zamieniając płonącą pochodnię w wyłączoną i emitując kłęby dymu).

Ponieważ ten sam silnik jest używany w SystemShock2, w ten sposób obsługiwane są wszystkie różne typy obrażeń, różne pociski mają różne zestawy Stim, a różne potwory mają następnie Receptrony dla różnych typów Stim i zadają obrażenia równe 1 *, 2 *, 1 / 2 intensywność w zależności od tego, czy rodzaj amunicji jest „super skuteczny”, czy nie.

Wydawało się, że jest to bardzo elastyczny system, ponieważ można dodawać źródła i receptrony do obiektów w edytorze poziomów (powiedzmy, aby stworzyć jednorazowe drzwi, które otworzą się, jeśli zostaną uderzone przez ogień). Chociaż można również powiedzieć receptorowi, aby „wysłał skrypt wiadomość ”, jeśli z obiektem skojarzono specjalne skrypty.

To, czego nie chcesz robić, to trzeba na stałe zakodować macierz interakcji nXn wszystkich możliwych obiektów kolidujących ze wszystkimi możliwymi obiektami! Uogólniając interakcje za pomocą standardowych komunikatów, upraszczasz ten proces.


Z punktu widzenia skryptów takie podejście wydaje się najbardziej elastyczne i najbardziej wyraziste. Bardzo fajny.
drhayes

-2

Jednym z rozwiązań jest trzymanie pojemników z kulami i graczami w osobnych klasach, a następnie posiadanie funkcji main (), która utrzymuje pętlę ramki odpowiedzialną za interakcję.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.