Sabit hızda A (x, y) 'den B (x1, y1)' e geçiş?


21

Şu anda böyle bir şey var:

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

Ve her 0.01 saniyede bir nesnelerimi şu şekilde yenileyiyorum:

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

Bu, nesneyi 1 saniyede point0'dan point1'e taşır. İhtiyacım olan şey 2 noktaya sahip, nesneyi nokta0'dan sabit bir hızla nokta1'e (yönünde) bakabilmek. Böylece, başlangıç ​​noktama daha yakın bir noktaya sahip olduğumda, nesne, daha uzak bir noktaya sahip olsaydım aynı hızda ona doğru hareket edecektir. Herhangi bir öneriniz için teşekkür ederiz. Teşekkürler.


Olası yinelenen: gamedev.stackexchange.com/questions/23430/… Ben diğer soruya verdiğim yanıtı gönderirim. Ama bu benim açımdan utanmazdı.
Gustavo Maciel

Yanıtlar:


26

İşlemleri bu şekilde tanımlamak daha kolay olduğu için bazı lineer cebir yapılarını kullanacağım. Bu vektör işlemlerini nasıl uygulayacağınızı bilmiyorsanız, sonunda hızlı bir açıklama yapacağım.

Diyelim ki bu değerlerle başlıyorsunuz: startve endhareketin bitiş noktalarını işaretleyin, speedsaniyede kaç piksel hareket etmesi gerektiğini ve elapsednesnenizin konumunu güncelleme hızıdır (bazı motorlar zaten sizin için bu değeri sağlar) ):

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

Hesaplamak isteyeceğiniz ilk şey, her iki nokta arasındaki mesafedir ve baştan sona yönü içeren normalleştirilmiş bir vektördür. Ayrıca, nesne konumunu startnoktaya "tutturmalısınız" . Bu adım başlangıçta sadece bir kez yapılır:

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

Daha sonra güncelleme yönteminizde direction, speedve öğesinin çarpımını ekleyerek nesneyi taşırsınız elapsed. Bundan sonra, hareketin bittiğini kontrol etmek için, başlangıç ​​noktası ile nesnenin mevcut konumu arasındaki mesafenin hesapladığınız başlangıç ​​mesafesinden daha büyük olup olmadığını görürsünüz. Bu doğruysa, nesnenin konumunu bitiş noktasına yaslar ve nesneyi hareket ettirmeyi durdururuz:

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

Hızlı Vektör İşlemleri Referansı

temsil

Vector2 A = float aX, aY;

Toplam / Çıkarma

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

Skaler ile çarp (float)

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

Uzunluk / Mesafe

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

Normale

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

VectorKullanabileceğiniz bir sınıfınız yoksa, yukarıdaki kodu normal işlemlere dönüştürmek için yeterli olmalıdır .


Dönüşüm Örneği

// 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 Bu yüzden sonunda vektörler hakkında açıklama yaptım. Cevabın jenerik olması gerekiyordu. Vector sınıfınız yoksa, iki ayrı şamandıra kullanın. Mesela Vector2 start;olur float startX, startY;. Ve sonunda açıkladığım gibi mesafeyi manuel olarak kolayca hesaplayabilirsiniz. Yani float dX = bX - aX; float dY = bY - aY; float distance = Math.sqrt(dx*dx+dy*dy);.
David Gouveia

@Fafole Düzenlemeyi kontrol edin, bir örnek ekledim. Yine de bir şey özledim emin değilim.
David Gouveia

3 yıl sonra nesneleri vektörlerle nasıl taşıyacağımı anlamış oldunuz. Şerefe!
Oliver Schöning

3

Bir Vektör oluşturun ve normalleştirin. Uyarı, yanlış numaralar içeren bazı sahte kodlar:

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

Bu size şöyle bir Vector verecektir:

25.96; 85.41

Şimdi vektörü normalleştirin ve bunu alacaksınız :

0.12; 0.75

Buradan delta ile aynı hareket.


2

Yanıtımdan kopyalandı ve yapıştırıldı: İki nokta arasındaki bir çizgideki noktaları al

Sözde kodda:

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
}

Bu cevap kullanım durumum için en iyi sonucu verdi.
kabuk
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.