Comment calculer l'angle de tir et la vitesse pour toucher une cible en mouvement?

11

Je développe un jeu Android 2D et je fais un algorithme de visée pour que les projectiles AI frappent les ennemis en suivant un chemin ou en se déplaçant librement. Pour le moment, il calcule simplement où la cible sera après une distance et tire un projectile pour la rencontrer à cette distance. Bien sûr, cela signifie faire varier la vitesse du projectile pour atteindre la cible.

Quelqu'un a-t-il des astuces pour un algorithme simple-ish (optimal-ish) pour calculer quand le projectile doit tirer et où il doit viser s'il ne peut se déplacer qu'à une vitesse constante? Disons que le projectile va deux fois plus vite que la cible?

La seule façon dont je peux penser implique la recherche et semble assez grande.

Guen
la source
@JohnMcDonald: pas très lié étant donné qu'il s'agit de projectiles paraboliques, pas linéaire. C'est beaucoup plus proche: gamedev.stackexchange.com/questions/4995/…
e100

Réponses:

13

Dans un jeu de tower defense que j'ai fait, j'ai utilisé une équation quadratique pour prédire l'intersection et donc viser le point. L'extrait de code de visée suivant suppose que l'ennemi se déplace à une vitesse et dans une direction constantes. Cela suppose également que le projectile se déplacera à une vitesse constante connue (pourrait être n'importe quelle vitesse mais doit être connue de l'algorithme).

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

Puisqu'il détermine également le moment de l'impact, j'ai simplement attendu le temps écoulé pour appeler les graphiques d'impact à la position de la cible à ce moment-là ... pas besoin de détection de collision pour déterminer les coups.

Steve H
la source
"pas besoin de détection de collision pour déterminer les coups." - Si la ou les cibles sont contraintes de maintenir leur vitesse et leur direction. --- Si, cependant, ils ont une IA active, ou pire, sont le joueur et sont capables de se déplacer après que le tireur ait tiré, alors baser vos coups sur le temps plutôt que sur la détection de collision conduira à ce que votre base de joueurs percevra comme quelques bugs / pépins désagréables.
XenoRo
@TheLima yup, comme il est dit dans la 2ème phrase de la réponse. ;-)
Steve H
C'est presque parfait pour mon scénario, mais comment prendriez-vous en compte ces 2 variables supplémentaires: l'accélération pour le projectile, le mouvement de la tour elle-même?
Jack
Qu'est-ce que a0? Cela produira une division par exception zéro, mais qu'est-ce que cela signifie en termes de variable t? Doit-il être considéré comme «un très grand nombre» ou quel serait le meilleur cas?
firelynx
Y a-t-il un bon livre qui rentre dans l'intuition derrière cela? Je suis curieux de savoir comment vous avez su rechercher ces mathématiques ...
davidkomer
4

entrez la description de l'image ici

L'IA, l'emplacement de la cible au moment du tir du projectile et l'emplacement éventuel de la cible au moment de la mort forment un triangle. Voici ce que vous devez déjà savoir:

  1. Longueur latérale a, qui est la vitesse du projectile
  2. Longueur latérale b, qui est la vitesse cible
  3. L'angle de mouvement de la cible de mouvement de la cible.

Vous avez trois parties du triangle, un cas SSA, alors résolvez-le comme ceci

  1. Trouver l'angle B en fonction de l'angle de mouvement et de l'emplacement de l'IA
  2. Utilisez la loi des sinus pour trouver l'angle A

L'angle A doit vous permettre de déterminer l'angle auquel le projectile doit être lancé.

tyjkenn
la source