Получайте очки на линии между двумя точками

9

Я делаю простую космическую игру на JavaScript, но теперь я столкнулся с проблемой векторов.

Вид игры сверху вниз на 2-мерной сетке. Когда пользователь нажимает на сетку, космический корабль летит к этому месту.

Итак, если у меня есть два набора точек:

{ x : 100.2, y : 100.6 }; // the ship
{ x : 20.5,  y : 55.95 }; // the clicked coordinates

Если игровой цикл тикает со скоростью 60 итераций в секунду, а желаемая скорость корабля составляет 0,05 балла за такт (3 балла в секунду), как рассчитать новый набор координат для корабля для каждого такта игрового цикла?

ps Я не хочу учитывать инерцию или множественные векторы, влияющие на корабль, я просто хочу, чтобы корабль прекратил все, что он делает (то есть летел в одну сторону) и перешел к координатам, по которым щелкнули, со статической скоростью.

Стивен
источник

Ответы:

8

В псевдокоде:

speed_per_tick = 0.05
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
}
Тристан
источник
@ Тристан: Вы имеете goal_distв виду в своем ifсостоянии?
Нейт В.
21

LERP - линейная интерполяция

Я дал этот ответ для аналогичной проблемы несколько дней назад, но здесь мы идем:

Линейная интерполяция - это функция, которая дает вам число между двумя числами, основываясь на прогрессе. На самом деле вы могли бы получить точку между двумя точками.


Великая формула - как рассчитать

Общая формула LERP определяется как pu = p0 + (p1 - p0) * u. Куда:

  • pu: номер результата
  • p0: начальный номер
  • p1: окончательный номер
  • U: прогресс. Это дано в процентах, между 0 и 1.

Как получить проценты

Вы можете спросить: «Как я могу получить этот процент !?». Не беспокойся Это примерно так: сколько времени займет точка, чтобы пройти вектор начала до конца? Хорошо, разделите это на время, которое уже прошло. Это даст вам процент.

Смотри, как то так: percentage = currentTime / finalTime;


Расчет векторов

Чтобы получить результирующий вектор, все, что вам нужно сделать, это применить формулу два раза, один для компонента X и один для компонента Y. Что-то вроде этого:

point.x = start.x + (final.x - start.x) * progress;
point.y = start.y + (final.y - start.y) * progress;

Расчет времени изменения

Возможно, вы хотите, чтобы ваши очки путешествовали со скоростью 0,5 балла, да? Так скажем, чем больше расстояние, тем больше будет пройдено.

Вы можете сделать это следующим образом:

  • Получить длину расстояния Для этого вам понадобятся две вещи. Получите вектор расстояния, затем преобразуйте его в значение длины.

    distancevec = final - start;
    distance = distancevec.length();

Я надеюсь, вы знаете векторы по математике. Если вы этого не сделаете, вы можете рассчитать длину вектора по этой формуле d = sqrt(pow(v.x, 2) + pow(v.y, 2));.

  • Получите время, которое потребуется, и обновите последнее время. Это легко. Поскольку вы хотите, чтобы на каждый тик вы получали 0,5 длины, нам просто нужно разделить и получить, сколько тиков мы получили.

    finalTime = distance / 0.5f;

Выполнено.

ВНИМАНИЕ: Может быть, это не та скорость, на которую вы рассчитывали, но это правильно. так что у вас есть линейное движение, даже на диагональных ходах. Если вы хотите сделать x + = 0.5f, y + = 0.5f, то прочитайте книгу векторной математики и перепроверьте свои планы.

Густаво Масиэль
источник
Что, если вы хотите, чтобы% оставался до пункта назначения с вашей позиции? Если вы не можете использовать дельта-время, а координаты x: y.
Дейв
Если вы рассчитали, progressкак указано в этом ответе, он должен быть в 0..1диапазоне. Просто сделай:progressLeft = 1.0 - progress;
Густаво Масиэль
3

Это может быть сделано путем вычисления нормали направления, а затем вычисления текущей позиции с помощью параметрического уравнения

newPoint = startPoint + directionVector * velocity * t

Где t - время, прошедшее с того момента, как корабль начал движение в нужном направлении. Вы также можете выполнить это для каждого обновления через

newPoint = currentPoint + directionVector * velocity * timeDelta

И вы просто рассчитываете это в каждом кадре / физике / и т.д. обновлять, пока корабль не достигнет пункта назначения.

hatboyzero
источник