Wo soll die Kollisionserkennungslogik platziert werden?

19

Ich entwickle eine kleine 2D-Game-Engine. Die Zeichen haben eine Malmethode, die derzeit Folgendes ausführt:

  1. Berechnen Sie die neue Position des Charakters anhand seiner Geschwindigkeit usw.
  2. Aktualisieren der Kollisionsgitterzelle **
  3. Zeichne den Charakter an der neuen Position

** Ich habe ein Kollisionsraster erstellt, um die Anzahl der Kreuzungsprüfungen zu verringern

Nun ist der grundlegende Algorithmus, den ich zur Erkennung von Kollisionen gedacht habe:

For Each Character
    Check intersection with characters in surrounding 8 cells

Ich kann diesen Code einfach in die Paint-Methode einfügen. Aber hier ist das Problem, das ich erwarte.

Angenommen, zwei Zeichen A und B liegen in benachbarten Zellen des Kollisionsgitters. Nun wird gemäß dem obigen Algorithmus bei der Iteration von Zeichen A festgestellt, dass es mit B kollidiert ist. Bei der Iteration von Zeichen B wird festgestellt, dass es mit A kollidiert ist.

Aber ich habe die Idee, dass wenn A feststellt, dass es mit B kollidiert ist, es B mitteilen sollte, dass es mit A kollidiert ist. Dies würde viele Vergleiche ersparen, wenn mehr als 2 Akteure kollidieren. Aber ich bin mir nicht sicher, wie ich damit umgehen soll. Ich denke, anstatt dass jeder Charakter nach seiner Kollision sucht, sollte ich innerhalb der Spielschleife nach der Kollision suchen.

Wäre dieser Ansatz richtig? Wie haben Sie mit solchen Problemen umgegangen? Ich habe selbst an das Kollisionsgitter gedacht. Gibt es Alternativen zur Kollisionsgitterlogik?

Cracker
quelle
Es tut mir leid, aber in einer spezialisierten 2D-Physik-Bibliothek. Die Spielphysik ist in der Regel sehr ungefähr, daher ist jede Lösung, die das Spiel nicht spielbar macht, in Ordnung. Wenn Sie sie jedoch richtig lösen möchten, verwenden Sie einfach eine spezielle Physik wie Box2D ... :-D
user712092

Antworten:

14

Der übliche Ansatz für die Kollisionserkennung besteht darin, dass weder A noch B selbst Kollisionen erkennen.

Stattdessen verschieben Sie zuerst alle Objekte, lassen dann in einem separaten Kollisionssystem nach Kollisionen zwischen allen Objektpaaren suchen, wobei Sie jedem Objekt mitteilen, mit welchen Dingen es kollidiert hat, und anschließend alle Objekte rendern.

Anstatt also in Ihrer Paint () -Funktion "Verschieben, auf Kollisionen prüfen, Zeichnen" auszuführen, teilen Sie "Verschieben" und "Zeichnen" in separate Funktionen auf, die Sie separat aufrufen (zuerst "Verschieben" für jedes Objekt, dann "zeichnen" für jedes Objekt). Und dazwischen auf Kollisionen prüfen.

Hinweis für Fortgeschrittene: Wenn sich eines Ihrer Objekte als Reaktion auf erkannte Kollisionen von selbst bewegt, müssen Sie möglicherweise den Schritt "Nach Kollisionen zwischen allen Objektpaaren suchen" wiederholen, falls die Kollisionsreaktion eines Objekts eine weitere Kollision verursacht.

Trevor Powell
quelle
Dies ist die richtige Art, Dinge zu tun. Lassen Sie die Objekte ihre Verantwortung wahrnehmen und das Kollisionssystem sollte entscheiden, was passiert, wenn sie auf ein Hindernis treffen. Sie können Ihre Charaktere auch mit einem Kollisionsrechteck / -zylinder (2d / 3d) als eine Art Frühauslöser versehen.
James P.
Groß! Sollten die Kollisionen in Bezug auf den erweiterten Hinweis nicht nur auf Objekte überprüft werden, die sich als Reaktion auf die Kollision und die Objekte, mit denen sie in der neuen Position kollidieren, selbst bewegen? Es wird eine Kette von Überprüfungen geben, aber es wird vermieden, die Kollision für alle Objekte zu überprüfen.
Cracker
Wie man damit umgeht - gamedev.stackexchange.com/questions/13076/…
Cracker
1

Ich starte eine Schleife für alle meine Charaktere in der Spieleschleife, wie Sie sagen.

Die Art und Weise, wie ich das mache, ist mit einem Status für jeden meiner Charaktere verbunden. Wenn also A und B kollidieren, während A die Kollision überprüft, sind A und B auf Treffer eingestellt. am anfang der schleife von b wird geprüft, ob die schleife bereits getroffen wurde, sonst wird die schleife nicht ausgeführt.

Ich habe den Affect-Code in die Schleife eingefügt, damit in der Schleife von A alle Aktionen ausgeführt werden, die für B ausgeführt werden sollten. Es sollte also keinen Grund für B geben, dies zu überprüfen, da dies das Ergebnis der Kollision verfälschen würde. Dies kann jedoch für Sie anders sein .

Skeith
quelle
In diesem Fall wird B.hit auf true gesetzt, wenn A eine Kreuzung mit B erkennt, und B prüft daher nicht, ob eine Kreuzung vorliegt. Aber wenn sich ein anderes Zeichen C mit B überschneidet, wird B es nicht erkennen?
Cracker
Entschuldigung. Da A nicht mit C schneidet, ist C.hit immer noch falsch. B prüft nicht auf Kollisionen. Aber C prüft und gibt die Information an B weiter, dass es eine Kollision zwischen B und C gibt. Cool!
Cracker
Aber ich denke, wenn sich alle A, B und C überschneiden, gibt es ein Problem. A setzt B.hit und C.hit auf true. B und C werden wissen, dass sie mit A kollidiert sind. Aber da ihre Treffer-Eigenschaft wahr ist, werden sie nicht auf Kollision prüfen. Die Kollision zwischen B und C bleibt unbemerkt.
Cracker
Sie können eine ähnliche Methode anwenden, indem Sie jedes funktionsfähige Kollisionsobjekt in eine Sammlung einfügen und dann nur die Kollision mit Dingen überprüfen, die nach dem Objekt in der Sammlung auftreten. IE: A prüft gegen B, C, D; B prüft gegen C, D; C-Checks gegen D. Jeder Rückstand muss nicht überprüft werden, da er bereits ab dem Zug des Rückstands überprüft wurde. Nicht ganz so schnell wie das Überspringen der Kollision des Elements, aber dennoch nützlich.
Lunin