Mouvement courbe entre deux points

15

Quelle est la bonne technique pour permettre à un objet de se déplacer entre des points dans un joli mouvement courbe?

La position finale pourrait également être en mouvement, comme la trajectoire d'un missile à tête chercheuse.

anonymouse
la source

Réponses:

11

En supposant que vous vouliez que ce soit une image par image (où la cible pourrait même se déplacer), et non une trajectoire précalculée, c'est en fait incroyablement simple:

À chaque trame, comparez le vecteur vitesse du missile au vecteur (position cible - position missile ) ; c'est-à-dire le vecteur pointant du missile vers la cible. Chaque image, si les deux vecteurs n'ont pas la même direction, faites pivoter un peu le vecteur de vitesse vers l'autre vecteur, de sorte que chaque image du missile se rapproche un peu plus de sa cible.

Vous pouvez déterminer s'il faut tourner dans le sens horaire ou antihoraire en regardant le signe du produit croisé entre les deux vecteurs.


[Modifier] Code XNA-ish (je n'ai pas XNA pour tester cela):

//Once a frame:

//Get vector spanning from missile to target
Vector2 vectorToTarget = target.Position - missile.Position;

//Convert to Vector3 to do cross-product
Vector3 vectorToTarget3 = new Vector3(vectorToTarget, 0);
Vector3 missileVelocity3 = new Vector3(missile.Velocity, 0);

//Rotate clockwise/counter-clockwise is determined by sign of cross-product
int crossProductSign = Vector3.Cross(missileVelocity3, vectorToTarget3).Z;

//Positive cross-product means rotate counter-clockwise, negative is clockwise
double rotationAngle = 0;
if(crossProductSign > 0)
    rotationAngle = -0.05;
else if(crossProductSign < 0)
    rotationAngle = 0.05;

//I'm not sure how to do rotation in XNA, but the internets tell me it's something like this:
missile.velocity = Vector2.Transform(missile.velocity, Matrix.CreateRotationZ(rotationAngle))

Notez que, comme il rotationAnglen'a que trois valeurs possibles, toutes les valeurs possibles de Matrix.CreateRotationZ(rotationAngle)peuvent être mises en cache afin que vous n'ayez pas à l'appeler à chaque image.

BlueRaja - Danny Pflughoeft
la source
Pourriez-vous peut-être fournir un pseudo-code, car je suis nouveau dans tout cela. Je ne travaille actuellement que dans la 2ème dimension ce qui supprime certaines complications.
anonymouse
@anonymouse: bien sûr, essayez ceci
BlueRaja - Danny Pflughoeft
15

Il existe deux techniques possibles:

La première technique consiste à faire une simulation basée sur des trames . C'est bien si vous faites quelque chose comme un missile à tête chercheuse dans le gameplay, qui ne doit pas toucher votre cible exactement.

Dans ce cas, vous souhaitez suivre la position et la vitesse de l'objet. Chaque image regarde la direction de la cible et la direction actuelle du mouvement et ajuste la vitesse de manière appropriée.

Si vous accélérez instantanément la vitesse, votre missile atteindra toujours la cible. Mais si vous ajustez la vitesse d'une petite quantité à chaque image, votre missile se courbera vers la cible - et s'il se courbe assez lentement, la cible pourrait l'esquiver.

La deuxième technique consiste à utiliser un paramétrique méthode . Ceci est utile pour animer des choses où vous voulez toucher votre cible avec précision et prévisibilité. Dans ce cas, vous prenez généralement le «temps» comme paramètre et le mettez dans une fonction quelconque.

Un ensemble de fonctions particulièrement utiles sont les équations du mouvement vous avez apprises en physique au lycée. En les appliquant aux deux axes, vous pouvez obtenir des trajectoires balistiques. Avec un peu de mathématiques, vous pouvez déterminer les paramètres initiaux pour atteindre une cible - même mobile, si elle se déplace de façon prévisible.

XNA fournit également un certain nombre de fonctions d'interpolation et de mouvement incurvé. Jetez un œil à la documentation pour Vector2 et pourMathHelper . Ceux-ci fournissent des fonctions d'interpolation que vous pouvez utiliser et même combiner pour faire des choses intéressantes. Par exemple, tirer un missile:Lerp (interpolation linéaire) la position de votre missile de son point de départ à une position cible, et également lerp cette position cible d'une cible initiale à la position réelle (changeante) de l'objet cible. Cela vous donnera un bel effet de "verrouillage".

(Il existe également certaines fonctions pour produire des courbes, par exemple: CatmulRom, Hermite. Elles sont probablement plus difficiles à utiliser avec succès avec une cible en mouvement, cependant.)

Si vous vous penchez sur "l'assouplissement" (dans le contexte de l'animation), vous pouvez obtenir des fonctions d'interpolation plus intéressantes qui peuvent vous donner des effets intéressants comme l'accélération.

Maintenant, vous pouvez dire que cette technique donne des résultats étranges lorsque votre cible se déplace. Cependant, dans la pratique, tant que votre projectile se déplace plus vite que votre cible, il semble généralement bien. Si c'est un problème, vous devriez probablement utiliser une technique basée sur le cadre de toute façon.

Andrew Russell
la source
3

Vous pouvez rechercher des ondes sinusoïdales ou éventuellement des courbes de Bézier . Je ne sais pas si l'approche à onde sinusoïdale est normale, mais je ne vois pas pourquoi elle serait si mauvaise.

Le canard communiste
la source
L'utilisation de courbes de Bézier avec des B-Splines permet une représentation assez précise de n'importe quelle courbe. Si vous avez besoin de précision, les splines Cubic Hermit sont légèrement plus précises. Gardez à l'esprit, parfois l'inexactitude fournit une touche bienvenue de bio.
doppelgreener
+1 pour les courbes de Bézier. Pour l'usage décrit, c'est probablement le plus simple et le plus contrôlable.
ggambett
1

Vous pouvez jeter un œil aux comportements de pilotage, tels que définis par Craig Reynolds: http://red3d.com/cwr/steer/

Ceci est souvent utilisé dans l'IA pour faire avancer les PNJ vers leur cible.

emartel
la source