Usa la suma de Minkowski
Una buena manera de resolver este problema es considerar la intersección entre una línea de movimiento ( v ) traducida al origen ( v ' ) y la suma de A de Minkowski girada 180 grados en el origen ( A' ) y sus obstáculos (solo B en este caso): a' ⊕ B .
En la siguiente imagen coloco A smack-dab en el origen de un sistema de coordenadas arbitrario. Esto simplifica la comprensión ya que la rotación de A en 180 grados da como resultado A ' , y v traducida al origen es igual a v' .
La suma de Minkowski es el rectángulo verde, y los puntos de intersección de una A en movimiento y una B estacionaria se pueden encontrar haciendo la intersección línea-AABB . Estos puntos están marcados con los círculos azules.
En la siguiente imagen se utilizó un origen diferente y se encuentran los mismos puntos de intersección.
Múltiples AABB móviles
Para que esto funcione para dos AABB que se mueven de manera lineal durante un período específico de tiempo, restarías el vector de velocidad de B del vector de velocidad de A y lo usarías como el segmento de línea para la intersección línea-AABB.
Pseudocódigo
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)
Respuesta de colisión
Dependiendo de la jugabilidad, realizaría una detección de colisión más fina (tal vez las AABB contienen mallas) o avanzaría a la siguiente fase: respuesta de colisión.
Cuando hay una colisión, el algoritmo de intersección línea-AABB devolverá 1 o 2 puntos de intersección dependiendo de si A finaliza su movimiento dentro de B o lo atraviesa, respectivamente. (Esto es descontar los casos degenerados en los que A roza a B a lo largo de sus lados o en una de sus respectivas esquinas).
De cualquier manera, el primer punto de intersección a lo largo del segmento de línea es el punto de colisión, lo traduciría de nuevo a la posición correcta en el sistema de coordenadas mundial (el primer círculo azul claro en la segunda imagen a lo largo de la v original , llámelo p ) y luego decida (p. ej., para colisiones elásticas al reflejar v a lo largo de la colisión normal en p ) cuál será la posición real de A al final del cuadro ( At + 1 ).
Si hay más de 2 colisionadores, esto se volverá un poco más complejo, ya que también querrá hacer una detección de colisión para la segunda parte reflejada de v .