2D-Spielkollisionsreaktion: SAT & minimale Verschiebung entlang einer bestimmten Achse?


13

Ich versuche, ein Kollisionssystem in einem 2D-Spiel zu implementieren, das ich mache. Der Satz der Trennachse (wie im Kollisions-Tutorial von Metanet beschrieben ) scheint eine effiziente und robuste Methode für die Kollisionserkennung zu sein, aber ich mag die von ihnen verwendete Kollisionsreaktionsmethode nicht ganz. Durch blindes Verschieben entlang der Achse mit der geringsten Überlappung ignoriert der Algorithmus einfach die vorherige Position des sich bewegenden Objekts, was bedeutet, dass es nicht so sehr mit dem stationären Objekt kollidiert, wie es in dieses eindringt und dann abprallt.

Hier ist ein Beispiel für eine Situation, in der dies eine Rolle spielen würde:

Beispiel

Nach der oben beschriebenen SAT-Methode würde das Rechteck einfach senkrecht zu seiner Hypotenuse aus dem Dreieck herausspringen:

SAT-Antwort

Realistisch sollte das Rechteck jedoch an der unteren rechten Ecke des Dreiecks anhalten, da dies der Punkt der ersten Kollision wäre, wenn es sich kontinuierlich entlang seines Verschiebungsvektors bewegen würde:

Realistische Reaktion

Nun, das ist vielleicht nicht wirklich wichtig während des Spiels, aber ich würde gerne wissen, ob es einen Weg gibt, auf diese Weise effizient und im Allgemeinen genaue Verschiebungen zu erzielen. Ich habe mir in den letzten Tagen den Kopf zerbrochen und möchte noch nicht aufgeben!

(Cross-posted von StackOverflow, hoffe das verstößt nicht gegen die Regeln!)


Es ist gegen die Regeln. Nicht kreuzen.
AttackingHobo

Ja, lösche es von StackOverflow und behalte es hier: P
TravisG

gamedev.stackexchange.com/questions/9144/… Ich habe Ihre spezielle Frage hier beantwortet.
Ultifinitus

Aus SO gelöscht.
Archagon

Starte ein Kopfgeld, Archagon: P Sonst muss ich es vielleicht tun. Diese Frage ist wirklich interessant und es wäre fantastisch, eine Antwort zu sehen, die mehr als nur ein paar Referenzen aufführt.
TravisG

Antworten:


11

Hier ist die Methode, die ich gefunden habe. Es mag fehlerhaft sein, aber ich habe noch keine Probleme damit in meiner flüchtigen Analyse gefunden. Es funktioniert auch für beliebige Polygone mit ein paar geringfügigen Änderungen.

In den folgenden Abbildungen bewegt sich das blaue Objekt und das rote Objekt steht still. 1 Schritt 1: Suchen Sie für jedes Polygon die beiden am weitesten entfernten Punkte entlang der Projektion dieses Polygons auf die Linie senkrecht zum Bewegungsvektor. 2 Schritt 2: Teilen Sie jedes Polygon entlang der Verbindungslinie zwischen diesen Punkten. Die Hälfte des Polygons, die dem anderen Polygon entlang des Bewegungsvektors zugewandt ist, ist die "vordere Hülle". Dies ist der einzige Teil des Polygons, der möglicherweise kollidieren kann. 3 Schritt 3:Projizieren Sie einen Vektor von jedem Punkt auf den "vorderen Rumpf" jedes Polygons entlang des Bewegungsvektors in Richtung des gegenüberliegenden Polygons und überprüfen Sie, ob er sich mit jeder Kante des "vorderen Rumpfs" des gegenüberliegenden Polygons schneidet. (Möglicherweise langsam, aber Computer sind heutzutage ziemlich schnell - richtig?) (Entschuldigen Sie den geneigten Pfeil. Alle Pfeile sollten parallel sein.) 4 Schritt 4: Nehmen Sie den kürzesten Vektor. Dies ist die genaue Kollisionsentfernung. 5 Schritt 5: Voila! 6


2
Das ist ziemlich beeindruckend. Haben Sie die Geschwindigkeit Ihres Algorithmus zufällig mit einfachem (4x oder 8x) Multisampling verglichen?
TravisG

Unglücklicherweise nicht.
Archagon

Beeindruckend, und ich bin sicher, dass die Mathematik auch nicht zu kompliziert / intensiv ist. +1
you786

7

Schauen Sie sich diese ähnliche Frage an: Kollisionsauflösung

Und auch von http://www.metanetsoftware.com/technique/tutorialA.html#section5 (zu dem Sie einen Link gepostet haben :))

ABSCHNITT 5: Sich schnell bewegende Objekte

Wie oben erwähnt, können kleine und / oder sich schnell bewegende Objekte Probleme verursachen, wenn ein statischer Kollisionstest verwendet wird. Es gibt verschiedene Ansätze, um mit solchen Objekten umzugehen. Am einfachsten ist es, das Spieldesign so einzuschränken, dass solche Objekte nicht benötigt werden.

Wenn Sie sie unbedingt benötigen, gibt es zwei gängige Methoden für den Umgang mit kleinen und / oder sich schnell bewegenden Objekten: Swept-Collision-Tests und Multisampling.

- = Wischtests = -

Anstatt zu testen, ob sich zwei statische Formen schneiden, können wir stattdessen neue Formen erstellen, indem wir die ursprünglichen Formen entlang ihrer Flugbahn ziehen und auf Überlappung zwischen diesen überstrichenen Formen prüfen.

Die Grundidee ist in [Gomez] für Kreis-Kreis- und AABB-AABB-Sweep-Tests beschrieben.

- = Multisampling = -

Eine viel einfachere Alternative zu Wobbeltests ist das Multisample. Anstatt einen einzelnen statischen Test an der neuen Position des Objekts durchzuführen, führen Sie mehrere Tests an mehreren Positionen zwischen der vorherigen und der neuen Position des Objekts durch. Diese Technik wurde verwendet, um die Ragdoll in N. kollidieren

Wenn Sie sicherstellen, dass die Proben immer einen Abstand haben, der kleiner als der Radius des Objekts ist, werden hervorragende Ergebnisse erzielt. In unserer Implementierung begrenzen wir die maximale Anzahl von Samples, sodass sehr hohe Geschwindigkeiten manchmal zu Problemen führen. Dies kann je nach Anwendung angepasst werden.

BEARBEITEN

Zusammenfassend und AFAIK gibt es ein paar Lösungen

  1. Beschränken Sie Ihr Spiel darauf, niemals ein kleines und / oder sich schnell bewegendes Objekt zu haben, das dies sogar verursachen kann
  2. Implementieren Sie ein System, das das tatsächliche Auftreten von Kollisionen verhindert, wie im ersten von mir geposteten Link beschrieben
  3. Erhöhen Sie die Abtastrate für schnelle und / oder kleine sich bewegende Objekte
  4. ... möglicherweise mehr, aber ich bin kein Experte.

1

Es hängt davon ab, ob Sie nur lineare Bewegungen möchten oder ob Sie auch mit Winkelbewegungen fertig werden müssen.

Eine Alternative zur Verwendung von SAT:

Im Falle von nur linear kann gegen den Minkowski-Unterschied der beiden Polygone vom Ursprung in Richtung der Delta-Lineargeschwindigkeit der Objekte gestrahlt werden.

Wenn der Strahl auf die MD trifft, kollidieren die beiden Objekte und der Trefferpunkt gibt die Zeit t an, zu der sie kollidierten.

Wenn sich die Objekte bewegen und drehen , wird es schwieriger, aber Sie können trotzdem eine ähnliche Technik anwenden. Mit Conservative Advancement können Sie sich mit diesem Fall befassen. Diese Technik ist iterativ; Jede Iteration generiert eine neue MD und bringt Sie der Zeit der Schnittmenge näher.

Hier ist der Originalentwurf zum konservativen Fortschritt:

http://www.continuousphysics.com/BulletContinuousCollisionDetection.pdf

Ich habe hier einen Artikel geschrieben, der die Technik ausführlich erklärt:

http://www.wildbunny.co.uk/blog/2011/04/20/collision-detection-for-dummies/

Hoffe diese Hilfe!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.