2D tower defense - Uma bala para um inimigo

14

Estou tentando encontrar uma boa solução para uma bala atingir o inimigo. O jogo é 2D tower defense, a torre deve atirar uma bala e acertar o inimigo garantido.

Eu tentei esta solução - http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-1/

O link mencionado para subtrair a origem da bala e o inimigo também (subtração do vetor). Eu tentei isso, mas uma bala apenas segue em torno do inimigo.

float diffX = enemy.position.x - position.x;
float diffY = enemy.position.y - position.y;

velocity.x = diffX;
velocity.y = diffY;

position.add(velocity.x * deltaTime, velocity.y * deltaTime);

Estou familiarizado com vetores, mas não tenho certeza de quais etapas (operações matemáticas vetoriais) devem ser executadas para obter essa solução funcionando.

Tashu
fonte

Respostas:

11

Seu raciocínio foi perfeito: use um vetor para passar da minha posição para o meu alvo. Esse é o objetivo de um vetor ; você simplesmente esqueceu a velocidade !

A velocidade é um vetor: uma velocidade e uma direção. No entanto, se você esquecer de normalizar o vetor de diferença e multiplicá-lo pela velocidade do marcador (um escalar), estará basicamente dizendo que, se estiver próximo do alvo (o vetor de diferença é pequeno), o marcador diminui ; enquanto que se você estiver longe, a velocidade da bala é maior.

Este é o problema subjacente: você precisa calcular a direção e a magnitude do vetor.

FxIII
fonte
Obrigado por ajudar. Tentei usar escalar depois de calcular o vetor de diferença, parece que funcionou, mas não parece bom. Tentei ver se calculava o vetor de diferença, normalizava e depois escalava a velocidade. Parece melhor agora. Sim, acho que preciso dos mísseis teleguiados neste jogo algum tempo depois. Obrigado novamente.
Tashu 04/07/11
1
Essa resposta não faz sentido para mais ninguém?
BlueRaja - Danny Pflughoeft
@Fxlll: Ok, acho que vejo o que você está tentando dizer. Há muita confusão não relacionada à resposta no início / fim, e eu também fiquei confuso com o seu inglês (o que eu sei que provavelmente não é sua culpa) . Enviei uma sugestão de edição para limpar esta resposta.
BlueRaja - Danny Pflughoeft
@BlueRaja - Danny Pflughoeft obrigado pelo seu esforço!
FxIII
7

Se o alvo estiver se movendo em uma direção constante em um ritmo constante e o caminho da bala estiver em uma linha reta em um ritmo constante, você pode usar uma equação quadrática para prever o ponto exato em que eles cruzarão e apontar a arma da sua torre para esse ponto .

Como é certo que a bala atingirá sua marca e você pode calcular o tempo exato que levará do disparo até o impacto, não será necessária nenhuma detecção de colisão, basta disparar a arma, aguardar o tempo calculado e registrar um acerto.

Aqui está o pseudo-código da equação quadrática:

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
Steve H
fonte
Obrigado pelo pseudo-código, vou ver como a equação quadrática funciona com essa situação. Obrigado novamente.
Tashu 04/07/11
O problema é que o usuário pode estar se movendo em direção à bala e, imediatamente antes da ocorrência, ele pode se afastar do rastreamento da bala. Nesse caso, essa solução seria boa o suficiente?
Martin.
Não, conforme qualificado na primeira frase. Isso não é para todos os jogos, mas para um jogo em que os alvos se movem apenas a uma velocidade constante. Velocidade constante significa direção e velocidade. Por exemplo, o jogo de defesa no estilo Grade de Defesa pode usar essa abordagem.
23712 Steve Steve H
3

Você precisa "prever" a posição dos objetos no momento em que a bala o atingir. Você pode fazer isso usando os objetos speed / speed (espero que seja constante;)) e seu vetor direcional.

Não sei ao certo qual é a fórmula exata, mas acho que é algo assim:

NewPosition = OldPosition + (Speed ​​* DirectionVector);

Se você tiver um caminho definido, será necessário recalcular quando o objeto mudar de direção. Use essa NewPosition como seu vetor enemy.position e o marcador deve atingir o objeto sem o 'efeito de retorno'. O retorno ao local ocorre devido ao fato de o objeto inimigo ter se movido desde que o vetor original foi calculado; ele só pode alcançá-lo quando um objeto estiver viajando em uma direção por tempo suficiente.

Espero que isto ajude :)

Jay
fonte
3
Ou você pode trapacear e acertar automaticamente, e depois usar o sprite em movimento como feedback visual. Ou apenas dispare suas balas a 50000 m².
Jonathan Connell
1

Você pode evitar o uso de raiz quadrada e potência de 2.

var distX:Float = target.x - x;
var distY:Float = target.y - y;
_velX = distX / timeTravel;
_velY = distY / timeTravel;

// Take out if you want a nice slow down as approaches effect.  
timeTravel -= 1.0; // make sure u have a positive timeTravel.
x += _velX;
y += _velY;

if (distX < 0)
    distX = -distX;

if (distY < 0)
    distY = -distY;

if (_velX < 0)
    _velX = -_velX;

if (_velY < 0)
    _velY = -_velY;

// Should both snap @ the same time.
if (distX < _velX)
x = target.x; // snap & see what happens.

if (distY < _velY)
y = target.y; // snap & see what happens.

// TODO: call your onHitTarget here ...
// Hopefully this shall provide 10x the performance 
// of using Math.sqrt and all the extra multiplications.

Está tudo escrito de memória. A propósito, use os elementos que funcionam - teste linha por linha, se você é novo nisso. Flutuar é o número no AS3.

Chris
fonte