2D tower defense: una bala para un enemigo

14

Estoy tratando de encontrar una buena solución para que una bala golpee al enemigo. El juego es la defensa de la torre 2D, se supone que la torre dispara una bala y golpea al enemigo garantizado.

Probé esta solución: http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-1/

El enlace mencionado para restar el origen de la bala y el enemigo también (resta de vectores). Lo intenté pero una bala sigue al enemigo.

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);

Estoy familiarizado con los vectores, pero no estoy seguro de qué pasos (operaciones matemáticas de vectores) se deben realizar para que esta solución funcione.

Tashu
fuente

Respuestas:

11

Su razonamiento fue perfecto: use un vector para moverse de mi posición a mi objetivo. Este es el propósito de un vector ; ¡simplemente olvidaste la velocidad !

La velocidad es un vector: una velocidad y una dirección. Sin embargo, si olvida normalizar el vector de diferencia y multiplicarlo por la velocidad de la bala (un escalar), básicamente está diciendo que si está cerca del objetivo (el vector de diferencia es pequeño) la bala se ralentiza ; mientras que si estás lejos, la velocidad de la bala es mayor.

Este es el problema subyacente: necesita calcular tanto la dirección como la magnitud del vector.

FxIII
fuente
Gracias por ayudar. Intenté usar el escalar después de calcular el vector de diferencia, parece que funcionó pero no se ve bien. Traté de ver si calculo el vector de diferencia, normalizo, luego escalar la velocidad. Se ve mejor en este momento. Sí, creo que necesito los misiles guiados en este juego algún tiempo después. Gracias de nuevo.
Tashu
1
¿Esta respuesta no tiene sentido para nadie más?
BlueRaja - Danny Pflughoeft
@Fxlll: Ok, creo que veo lo que estás tratando de decir. Hay un montón de cosas sin relación con la respuesta al principio / al final, y su inglés también me confundió (lo que me doy cuenta es que probablemente no es su culpa) . He enviado una sugerencia de edición para limpiar esta respuesta.
BlueRaja - Danny Pflughoeft
@BlueRaja - Danny Pflughoeft gracias por tu esfuerzo!
FxIII
7

Si el objetivo se mueve en una dirección constante a un ritmo constante, y su trayectoria de bala está en línea recta a un ritmo constante, puede usar una ecuación cuadrática para predecir el punto exacto en el que se cruzarán y apuntar el arma de su torre hacia ese punto .

Dado que es seguro que la bala alcanzará su marca, y puede calcular el tiempo exacto que tomará desde el disparo hasta el impacto, no se requerirá detección de colisión, simplemente dispare el arma, espere el lapso de tiempo calculado, registre un golpe.

Aquí hay un pseudocódigo para la ecuación cuadrá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
fuente
Gracias por el pseudocódigo, lo comprobaré para ver cómo funciona la ecuación cuadrática con esta situación. Gracias de nuevo.
Tashu
El problema es que el usuario puede moverse hacia la bala y justo antes del golpe, puede alejarse del rastro de la bala. En este caso, ¿sería esta solución lo suficientemente buena?
Martin.
No, según lo calificado en la primera oración. Esto no es para todos los juegos, sino para un juego donde los objetivos se mueven a una velocidad constante solamente. Velocidad constante significa dirección y velocidad. Por ejemplo, el juego de estilo de defensa Grid puede usar este enfoque.
Steve H
3

Debe 'predecir' la posición de los objetos para cuando la bala lo alcance. Puede hacer esto usando la velocidad / velocidad de los objetos (es de esperar que sea constante;)) y su vector direccional.

No estoy seguro de cuál es la fórmula exacta de mi cabeza, pero creo que es algo como esto:

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

Si tiene una ruta establecida, deberá volver a calcular cuando el objeto cambie de dirección. Use esta nueva posición como su vector de posición enemiga y la bala debería golpear el objeto sin el 'efecto de referencia'. El recorrido de referencia se produce debido al hecho de que el objeto enemigo se ha movido desde que se calculó el vector original, solo puede alcanzarlo cuando un objeto viaja en una dirección el tiempo suficiente.

Espero que esto ayude :)

Arrendajo
fuente
3
O puede hacer trampa y golpear automáticamente, luego usar el sprite en movimiento como retroalimentación visual. O simplemente dispara tus balas a 50000² mph.
Jonathan Connell el
1

Puede evitar el uso de raíz cuadrada y potencia 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.

Todo está escrito de memoria. Por cierto, usa los elementos que funcionan: pruébalo línea por línea si eres nuevo en esto. Float es Number en AS3.

Chris
fuente