Passare da A (x, y) a B (x1, y1) a velocità costante?


21

Al momento ho qualcosa come:

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

E ogni 0,01 secondi aggiorno la posizione dei miei oggetti in questo modo:

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

Quindi questo sposta il mio oggetto da punto0 a punto1 in 1 secondo. Ciò di cui ho bisogno è avere i 2 punti, per poter spostare l'oggetto dal punto 0, affrontando (nella direzione di) il punto 1 con una velocità costante. Pertanto, quando ho un punto più vicino al mio punto iniziale, l'oggetto si sposterà verso di esso con la stessa velocità che avrebbe se avessi un punto più lontano. Eventuali suggerimenti sono apprezzati. Grazie.


Possibile duplicato: gamedev.stackexchange.com/questions/23430/… Pubblicherei la stessa risposta che ho dato all'altra domanda. Ma questo sarebbe vergognoso da parte mia.
Gustavo Maciel,

Risposte:


26

Userò alcune strutture di algebra lineare poiché è più facile descrivere le operazioni in quel modo. Se non sai come implementare queste operazioni vettoriali, alla fine ti darò una rapida spiegazione.

Quindi supponiamo che inizi con questi valori: starte endsegna i punti finali del movimento, speedquanti pixel dovrebbe spostare al secondo, ed elapsedè la velocità con cui aggiornerai la posizione del tuo oggetto (alcuni motori forniscono già quel valore per te ):

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

La prima cosa che vorrai calcolare è la distanza tra entrambi i punti e un vettore normalizzato contenente la direzione dall'inizio alla fine. Inoltre, è necessario "agganciare" la posizione dell'oggetto al startpunto. Questo passaggio viene eseguito una sola volta, all'inizio:

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

Poi sul vostro metodo di aggiornamento, si sposta l'oggetto con l'aggiunta di una moltiplicazione di direction, speede elapsedper la sua posizione. Successivamente, per verificare se il movimento è terminato, vedi se la distanza tra il punto iniziale e la posizione corrente dell'oggetto è maggiore della distanza iniziale calcolata. Se questo è vero, agganciamo la posizione dell'oggetto al punto finale e smettiamo di spostare l'oggetto:

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

Riferimento rapido alle operazioni vettoriali

Rappresentazione

Vector2 A = float aX, aY;

Somma / Sottrai

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

Moltiplica per scalare (float)

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

Lunghezza / Distanza

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

Normalizzare

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

Questo dovrebbe essere sufficiente per convertire il codice sopra in normali operazioni se non hai una Vectorclasse a tua disposizione.


Esempio di conversione

// 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;
    }
}

1
@Fofole Ecco perché alla fine ho dato la spiegazione dei vettori. La risposta doveva essere generica. Se non hai una classe Vector, usa due float separati. Ad esempio Vector2 start;diventa float startX, startY;. E puoi facilmente calcolare manualmente la distanza, come spiego alla fine. Vale a dire float dX = bX - aX; float dY = bY - aY; float distance = Math.sqrt(dx*dx+dy*dy);.
David Gouveia,

@Fafole Controlla la modifica, ho aggiunto un esempio. Non sono sicuro di aver perso qualcosa però.
David Gouveia,

3 anni dopo e mi hai fatto capire come muovere gli oggetti con i vettori. Saluti!
Oliver Schöning,

3

Crea un vettore e normalizzalo. Attenzione, alcuni pseudo-codici con numeri sbagliati in anticipo:

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

Questo ti darà un vettore come:

25.96; 85.41

Ora normalizza il vettore e riceverai questo :

0.12; 0.75

Da qui è lo stesso movimento del tuo delta.


2

Copiato e incollato dalla mia risposta a: Ottieni punti su una linea tra due punti

In Pseudocodice:

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
}

Questa risposta ha funzionato meglio per il mio caso d'uso.
shell
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.