Utilisez la somme de Minkowski
Un bon moyen de résoudre ce problème est de considérer l'intersection entre une ligne de mouvement ( v ) traduite à l'origine ( v ' ) et la somme de Minkowski de A tournée de 180 degrés à l'origine ( A' ) et ses obstacles (juste B dans ce cas): A » ⊕ B .
Dans l'image suivante, je place A smack-dab à l'origine d'un système de coordonnées arbitraires. Cela simplifie la compréhension car la rotation de A de 180 degrés donne A ' , et v traduit à l'origine est égal à v' .
La somme de Minkowski est le rectangle vert, et les points d'intersection d'un A en mouvement et d'un B stationnaire peuvent être trouvés en faisant l' intersection ligne-AABB . Ces points sont marqués par des cercles bleus.
Dans l'image suivante, une origine différente a été utilisée et les mêmes points d'intersection sont trouvés.
Plusieurs AABB mobiles
Pour que cela fonctionne pour deux AABB qui se déplacent de manière linéaire pendant une période de temps spécifique, vous devez soustraire le vecteur de vitesse de B du vecteur de vitesse de A et l'utiliser comme segment de ligne pour l'intersection ligne-AABB.
Pseudo code
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)
Réponse à la collision
Selon le gameplay, vous effectuez soit une détection de collision plus fine (peut-être que les AABB contiennent des mailles), soit vous passez à la phase suivante: la réponse à la collision.
En cas de collision, l'algorithme d'intersection ligne-AABB renvoie respectivement 1 ou 2 points d'intersection selon que A termine son mouvement à l'intérieur de B ou le traverse, respectivement. (Ceci réduit les cas dégénérés où A effleure B le long de leurs côtés ou le long d'un de leurs coins respectifs.)
Quoi qu'il en soit, le premier point d'intersection le long du segment de ligne est le point de collision, vous devez le traduire à la bonne position dans le système de coordonnées mondial (le premier cercle bleu clair dans la deuxième image le long du v d' origine , appelez-le p ) et ensuite décider (par exemple, pour les collisions élastiques en réfléchissant v le long de la normale de collision en p ) quelle sera la position réelle de A à la fin de la trame ( At + 1 ).
S'il y a plus de 2 collisionneurs, cela deviendra un peu plus complexe, car vous voudriez également effectuer la détection de collision pour la deuxième partie réfléchie de v .