Gebogene Bewegung zwischen zwei Punkten


15

Was ist eine gute Technik, um einem Objekt zu ermöglichen, sich in einer schönen, geschwungenen Bewegung zwischen Punkten zu bewegen?

Die Endposition könnte auch in Bewegung sein, beispielsweise die Flugbahn einer Zielsuchrakete.

Antworten:


11

Angenommen, Sie möchten, dass dies Bild für Bild geschieht (wobei sich das Ziel möglicherweise sogar bewegt) und keine vorberechnete Flugbahn, dann ist dies tatsächlich unglaublich einfach:

Vergleichen Sie in jedem Frame den Geschwindigkeitsvektor des Flugkörpers mit dem Vektor (Position Ziel - Position Flugkörper ) . Das heißt, der Vektor zeigt von der Rakete zum Ziel. Jedes Bild, wenn die beiden Vektoren nicht die gleiche Richtung haben, drehen Sie den Geschwindigkeitsvektor ein wenig in Richtung des anderen Vektors, so dass jedes Bild, das die Rakete hat, dem Ziel ein wenig näher kommt.

Sie können bestimmen, ob Sie im oder gegen den Uhrzeigersinn drehen möchten, indem Sie das Vorzeichen des Kreuzprodukts zwischen den beiden Vektoren betrachten.


[Bearbeiten] XNA-ish Code (ich habe kein XNA, um dies zu testen):

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

Beachten Sie, dass aufgrund rotationAngleder drei möglichen Werte alle möglichen Werte von Matrix.CreateRotationZ(rotationAngle)zwischengespeichert werden können, sodass Sie nicht jeden Frame einzeln aufrufen müssen.


Könnten Sie vielleicht einen Pseudocode bereitstellen, da ich in all dem neu bin? Ich arbeite momentan nur in der 2. Dimension, so dass sich einige Komplikationen beseitigen lassen.
Anonymus

@anonymouse: sicher, versuchen Sie dies
BlueRaja - Danny Pflughoeft

15

Es gibt zwei mögliche Techniken:

Die erste Technik besteht darin, eine rahmenbasierte Simulation durchzuführen. Dies ist gut, wenn Sie im Spiel so etwas wie eine Zielsuchrakete machen, die Ihr Ziel nicht genau treffen muss.

In diesem Fall möchten Sie die Position und Geschwindigkeit des Objekts verfolgen. Jeder Frame betrachtet die Richtung zum Ziel und die aktuelle Bewegungsrichtung und passt die Geschwindigkeit entsprechend an.

Wenn Sie die Geschwindigkeit sofort anpassen, trifft Ihre Rakete immer das Ziel. Wenn Sie jedoch die Geschwindigkeit in jedem Frame geringfügig anpassen, wird sich Ihre Rakete in Richtung des Ziels krümmen - und wenn sie sich langsam genug krümmt, kann das Ziel ihr ausweichen.

Die zweite Technik ist die Verwendung einer parametrischen Methode. Dies ist nützlich, um Dinge zu animieren, bei denen Sie Ihr Ziel präzise und vorhersehbar treffen möchten. In diesem Fall nehmen Sie normalerweise "Zeit" als Parameter und ordnen sie einer Funktion zu.

Ein besonders nützlicher Satz von Funktionen sind die Bewegungsgleichungen, die Sie in der Physik des Gymnasiums gelernt haben. Wenn Sie diese auf beide Achsen anwenden, erhalten Sie ballistische Flugbahnen. Mit ein bisschen Mathe können Sie die Anfangsparameter bestimmen, um ein Ziel zu treffen - auch wenn es sich bewegt, wenn es sich vorhersagbar bewegt.

XNA bietet auch eine Reihe von Interpolations- und Kurvenbewegungsfunktionen. Schauen Sie sich die Dokumentation für Vector2 und für anMathHelper . Diese bieten einige Interpolationsfunktionen, die Sie verwenden und sogar kombinieren können, um interessante Dinge zu tun. Zum Beispiel, eine Rakete abfeuern: Lerp(Linear interpolieren) Sie die Position Ihrer Rakete von ihrem Startpunkt zu einer Zielposition, und lerpen Sie diese Zielposition auch von einem Anfangsziel zu der realen (sich ändernden) Position des Zielobjekts. Dies gibt Ihnen einen schönen "Locking-On" -Effekt.

(Es gibt auch einige Funktionen zur Erzeugung von Kurven, zum Beispiel: CatmulRom, Hermite. Dies sind wahrscheinlich schwieriger erfolgreich mit einem beweglichen Ziel zu verwenden, though.)

Wenn Sie sich mit "Beschleunigen" (im Kontext der Animation) befassen, können Sie einige interessantere Interpolationsfunktionen erhalten, die Ihnen interessante Effekte wie die Beschleunigung liefern können.

Nun - Sie können sagen, dass diese Technik einige seltsame Ergebnisse liefert, wenn sich Ihr Ziel bewegt. In der Praxis sieht es jedoch normalerweise gut aus, solange sich Ihr Projektil schneller als Ihr Ziel bewegt. Wenn es ein Problem ist, sollten Sie wahrscheinlich trotzdem eine rahmenbasierte Technik verwenden.


3

Möglicherweise möchten Sie Sinuswellen oder möglicherweise Bézier-Kurven nachschlagen . Ich weiß nicht, ob der Sinus-Ansatz normal ist, aber ich kann nicht verstehen, warum er so schlecht wäre.


Die Verwendung von Bezier-Kurven mit B-Splines ermöglicht eine ziemlich genaue Darstellung jeder Kurve. Wenn Sie Präzision benötigen, sind Cubic Hermit-Splines etwas genauer. Denken Sie daran, dass Ungenauigkeiten manchmal einen willkommenen Hauch von Natürlichkeit bieten.
doppelgreener

+1 für Bezierkurven. Für die beschriebene Verwendung ist es wahrscheinlich die einfachste und am besten kontrollierbare.
ggambett

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.