Comment calculer le vecteur d'une interception?

11

Étant donné un espace bidimensionnel et 1 vaisseau spatial ami immobile, un ennemi ne se déplace PAS directement vers le navire ami avec la position, la vitesse et la direction réelles connues.

Le vaisseau ami veut se mettre à portée de tir pour combattre l'ennemi.

En fait, je ne fixe qu'un vecteur direct à la position réelle du navire en mouvement et je le recalcule à chaque image, ce qui donne une sorte de trajectoire de vol "ronde".

Ce que je veux, c'est définir une trajectoire directe et directe vers la position que l'ennemi aura (vraisemblablement) aura lorsque la distance de tir sera atteinte, en supposant que l'ennemi ne changera pas de cap jusque-là.

En tant que première et "simple" mise en œuvre, il suffirait de supposer que l'ami peut passer de 0 à max en un rien de temps.

La mise en œuvre préférée serait celle qui prend en compte les capacités d'accélération de l'ami et sait quand l'interception est impossible en raison de la vitesse. Cela devrait fonctionner pour chaque vitesse de démarrage, pas seulement à l'arrêt. Un plus serait s'il considère même le freinage (se battre à la vitesse de la lumière est très inefficace sur le plan énergétique dans l'univers donné)

NobbZ
la source

Réponses:

5

Si je comprends votre question, vous ne voulez pas que le navire se dirige vers la cible, mais plutôt qu'il vole en ligne droite qui arrive à intercepter la cible. Je fais un jeu de tower defense qui a fondamentalement le même besoin pour une balle de tour, une tour veut tirer un pistolet de telle sorte que la balle intercepte une cible en mouvement tant qu'elle ne change pas de vitesse / direction. J'ai résolu le problème en utilisant une équation quadratique. Voici un pseudo code:

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

J'ai trouvé que cela fonctionnait si bien que je n'avais pas besoin de détection de collision pour le tir ... Je pouvais compter sur chaque tir frappant une cible, quelle que soit la distance / direction / vitesse de la cible tant que ces facteurs restaient stables.

Steve H
la source
D'après votre description, cela semble être ce que je recherche, du moins la manière la plus simple en supposant une accélération instantanée jusqu'à la vitesse maximale. Je vais y regarder de plus près dans la soirée. Suis-je en supposant que Vector.Dot retourne le produit dot des vecteurs?
NobbZ
Hmmm ... J'ai fait ça en rubis maintenant, mais il semble que quelque chose ne va pas. Chaque fois que j'essaye, il y a une exception levée, car l'expression dans le sqrt est évaluée comme quelque chose de négatif et est donc hors limites. Comment puis-je gérer cela. Désolé pour la question, mais je ne peux que l'utiliser, mais ne comprends pas les concepts ici jusqu'à ce que quelqu'un me donne un conseil.
NobbZ
L'exemple provient de ce livre: amazon.com/…
Steve H
1
Je ne sais pas si cela aide, mais voici du code Python qui accomplit la même chose. moddb.com/mods/wicmw/tutorials/…
Steve H
OK, je ne comprends toujours pas les mathématiques des trous derrière, mais thx pour le code python, la documentation m'a dit que s'il y a une valeur négative à l'intérieur du sqrt, alors mon ami doit ralentir pour rattraper son retard. Après avoir modifié mes valeurs de test, j'obtiens des résultats. Merci pour votre aide.
NobbZ
6

Je vous suggère d'examiner les comportements de pilotage. Surtout la poursuite . Le code source peut être trouvé dans l' implémentation d' OpenSteer ou rechercher un livre comme " Programmation du jeu AI par exemple " (ISBN 13: 978-1556220784)

bummzack
la source
la poursuite semble avoir besoin de connaissances sur la cible et s'oriente vers cela, mais je ne connais pas vraiment la cible. Je sais où est l'ennemi maintenant, je connais sa vitesse et sa direction. Maintenant, je veux savoir dans quelle direction il doit aller pour intercepter l'ennemi sur son chemin vers sa cible le plus rapidement et le plus possible. Comme mentionné précédemment, l'accélération peut être ignorée au début, cela permettrait même d'économiser beaucoup de temps de traitement par rapport à la version réelle ... Avec le nouveau modèle, je dois recalculer uniquement lorsque l'ennemi déclenche un événement "coursechange", pas pour chaque " hasmoved "-event comme je le fais maintenant.
NobbZ
Oui, ce que vous décrivez est une poursuite. Il ne connaît pas la cible .. il fait une prédiction basée sur l'emplacement, la vitesse et la direction actuels des "ennemis"
bummzack
Ensuite, j'ai mal compris la description, je vais y regarder de plus près demain.
NobbZ
Je viens de terminer la lecture du document il y a quelques minutes, la poursuite n'est PAS ce que je recherche. C'est comme ma mise en œuvre réelle, sauf qu'elle cible la position de la trame suivante, je dois encore recalculer le nouveau cours à chaque trame et le cours donne une courbe. Mais ce que je veux, c'est la ligne directe en supposant que l'ennemi ne change pas de vitesse ou de cap jusqu'à ce que les deux se rencontrent. Si ce n'est pas encore assez clair, j'essaie de dessiner ce que je veux après le travail. Mais merci pour les liens quand même. Je pense que je peux l'utiliser ailleurs dans le projet.
NobbZ
@NobbZ Je suis désolé, ma réponse n'a pas été utile. Vous devriez peut-être modifier votre question en conséquence, car des déclarations comme: "Je sais qu'en cas de changement de vitesse ou de cap de l'ennemi, chaque calcul doit être répété" peut être trompeuse .. si vous le faites, vous finirez par avoir le comportement de direction "poursuite".
bummzack