Qual é a maneira mais eficiente de encontrar o ponto de interseção de um míssil e um terreno de bitmap?

10

Seguindo a minha pergunta anterior sobre como encontrar a inclinação de um terreno de bitmap 2D, agora preciso saber a melhor maneira de encontrar o ponto no terreno 2D que o míssil atingiu. Obviamente, posso ver se algum pixel sob o míssil cruza o terreno, mas digo que ele se moveu bastante fundo no terreno.

Qual é a melhor maneira de voltar atrás e descobrir onde ela colidiu inicialmente? Eu poderia voltar X pixels de cada vez para a posição anterior do míssil, mas qual seria um bom valor para X? E existe uma maneira mais inteligente? Talvez movendo metade da distância, então um quarto, etc?

Iain
fonte
O fenômeno que você está descrevendo é chamado de "encapsulamento", e a melhor maneira de lidar com isso é introduzir um teste de varredura - como o TetraD e o JasonD mencionaram abaixo.
precisa saber é
apenas dizer "teste de varredura" não me ajuda. Como faço isso com um terreno de bitmap?
Iain
A sugestão de Jason parece ser a melhor para mim: um pixel de cada vez.
jpaver

Respostas:

3

Para testes de colisão, você não deve fazer testes estáticos de tick-by-tick, deve fazer testes de rastreio / varredura.

Há uma lista exaustiva de várias fórmulas para diferentes tipos de primitivas aqui: http://www.realtimerendering.com/intersections.html

Isso é claro, supondo que você possa dividir seu terreno em algum tipo de conjunto de primitivas com as quais você possa testar (ou seja, segmentos de linha). Existem várias maneiras de fazer isso.

Veja também esta pergunta (apenas ligeiramente relacionada): Qual é um bom algoritmo para detectar colisões entre esferas móveis?

Tetrad
fonte
Eu estava pensando em um terreno de bitmaps destrutível como em Worms. Você poderia gerar dinamicamente primitivas a partir de um bitmap ou isso seria muito louco?
Iain
1
Eu tenho certeza que você poderia, mas pode ser mais fácil / mais rápido fazer testes pixel por pixel para um bitmap arbitrário.
Tetrad
COM UMA QUADTREE !! (para que ele não demorar uma eternidade)
bobobobo
3

A pesquisa binária não ajudará se você tiver pequenos pedaços de cenário e projéteis em movimento rápido - você pode sentir falta deles.

Acho que sua melhor opção é varrer uma linha pela frente do projétil ao longo do caminho, pixel por vez. Você pode fazer uma verificação delimitadora primeiro em todo o volume para evitar fazer isso a cada passo.

JasonD
fonte
O que é pesquisa binária?
Iain
1
Desculpe - a pesquisa binária é mais ou menos o que você estava falando na pergunta. Você começa no meio e divide o espaço de pesquisa por dois até convergir para a resposta. É ideal em muitos casos, mas no seu caso não funcionaria (você pode pular a resposta correta por completo).
JasonD
3

Como é improvável que o míssil mova uma quantidade enorme de pixels por quadro (não seria bom na tela), não vejo razão para não apenas verificar todos os pixels no caminho. O algoritmo de linha Bressenham é seu amigo, e certifique-se de que você também tenha uma cópia local do seu bitmap, pois geralmente não deseja acessar a memória de vídeo para cada pixel. Isso pressupõe que seu terreno de bitmap seja totalmente aleatório (conforme o terreno de worms destrutíveis). Se seu mundo é baseado em blocos, você pode pular todos os blocos que você sabe que estão vazios para começar, mas, como mencionado anteriormente, a menos que você tenha uma quantidade enorme de mísseis para verificar, não consegui pensar em uma plataforma que precisaria lenta demais para testar pixel por pixel, e você não precisará ter seu mundo definido em primitivas (um clone de worms tornaria isso complicado)

Kaj
fonte
Sim, eu estava pensando em um terreno parecido com Worms. Você poderia dividi-lo em blocos dinamicamente e marcar apenas os blocos vazios para não serem verificados? Se houvesse muitos mísseis ao mesmo tempo, talvez isso acelerasse um pouco as coisas?
Iain
Então você acha que devo avançar pixel por pixel, verificando a interseção, em vez de recuar?
Iain
Acho que as três respostas sugeriram uma pesquisa direta. Verificar para trás não funcionará se o passo a seguir o fizer pular alguns cenários.
JasonD
Sim, definitivamente encaminha.
Kaj
1

Além das outras respostas, há algumas coisas que você pode fazer para acelerar isso, se quiser fazer uma pequena contabilidade, no que diz respeito à "coleta" de vários pixels em blocos de "estado semelhante conhecido". Por exemplo, você pode armazenar a altura da parte mais alta do terreno, para ter como certo que o míssil não atingirá nada enquanto estiver acima disso. Você também pode armazenar a altura do menor espaço "aéreo", para saber que, se o míssil chegar a essa altitude, ele deve ter atingido alguma coisa (embora isso possa ser melhor usado como verificação de sanidade). Indo além disso, você pode armazenar retângulos que representam áreas que são todo o terreno e outros retângulos que são todos do ar, mas que podem ser mais trabalhosos do que valor.

Por fim, o melhor método provavelmente será "armazenar a altura de cada coluna do terreno" e depois apenas calcular a altura do míssil a cada passo do caminho. Não posso falar com jogos mais modernos, mas acredito que, quando você fez uma "caverna" em Scorched Earth, o terreno acima dessa caverna caiu direto, sem deixar saliências. Se você quiser saliências, o trabalho será um pouco maior, mas será uma extensão dessa ideia básica. (Dica: comece a ideia básica trabalhando primeiro!)

Como seu terreno é presumivelmente completamente arbitrário, não há atalhos. Mesmo que você tenha forçado seu terreno a ser um spline ou algo assim, isso ficará aborrecido quando você começar a destruí-lo e os testes de interseção de spline de linha forem iterativos e não perfeitos ou exaustivos e sem sentido lentos para o seu tipo de problema.

traço-tom-bang
fonte