Usa la somma di Minkowski
Un buon modo per risolvere questo problema è considerare l'intersezione tra una linea di movimento ( v ) tradotta nell'origine ( v ' ) e la somma di Minkowski di A ruotata di 180 gradi all'origine ( A' ) e i suoi ostacoli (solo B in questo caso): a' ⊕ B .
Nell'immagine seguente inserisco A smack-dab nell'origine di un sistema di coordinate arbitrario. Ciò semplifica la comprensione della rotazione di 180 gradi di A in A ' , e v tradotto nell'origine equivale a v' .
La somma di Minkowski è il rettangolo verde e i punti di intersezione di una A in movimento e una B fissa possono essere trovati facendo l' intersezione linea-AABB . Questi punti sono contrassegnati dai cerchi blu.
Nell'immagine seguente è stata utilizzata un'origine diversa e sono stati trovati gli stessi punti di intersezione.
AABB mobili multipli
Per far funzionare questo per due AABB che si muovono in modo lineare durante uno specifico periodo di tempo, sottraresti il vettore di velocità B dal vettore di velocità A e lo utilizzeresti come segmento di linea per l'intersezione linea-AABB.
Codice pseudo
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)
Risposta alla collisione
A seconda del gameplay eseguiresti un rilevamento delle collisioni più dettagliato (forse gli AABB contengono mesh) o passerai alla fase successiva: la risposta alle collisioni.
Quando c'è una collisione l'algoritmo line-AABB-intersection restituirà 1 o 2 punti di intersezione a seconda che A finisca il suo movimento all'interno di B o lo attraversi, rispettivamente. (Questo sta scontando i casi degeneri in cui A sfiora B lungo i loro lati o lungo uno dei rispettivi angoli.)
Ad ogni modo, il primo punto di intersezione lungo il tratto di linea è il punto di collisione, lo ritrasformeresti nella posizione corretta nel sistema di coordinate del mondo (il primo cerchio azzurro nella seconda immagine lungo la v originale , chiamalo p ) e quindi decidere (ad es. per le collisioni elastiche riflettendo v lungo la collisione normale a p ) quale sarà la posizione effettiva per A alla fine del telaio ( At + 1 ).
Se ci sono più di 2 soli collider, questo diventerà un po 'più complesso, poiché si vorrebbe fare il rilevamento delle collisioni anche per la seconda, riflessa, parte di v .