Verwenden Sie die Minkowski-Summe
Eine gute Möglichkeit, dieses Problem zu lösen, besteht darin, den Schnittpunkt zwischen einer Bewegungslinie ( v ), die zum Ursprung ( v ' ) verschoben wurde, und der Minkowski-Summe von A , die am Ursprung ( A' ) um 180 Grad gedreht wurde , und seinen Hindernissen (nur B) zu betrachten in diesem Fall): A‘ ⊕ B .
Im folgenden Bild platziere ich einen Klaps in den Ursprung eines beliebigen Koordinatensystems. Dies vereinfacht das Verständnis, da das Drehen von A um 180 Grad zu A ' führt und v in den Ursprung übersetzt gleich v' ist .
Die Minkowski-Summe ist das grüne Rechteck, und die Schnittpunkte eines sich bewegenden A und eines stationären B können durch Ausführen der Schnittlinie AABB ermittelt werden . Diese Punkte sind mit den blauen Kreisen markiert.
Im folgenden Bild wurde ein anderer Ursprung verwendet und es wurden die gleichen Schnittpunkte gefunden.
Mehrere bewegliche AABBs
Damit dies für zwei AABBs funktioniert, die sich in einem bestimmten Zeitraum linear bewegen, würden Sie subtrahieren Geschwindigkeitsvektor von B vom Geschwindigkeitsvektor von A und verwenden diesen als Liniensegment für den Schnittpunkt zwischen Linie und AABB.
Pseudocode
def normalize(aabb):
return {x1: min(aabb.x1, aabb.x2), x2: max(aabb.x1, aabb.x2),
y1: min(aabb.y1, aabb.y2), y2: max(aabb.y1, aabb.y2),
def rotate_about_origin(aabb):
return normalize({x1: -aabb.x1, x2: -aabb.x2
y1: -aabb.y1, y2: -aabb.y2})
# given normalized aabb's
def minkowski_sum(aabb1, aabb2):
return {x1: aabb1.x1+aabb2.x1, x2: aabb1.x2+aabb2.x2,
y1: aabb1.y1+aabb2.y1, y2: aabb1.y2+aabb2.y2}
def get_line_segment_from_origin(v):
return {x1: 0, y1: 0, x2: v.x, y2: v.y}
def moving_objects_with_aabb_intersection(object1, object2):
A = object1.get_aabb()
B = object2.get_aabb()
# get A'⊕B
rotated_A = rotate_about_origin(A)
sum_aabb = minkowski_sum(rotated_A, B)
# get v'
total_relative_velocity = vector_subtract(object1.get_relative_velocity(), object2.get_relative_velocity())
line_segment = get_line_segment_from_origin(total_relative_velocity)
# call your favorite line clipping algorithm
return line_aabb_intersection(line_segment, sum_aabb)
Kollisionsreaktion
Abhängig vom Gameplay würden Sie entweder eine feinkörnigere Kollisionserkennung durchführen (möglicherweise enthalten die AABBs Maschen) oder mit der nächsten Phase fortfahren: Kollisionsreaktion.
Bei einer Kollision gibt der AABB-Schnittpunkt-Algorithmus entweder 1 oder 2 Schnittpunkte zurück, je nachdem, ob A seine Bewegung innerhalb von B beendet oder durch ihn läuft. (Dies schließt die entarteten Fälle aus, in denen A B entlang ihrer Seiten oder entlang einer ihrer jeweiligen Ecken streift.)
In beiden Fällen ist der erste Schnittpunkt entlang des Liniensegments der Kollisionspunkt. Sie würden diesen Punkt in die richtige Position im Weltkoordinatensystem zurückversetzen (der erste hellblaue Kreis im zweiten Bild entlang des ursprünglichen v , nennen Sie ihn p ) und dann entscheiden (z. B. für elastische Kollisionen durch Reflektieren von v entlang der Kollisionsnormalen bei p ), wie die tatsächliche Position für A am Ende des Rahmens sein wird ( bei + 1 ).
Wenn es mehr als nur 2 Collider gibt, wird dies etwas komplexer, da Sie die Kollisionserkennung auch für den zweiten, reflektierten Teil von v durchführen möchten .