Bewegen Sie sich mit konstanter Geschwindigkeit von A (x, y) nach B (x1, y1)?

21

Ich habe derzeit etwas wie:

float deltaX = point0.getX() - point1.getX();
float deltaY = point0.getY() - point1.getY();

Und alle 0,01 Sekunden aktualisiere ich meine Objektposition wie folgt:

object.setPosition(object.getX()-deltaX/100,object.getY()-deltaY/100);

Das verschiebt mein Objekt in 1 Sekunde von Punkt 0 nach Punkt 1. Was ich brauche ist, die 2 Punkte zu haben, um das Objekt von Punkt 0 in Richtung Punkt 1 mit konstanter Geschwindigkeit bewegen zu können. Wenn ich also einen Punkt näher an meinem Anfangspunkt habe, bewegt sich das Objekt mit der gleichen Geschwindigkeit darauf zu, wie wenn ich einen weiteren Punkt hätte. Anregungen sind willkommen. Vielen Dank.

Fofole
quelle
Mögliches Duplikat: gamedev.stackexchange.com/questions/23430/… Ich würde die gleiche Antwort posten, die ich auf die andere Frage gegeben habe. Aber das wäre meinerseits schamlos.
Gustavo Maciel

Antworten:

26

Ich werde einige lineare Algebra-Strukturen verwenden, da es einfacher ist, die Operationen auf diese Weise zu beschreiben. Falls Sie nicht wissen, wie Sie diese Vektoroperationen implementieren sollen, werde ich am Ende eine kurze Erklärung geben.

Angenommen, Sie beginnen mit diesen Werten: startund endmarkieren die Endpunkte der Bewegung, geben an, speedum wie viele Pixel sie sich elapsedpro Sekunde bewegen soll, und wie schnell Sie die Position Ihres Objekts aktualisieren (einige Engines stellen diesen Wert bereits für Sie bereit) ):

Vector2 start = new Vector2(x1, y2);
Vector2 end = new Vector2(x2, y2);
float speed = 100;
float elapsed = 0.01f;

Das erste, was Sie berechnen möchten, ist der Abstand zwischen beiden Punkten und ein normalisierter Vektor, der die Richtung vom Anfang bis zum Ende enthält. Außerdem sollten Sie die Objektposition auf den startPunkt "einrasten" . Dieser Schritt wird zu Beginn nur einmal ausgeführt:

float distance = Vector2.Distance(start, end);
Vector2 direction = Vector2.Normalize(end - start);
object.Position = start;
moving = true;

Dann auf dem Update - Methode, bewegen Sie das Objekt durch Hinzufügen einer Multiplikation direction, speedund elapsedzu seiner Position. Anschließend können Sie überprüfen, ob die Bewegung beendet ist und ob der Abstand zwischen dem Startpunkt und der aktuellen Position des Objekts größer ist als der ursprünglich berechnete Abstand. Wenn dies zutrifft, fangen wir die Position des Objekts am Endpunkt und stoppen das Verschieben des Objekts:

if(moving == true)
{
    object.Position += direction * speed * elapsed;
    if(Vector2.Distance(start, object.Position) >= distance)
    {
        object.Position = end;
        moving = false;
    }
}

Schnelle Referenz für Vektoroperationen

Darstellung

Vector2 A = float aX, aY;

Summe / Subtrahieren

A+B = a.x + b.x; a.y + b.y;
A-B = a.x - b.x; a.y - b.y;

Mit Skalar multiplizieren (float)

A*float = a.x*float; a.y*float;

Länge / Distanz

length(A) = sqrt(a.x*a.x + a.y*a.y)
distance(A,B) = length(B-A)

Normalisieren

normalize(A) = a.X/length(A); a.Y/length(A);

Das sollte ausreichen, um den obigen Code in reguläre Operationen umzuwandeln, wenn Ihnen keine VectorKlasse zur Verfügung steht.


Beispiel für die Konvertierung

// Your Variables
float startX, startY, endX, endY;
float speed = 100;
float elapsed = 0.01f;

// On starting movement
float distance = Math.sqrt(Math.pow(endX-startX,2)+Math.pow(endY-startY,2));
float directionX = (endX-startX) / distance;
float directionY = (endY-startY) / distance;
object.X = startX;
object.Y = startY;
moving = true;

// On update
if(moving == true)
{
    object.X += directionX * speed * elapsed;
    object.Y += directionY * speed * elapsed;
    if(Math.sqrt(Math.pow(object.X-startX,2)+Math.pow(object.Y-startY,2)) >= distance)
    {
        object.X = endX;
        object.Y = endY;
        moving = false;
    }
}
David Gouveia
quelle
1
@Fofole Deshalb habe ich am Ende die Erklärung zu Vektoren gegeben. Die Antwort sollte allgemein sein. Wenn Sie keine Vector-Klasse haben, verwenden Sie zwei separate Floats. Zum Beispiel Vector2 start;wird float startX, startY;. Und Sie können den Abstand leicht manuell berechnen, wie ich am Ende erkläre. D. h float dX = bX - aX; float dY = bY - aY; float distance = Math.sqrt(dx*dx+dy*dy);.
David Gouveia
@Fafole Überprüfe die Bearbeitung, ich habe ein Beispiel hinzugefügt. Ich bin mir nicht sicher, ob ich etwas verpasst habe.
David Gouveia
3 Jahre später haben Sie mir nur gezeigt, wie man Objekte mit Vektoren bewegt. Prost!
Oliver Schöning
3

Erstellen Sie einen Vektor und normalisieren Sie ihn. Achtung, ein Pseudocode mit falschen Zahlen voraus:

Vector = new Vector(point0.getX() - point1.getX(), point0.getY() - point1.getY());

Dies gibt Ihnen einen Vektor wie:

25.96; 85.41

Nun normalisiere den Vektor und du erhältst folgendes :

0.12; 0.75

Von hier aus ist es die gleiche Bewegung wie mit Ihrem Delta.

Bobby
quelle
2

Kopiert und eingefügt von meiner Antwort an: Punkte auf einer Linie zwischen zwei Punkten erhalten

Im Pseudocode:

speed_per_tick = 0.05 //constant speed you want the object to move at
delta_x = x_goal - x_current
delta_y = y_goal - y_current
goal_dist = sqrt( (delta_x * delta_x) + (delta_y * delta_y) )
if (dist > speed_per_tick)
{
    ratio = speed_per_tick / goal_dist
    x_move = ratio * delta_x  
    y_move = ratio * delta_y
    new_x_pos = x_move + x_current  
    new_y_pos = y_move + y_current
}
else
{
    new_x_pos = x_goal 
    new_y_pos = y_goal
}
Tristan
quelle
Diese Antwort hat für meinen Anwendungsfall am besten funktioniert.
Shell