Przechodzisz z A (x, y) do B (x1, y1) ze stałą prędkością?

21

Obecnie mam coś takiego:

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

I co 0,01 sekundy odświeżam moje obiekty w następujący sposób:

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

To przenosi mój obiekt z punktu 0 do punktu 1 w ciągu 1 sekundy. Potrzebuję 2 punktów, aby móc przesuwać obiekt z punktu 0, skierowany w stronę punktu 1 ze stałą prędkością. Tak więc, kiedy mam punkt bliższy mojego punktu początkowego, obiekt przesunie się w jego kierunku z taką samą prędkością, jak wtedy, gdybym miał dalszy punkt. Wszelkie sugestie są mile widziane. Dzięki.

Fofole
źródło
Możliwy duplikat: gamedev.stackexchange.com/questions/23430 /... Zamieszczę tę samą odpowiedź, której udzieliłem na inne pytanie. Ale byłoby to z mojej strony bezwstydne.
Gustavo Maciel

Odpowiedzi:

26

Użyję struktur algebry liniowej, ponieważ łatwiej jest opisać operacje w ten sposób. Jeśli nie wiesz, jak zaimplementować te operacje wektorowe, na końcu udzielę krótkiego wyjaśnienia.

Powiedzmy, że zaczynasz od tych wartości: starti endzaznacz punkty końcowe ruchu, speedliczbę pikseli, o jaką powinien się poruszać na sekundę, i elapsedszybkość, z jaką zaktualizujesz pozycję obiektu (niektóre silniki już zapewniają tę wartość dla Ciebie ):

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

Pierwszą rzeczą, którą chcesz obliczyć, jest odległość między dwoma punktami i znormalizowany wektor zawierający kierunek od początku do końca. Ponadto należy „przyciągnąć” pozycję obiektu do startpunktu. Ten krok jest wykonywany tylko raz, na początku:

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

Następnie na metodę aktualizacji, możesz przesunąć obiekt dodając mnożenia direction, speeda elapsedna jego miejscu. Następnie, aby sprawdzić, czy ruch się skończył, zobaczysz, czy odległość między punktem początkowym a bieżącą pozycją obiektu jest większa niż obliczona początkowa odległość. Jeśli to prawda, przyciągamy pozycję obiektu do punktu końcowego i przestajemy przenosić obiekt:

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

Skrócone informacje o operacjach wektorowych

Reprezentacja

Vector2 A = float aX, aY;

Suma / Odejmij

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

Pomnóż przez skalar (liczba zmiennoprzecinkowa)

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

Długość / odległość

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

Normalizować

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

To powinno wystarczyć do konwersji powyższego kodu w zwykłe operacje, jeśli nie masz Vectordostępnej klasy.


Przykład konwersji

// 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
źródło
1
@Fofole Dlatego na końcu podałem wyjaśnienie dotyczące wektorów. Odpowiedź miała być ogólna. Jeśli nie masz klasy Vector, użyj dwóch oddzielnych liczb zmiennoprzecinkowych. Na przykład Vector2 start;staje się float startX, startY;. Możesz łatwo obliczyć odległość ręcznie, jak wyjaśnię na końcu. Tj float dX = bX - aX; float dY = bY - aY; float distance = Math.sqrt(dx*dx+dy*dy);.
David Gouveia,
@Fafole Sprawdź edycję, dodałem przykład. Nie jestem pewien, czy coś przeoczyłem.
David Gouveia,
3 lata później i właśnie zrozumiałeś, jak przenosić obiekty za pomocą wektorów. Twoje zdrowie!
Oliver Schöning
3

Utwórz wektor i znormalizuj go. Ostrzeżenie, przed nami jakiś pseudo-kod z niewłaściwymi numerami:

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

Otrzymasz wektor typu:

25.96; 85.41

Teraz znormalizuj wektor, a otrzymasz :

0.12; 0.75

Odtąd jest to ten sam ruch, co w twojej delcie.

Konstabl
źródło
2

Skopiowałem i wkleiłem z mojej odpowiedzi na: Zdobądź punkty na linii między dwoma punktami

W pseudokodzie:

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
źródło
Ta odpowiedź działała najlepiej w moim przypadku użycia.
shell