Переміщення від A (x, y) до B (x1, y1) з постійною швидкістю?


21

На даний момент у мене є щось на кшталт:

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

І кожні 0,01 секунди я оновлюю позицію своїх об’єктів так:

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

Таким чином, це переміщує мій об’єкт з точки 0 до точки 1 за 1 секунду. Що мені потрібно - це мати 2 бали, щоб мати можливість переміщати об'єкт з точки0, зверненої (у напрямку до) точки1 з постійною швидкістю. Таким чином, коли у мене є точка, що знаходиться ближче до моєї початкової точки, об'єкт рухатиметься до нього з тією ж швидкістю, що і у мене, якщо б я мав дальшу точку. Будь-які пропозиції вдячні. Спасибі.


Можливий дублікат: gamedev.stackexchange.com/questions/23430/… Я б опублікував ту саму відповідь, яку я дав на інше питання. Але це було б безсоромно з мого боку.
Gustavo Maciel

Відповіді:


26

Я буду використовувати лінійні структури алгебри, оскільки так простіше описати операції. Якщо ви не знаєте, як реалізувати ці векторні операції, я коротко поясню наприкінці.

Тож скажімо, що ви починаєте з цих значень: startі endпозначте кінцеві точки руху, speedце скільки пікселів воно повинно рухатись за секунду, і elapsedшвидкість, з якою ви оновите позицію свого об'єкта (деякі двигуни вже надають це значення для вас ):

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

Перше, що вам потрібно буде обчислити - це відстань між обома точками та нормалізований вектор, що містить напрямок від початку до кінця. Крім того, вам слід "прив’язати" положення об'єкта до startточки. Цей крок робиться лише один раз, на початку:

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

Потім на вашому методі поновлення, ви переміщаєте об'єкт, додавши множення direction, speedі elapsedйого позиції. Після цього, щоб перевірити , якщо рух закінчиться, ви бачите , якщо відстань між початковою точкою і поточним становищем об'єкта є більше , ніж початкова відстань Ви вирахували. Якщо це правда, ми прив'язуємо позицію об'єкта до кінцевої точки і перестаємо рухати об’єкт:

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

Швидкий довідник векторних операцій

Представництво

Vector2 A = float aX, aY;

Сума / Віднімання

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

Помножити на скаляр (поплавок)

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

Довжина / відстань

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

Нормалізувати

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

Цього повинно вистачити для перетворення вищевказаного коду в звичайні операції, якщо у вас немає у вас Vectorкласу.


Приклад конверсії

// 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 Тому я дав пояснення щодо векторів наприкінці. Відповідь мала бути загальною. Якщо у вас немає класу Vector, використовуйте два окремих поплавці. Наприклад Vector2 start;стає float startX, startY;. І ви можете легко обчислити відстань вручну, як я пояснюю в кінці. Тобто float dX = bX - aX; float dY = bY - aY; float distance = Math.sqrt(dx*dx+dy*dy);.
Девід Гувейя

@Fafole Перевір редагування, я додав приклад. Не впевнений, якщо я щось пропустив.
Девід Гувейя

Через 3 роки, і ви щойно змусили мене зрозуміти, як рухати предмети за допомогою векторів. Ура!
Олівер Шьонінг

3

Створіть вектор і нормалізуйте його. Попередження, деякий псевдо-код з неправильними числами попереду:

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

Це дасть вам вектор, як:

25.96; 85.41

Тепер нормалізуйте вектор, і ви отримаєте це :

0.12; 0.75

Звідси це той самий рух, що і з вашою дельтою.


2

Скопійовано та вставлено з моєї відповіді на: Отримайте очки на лінії між двома точками

У псевдокоді:

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
}

Ця відповідь найкраще підходила для мого випадку використання.
оболонка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.