Use a soma de Minkowski
Uma boa maneira de resolver esse problema é considerar a interseção entre uma linha de movimento ( v ) traduzida para a origem ( v ' ) e a soma de Minkowski de A girada 180 graus na origem ( A' ) e seus obstáculos (apenas B neste caso): a' ⊕ B .
Na figura a seguir, coloco A smack-dab na origem de um sistema de coordenadas arbitrário. Isso simplifica a compreensão, pois girar A em 180 graus resulta em A ' e v traduzidos para a origem igual a v' .
A soma de Minkowski é o retângulo verde, e os pontos de interseção de um A móvel e um B estacionário podem ser encontrados através da interseção da linha AABB . Esses pontos são marcados com os círculos azuis.
Na figura a seguir, uma origem diferente foi usada e os mesmos pontos de interseção foram encontrados.
Vários AABBs em movimento
Para fazer isso funcionar para dois AABBs que se movem de maneira linear durante um período específico, você subtrai o vetor de velocidade de B do vetor de velocidade de A e o utiliza como segmento de linha para a interseção linha-AABB.
Pseudo-có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)
Resposta à colisão
Dependendo da jogabilidade, você realizaria uma detecção de colisão mais refinada (talvez os AABBs contenham malhas) ou avançaria para a próxima fase: resposta à colisão.
Quando há uma colisão, o algoritmo de interseção de linha AABB retornará 1 ou 2 pontos de interseção, dependendo de A terminar o movimento dentro de B ou passar por ele, respectivamente. (Isso está descontando os casos degenerados em que A roça B ao longo de seus lados ou em um de seus respectivos cantos.)
De qualquer maneira, o primeiro ponto de interseção ao longo do segmento de linha é o ponto de colisão. Você o traduziria de volta à posição correta no sistema de coordenadas mundiais (o primeiro círculo azul claro na segunda foto ao longo do original v , chame-o de p ) e depois decida (por exemplo, para colisões elásticas refletindo v ao longo da colisão normal em p ) qual será a posição real de A no final do quadro ( At + 1 ).
Se houver mais do que apenas 2 colisores, isso ficará um pouco mais complexo, pois você também deseja detectar a colisão para a segunda parte refletida de v .