Como calcular o vetor de uma interceptação?

11

Dado um espaço bidimensional e uma espaçonave amigável parada, um inimigo está se movendo NÃO diretamente para a nave amiga com posição, velocidade e direção reais conhecidas.

O navio amigo quer entrar no campo de tiro para combater o inimigo.

Na verdade, estou definindo apenas um vetor direto para a posição real da nave em movimento e recalculando-a a cada quadro, resultando em algum tipo de percurso de vôo "redondo".

O que eu quero é definir um caminho direto e direto para a posição que o inimigo (presumivelmente) terá quando a distância de tiro for alcançada, assumindo que o inimigo não mudará de rumo até então.

Como uma primeira e "simples" implementação, seria suficiente se assumirmos que o amigo pode acelerar de 0 a max rapidamente.

A implementação preferida seria aquela que considera os recursos de aceleração do amigo e sabe quando a interceptação é impossível por causa da velocidade. Deve funcionar para todas as velocidades de partida, não apenas para ficar parado. Uma vantagem seria se considerar a frenagem (lutar na velocidade da luz é muito ineficiente em energia no universo)

NobbZ
fonte

Respostas:

5

Se entendi sua pergunta, você não quer que o navio dirija até o alvo, mas sim voar em linha reta que intercepta o alvo. Estou fazendo um jogo de defesa de torre que basicamente tem a mesma necessidade de uma bala de torre, uma torre quer disparar uma arma de modo que a bala intercepte um alvo em movimento, desde que não mude a velocidade / direção. O jeito que eu resolvi foi usando uma equação quadrática. Aqui está algum pseudo-código:

Vector totarget =  target.position - tower.position;

float a = Vector.Dot(target.velocity, target.velocity) - (bullet.velocity * bullet.velocity);
float b = 2 * Vector.Dot(target.velocity, totarget);
float c = Vector.Dot(totarget, totarget);

float p = -b / (2 * a);
float q = (float)Math.Sqrt((b * b) - 4 * a * c) / (2 * a);

float t1 = p - q;
float t2 = p + q;
float t;

if (t1 > t2 && t2 > 0)
{
    t = t2;
}
else
{
    t = t1;
}

Vector aimSpot = target.position + target.velocity * t;
Vector bulletPath = aimSpot - tower.position;
float timeToImpact = bulletPath.Length() / bullet.speed;//speed must be in units per second

Achei que funcionava tão bem que não precisava de detecção de colisão para o tiro ... Consegui contar com todos os tiros atingindo o alvo, independentemente da distância / direção / velocidade do alvo, desde que esses fatores permanecessem constantes.

Steve H
fonte
Pela sua descrição, isso parece ser o que estou procurando, pelo menos da maneira mais fácil, assumindo uma aceleração instantânea à velocidade máxima. Vou dar uma olhada nisso à noite. Estou assumindo que Vector.Dot retorna o produto de ponto dos vetores?
NobbZ
Hummm ... já fiz isso em rubi agora, mas parece que algo está errado. Sempre que tento, há uma exceção lançada, porque a expressão no sqrt é avaliada como algo negativo e, portanto, está fora dos limites. Como posso lidar com isso. Desculpe a pergunta, mas só posso usar isso, mas não entendo os conceitos aqui até que alguém me dê um conselho.
NobbZ
O exemplo foi deste livro: amazon.com/…
Steve H
1
não sei se isso ajuda, mas aqui está um código python que realiza a mesma coisa. moddb.com/mods/wicmw/tutorials/…
Steve H
OK, eu ainda não entendo a matemática dos buracos por trás, mas, para o código python, a documentação me disse que, se houver um valor negativo dentro do sqrt, meu amigo deve demorar para recuperar o atraso. Depois de ajustar meus valores de teste, obtenho alguns resultados. Obrigado pela sua ajuda.
NobbZ
6

Eu sugiro que você analise os comportamentos de direção. Especialmente perseguição . O código-fonte pode ser encontrado na implementação do OpenSteer ou procure um livro como " Programming AI game by example " (ISBN 13: 978-1556220784)

bummzack
fonte
A busca parece precisar de conhecimento sobre o alvo e se encaminha para isso, mas eu realmente não o conheço. Eu sei onde está o inimigo agora, sei a velocidade e a direção. Agora eu quero saber em que direção ele deve ir para interceptar o inimigo a caminho de seu alvo o mais rápido e rápido possível. Como mencionado antes, a aceleração pode ser ignorada a princípio, isso economizaria muito tempo de processamento em comparação com a versão real ... Com o novo modelo, só preciso recalcular quando o inimigo dispara um "evento de mudança de curso", não para todos " hasmoved "-event como eu faço agora.
NobbZ
Sim, o que você descreve é perseguição. Ele não sabe o alvo .. faz uma previsão com base nos "inimigos" actual localização, velocidade e direção
bummzack
Então eu não entendi bem a descrição, vou dar uma olhada mais de perto amanhã.
NobbZ
Acabei de ler o documento há alguns minutos, a busca NÃO é o que estou procurando. É como a minha implementação de fato, exceto que tem como alvo a posição do próximo quadro, ainda tenho que recalcular o novo curso a cada quadro e o curso está resultando em alguma curva. Mas o que eu quero é a linha direta, assumindo que o inimigo não muda a velocidade ou o curso até que ambos se encontrem. Se isso ainda não estiver claro o suficiente, tento desenhar o que quero depois do trabalho. Mas obrigado pelos links de qualquer maneira. Eu acho que posso usar isso em outro lugar do projeto.
NobbZ
@NobbZ Sinto muito, minha resposta não foi útil. Talvez você deva editar sua pergunta de acordo, porque afirmações como: "Eu sei que, em caso de mudança de velocidade ou curso do inimigo, todo cálculo deve ser repetido" pode ser enganoso. Se você fizer isso, acabará tendo o comportamento de direção "perseguição".
21711 bhmzack