¿Pasando de A (x, y) a B (x1, y1) con velocidad constante?

21

Actualmente tengo algo como:

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

Y cada 0.01 segundos actualizo la posición de mis objetos de esta manera:

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

Entonces esto mueve mi objeto del punto 0 al punto 1 en 1 segundo. Lo que necesito es tener los 2 puntos, para poder mover el objeto desde el punto 0, mirando (en la dirección de) punto 1 con una velocidad constante. Por lo tanto, cuando tengo un punto más cercano a mi punto inicial, el objeto se moverá hacia él con la misma velocidad que si tuviera un punto más alejado. Cualquier sugerencia es apreciada. Gracias.

Fofole
fuente
Posible duplicado: gamedev.stackexchange.com/questions/23430/… Publicaría la misma respuesta que di a la otra pregunta. Pero esto sería desvergonzado de mi parte.
Gustavo Maciel

Respuestas:

26

Usaré algunas estructuras de álgebra lineal, ya que es más fácil describir las operaciones de esa manera. En caso de que no sepa cómo implementar estas operaciones vectoriales, le daré una explicación rápida al final.

Entonces, digamos que comienza con estos valores: starty endmarca los puntos finales del movimiento, speedes cuántos píxeles debe mover por segundo y elapsedes la velocidad a la que actualizará la posición de su objeto (algunos motores ya le proporcionan ese valor ):

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

Lo primero que querrá calcular es la distancia entre ambos puntos y un vector normalizado que contiene la dirección de principio a fin. Además, debe "ajustar" la posición del objeto al startpunto. Este paso se realiza solo una vez, al principio:

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

Luego de su método de actualización se pasa el objeto mediante la adición de una multiplicación de direction, speedy elapseden su posición. Después de eso, para verificar si el movimiento ha terminado, puede ver si la distancia entre el punto inicial y la posición actual del objeto es mayor que la distancia inicial que calculó. Si eso es cierto, ajustamos la posición del objeto al punto final y dejamos de moverlo:

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

Referencia rápida de operaciones vectoriales

Representación

Vector2 A = float aX, aY;

Suma / Resta

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

Multiplicar por escalar (flotante)

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

Longitud / distancia

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

Normalizar

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

Eso debería ser suficiente para convertir el código anterior en operaciones regulares si no tiene una Vectorclase disponible para usted.


Ejemplo de conversión

// 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
fuente
1
@Fofole Por eso di la explicación sobre los vectores al final. Se suponía que la respuesta era genérica. Si no tiene una clase de Vector, use dos flotadores separados. Por ejemplo se Vector2 start;convierte float startX, startY;. Y puede calcular fácilmente la distancia manualmente, como explico al final. Es decir float dX = bX - aX; float dY = bY - aY; float distance = Math.sqrt(dx*dx+dy*dy);.
David Gouveia
@Fafole Compruebe la edición, agregué un ejemplo. Aunque no estoy seguro si me perdí algo.
David Gouveia
3 años después y me hiciste entender cómo mover objetos con vectores. ¡Salud!
Oliver Schöning
3

Crea un vector y normalízalo. Advertencia, algunos pseudocódigos con números incorrectos por delante:

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

Esto le dará un vector como:

25.96; 85.41

Ahora normalice el vector y recibirá esto :

0.12; 0.75

Desde aquí es el mismo movimiento que con tu delta.

Poli
fuente
2

Copiado y pegado de mi respuesta a: Obtener puntos en una línea entre dos puntos

En pseudocódigo:

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
fuente
Esta respuesta funcionó mejor para mi caso de uso.
Shell