Nach der Antwort von larsbutler spielt es in einfachen Fällen keine Rolle, ob Sie zuerst nach x- oder y-Kollisionen suchen. Dies kann jedoch später schnell zu Ungenauigkeiten führen (insbesondere bei komplexeren Formen, höheren Geschwindigkeiten und mehr Objekten).
Wenn jemand an der Implementierung eines ausgefeilteren Kollisionserkennungsalgorithmus interessiert ist, finden Sie hier eine Übersicht über die erforderlichen Funktionen:
- Zunächst führt der Algorithmus einen Sweep durch und beschneidet die Anzahl der zu überprüfenden Objekte. Wenn Sie jedes Objekt mit jedem anderen Objekt vergleichen, kann dies rechenintensiv sein. Grundsätzlich sagen Sie voraus, ob ein Objekt in Zukunft wahrscheinlich kollidieren wird. Wenn es nicht sehr wahrscheinlich ist, führen Sie die Berechnungen nicht durch.
- Nach dem Beschneiden führen Sie einen vorläufigen Kollisionstest durch. Jedes Objekt hat ein begrenzendes Rechteck oder einen begrenzten Kreis (etwas, das leicht zu berechnen ist). Das Erkennen, ob zwei Kreise / Rechtecke kollidieren, ist recht einfach und kann unnötige Berechnungen zwischen zwei Objekten auf gegenüberliegenden Seiten des Bildschirms schnell eliminieren.
- Wenn eine vorläufige Erkennung durchgeführt wurde, müssen Sie die Kanten jeder Form durchlaufen und Kollisionspunkte erkennen (Schnittpunkt zweier Liniensegmente). In Jons Fall wäre dies der Kollisionspunkt auf der vertikalen und horizontalen Achse.
- Sobald Sie eine Liste von Kollisionspunkten haben, müssen Sie den genauen Kollisionspunkt berechnen. Es gibt eine Reihe von Möglichkeiten, wie Sie dies tun können, und alles hängt davon ab, wie genau Sie sein möchten. Eine Möglichkeit ist , auf die Hälfte der Zeitinkrement (Ihres Physik - Integrator ), die Formen Positionen neu zu berechnen, und wiederholen Sie die Kollisionserkennung , bis es ist nur ein Kollisionspunkt. Grundsätzlich nähern Sie sich dem "Moment des Aufpralls" an. Wenn Ihre Simulation nicht sehr viele partielle Differentialkräfte aufweist, können Sie einfach die Geschwindigkeit der vorherigen Integration mit nachfolgenden Zeithalbierungen verwenden.
- Die Ergebnisse von Schritt vier geben Ihnen die ungefähren Kollisionspunkte (innerhalb einer oberen / unteren Grenze wie 3px oder so). Wenn es mehr als einen Kollisionspunkt gibt, müssen Sie diese als imaginäre Kante behandeln. Sie können dann Kollisionsauflösungsberechnungen durchführen (Geschwindigkeit, Impuls, Reibung usw.)
Hoffe das hilft jemandem.
Speziell für Jons Frage:
Der Schritt, den Sie beim Kollisionsalgorithmus vermissen, ist Schritt 4. Soweit ich weiß, schneiden sich Ihre Rechtecke diagonal und erhalten zwei Kollisionspunkte (einen horizontal und einen vertikal). Die Bestimmung, welcher Kollisionspunkt zuerst aufgetreten ist, hängt wirklich davon ab, was Sie für die Physikintegration verwenden.
Aus Ihrer Beschreibung geht hervor, dass sich die Rechtecke nicht drehen und Dinge wie partielle Differentialkräfte keine große Rolle spielen. Wenn dies der Fall ist , ist es ziemlich einfach herauszufinden, welche Kante zuerst kollidiert. Hier ist ein Pseudocode:
/*
Assume Obj1 is stationary
Assume Obj2's velocity is -x and -y (to bottom left)
From this, we know the collision edges are:
*/
colEdgesObj1 = [1,0]; //right, top
colEdgesObj2 = [0,1]; //left, bottom
//... where [0=left/1=right, 0=top/1=bottom]
//Calculate distances between Obj1 edges and Obj2 edges
distX = Math.Abs(Obj1[colEdgesObj1[0] ? "right" : "left"] -
Obj2[colEdgesObj2[0] ? "right" : "left"]);
distY = Math.Abs(Obj1[colEdgesObj1[1] ? "bottom" : "top"] -
Obj2[colEdgesObj2[1] ? "bottom" : "top"]);
//Calculate time object would take to go those distances
//(assuming Obj2 is the only moving object)
timeX = distX/Obj2.VelX;
timeY = distY/Obj2.VelY;
//If time is greater, that axis has been colliding longer
if timeX > timeY
//collided X axis first
else if timeY > timeX
//collided Y axis first
else
//collided at a corner