Resolução de colisão em caso de colisão com vários objetos


15

Eu tenho objetos estáticos e objetos móveis. As colisões são detectadas usando o teorema do eixo separador.

Por exemplo, nessa situação, tenho dois objetos estáticos (em vermelho):

insira a descrição da imagem aqui

e um objeto móvel entre os dois:

insira a descrição da imagem aqui

Meu algoritmo é capaz de calcular a colisão entre dois desses objetos e também cospe um vetor de resolução perfeita (significando um vetor de deslocamento mínimo) para a colisão.

Por exemplo, quando eu checo a colisão entre o retângulo verde e o retângulo vermelho direito, o algoritmo cospe um vetor que me diz como eu preciso mover o retângulo verde para resolver a colisão:

insira a descrição da imagem aqui

Observe que eu desenhei isso rapidamente no MSPaint, então nessa imagem pode ser que o vetor de tradução mínimo empurre o retângulo verde para cima, mas presumo que o empurre para a esquerda / certo é realmente mais curto.

A maneira geral de abordar isso seria resolver apenas a colisão de uma colisão por quadro, em vez de todos de uma vez. Mas no meu caso, isso resultaria em flip-flopping:

Primeiro, o solucionador detecta duas colisões, mas apenas resolve a colisão entre o retângulo direito e o retângulo verde:

insira a descrição da imagem aqui

Em seguida, no próximo quadro, ele detecta apenas uma colisão que está entre o retângulo vermelho esquerdo e o retângulo verde e o resolve:

insira a descrição da imagem aqui

Como você pode ver, isso realmente não resolve a colisão (por exemplo, empurrando o retângulo verde para cima) e, em vez disso, apenas inverta os flops infinitamente.

Como posso resolver isso?


Você está usando retângulos no seu exemplo. Seu algoritmo de colisão resolve apenas a colisão em apenas um eixo? Nesse caso, faz sentido que o comportamento que você descreve esteja ocorrendo.
chaosTechnician

Não, ele pode resolvê-los com qualquer tipo de forma em todos os eixos possíveis (não apenas retângulos, eles são os mais fáceis de desenhar com tinta MS: P) e sempre encontrará o vetor mais curto existente que separa os dois objetos .
TravisG

+1 boa pergunta. Eu removi a "tag" (2D) do título, é algo que você deve evitar (consulte a meta ).
bummzack

Respostas:


7

Dependendo exatamente do que você está tentando alcançar (alta precisão física ou apenas uma simulação em tempo real suficientemente próxima), você pode tentar usar contatos especulativos.

Aqui estão os detalhes: http://www.wildbunny.co.uk/blog/2011/03/25/speculative-contacts-an-continuous-collision-engine-approach-part-1/

Ele descreve nesse artigo o que você precisa saber para implementá-lo, e é muito simples comparado a outras abordagens (como projeção de esferas e classificação das resoluções de colisão por tempo de impacto).

Se você precisar / quiser mais, poderá comprar o código-fonte por US $ 7 (IIRC).

Aqui está um vídeo da minha implementação em 3D: http://www.youtube.com/watch?v=JvT2H1RmOas

Observe como a simulação é estável com apenas uma única iteração. Você poderia facilmente usar várias iterações por quadro para resolver várias colisões para um estado estável, o que seria mais preciso.


2

Você pode primeiro calcular todos os vetores necessários para resolver cada colisão e depois calcular uma resultante deles.

O único caso em que isso pode ser byte é se esses vetores se anulam, como no seu exemplo. Nesse caso, a colisão não pode ser resolvida.


Adicione um pequeno vetor aleatório com uma magnitude de cerca de epsilon * 10 às colisões? A aritmética de ponto flutuante deve fazer o resto.
Martin Sojka

2
Sim, isso pode funcionar, eu acho. Mas também pode criar movimentos trêmulos.
Mihai Maruseac

11
Espero ainda poder obter uma resposta sobre isso: calcular um resultante corrige o problema do "loop infinito", mas reintroduz o problema do "crack", onde mover-se enquanto desliza sobre uma parede feita de ladrilhos do mesmo tamanho faz com que o corpo fique preso entre as "rachaduras" dos azulejos. Existe alguma maneira de resolver esses dois problemas?
Vittorio Romeo

Concordo ... não existe a melhor "resposta certa" para resolver uma colisão impossível de corpos rígidos como essa. Ou ele se agita, ou você permite um pouco de "bolor" em um ou mais dos objetos.
David van brink

0

Se você olhar atentamente, esse estado de objetos é (ou deveria ser) inatingível.

Deixe a forma vermelha mais à esquerda ter a forma R1 e a forma vermelha mais à direita ter a forma R2. Deixe a forma verde ser G.

Dado o tamanho e a geometria dos três objetos, e considerando que todos os objetos não são penetráveis:

 (1) G could not have been just directly to the left of R2, since R1 has been there 
     already. Consequently, the translation of G from left to right, penetrating R2
     could not have occurred.
 (2) G could not have been just directly to the right of R1 since R2 has been there 
     already. Consquence of which is the same as that from (1).
 (3) Had G come from the top, the movement will be blocked by both R1 and R2, given
     that their geometry and Y coordinate is the same.

Agora, tudo se resume a isso: se seu algoritmo consulta seus objetos um por um, é uma questão de simultaneidade, ou seja, de certa forma, o algoritmo deve verificar TODOS os objetos ao mesmo tempo, mas o algoritmo limita você a fazer objetos e processá-los um de cada vez ...

Se G é checado contra R1 depois de checado com R2, então G parece legalmente estar à direita de R1 (se G diz aproxima-se de R1 com a direção do vetor <-1, -1> com magnitude (ou distância) arbitrária ), porque a verificação entre R1 e G permite isso e esquece a verificação entre R2 e G, que foi feita antes.

Uma solução que você pode fazer é coletar todos os vetores de deslocamento mínimo em uma matriz ou em qualquer estrutura de dados desejada e escolher uma que seja legal para TODOS os Objetos.

Observe que em um determinado quadro, o objeto (G, por exemplo) pode ter apenas UMA direção. (oh cara, parece a boyband ...)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.