Кривое движение между двумя точками


15

Какова хорошая техника, позволяющая объекту перемещаться между точками с хорошим изогнутым движением?

Конечная позиция также может находиться в движении, например, траектория полета ракеты-носителя.

Ответы:


11

Предполагая, что вы хотите, чтобы это было кадр за кадром (где цель могла бы даже двигаться), а не предварительно вычисленная траектория, это на самом деле невероятно просто:

В каждом кадре сравнивайте вектор скорости ракеты с вектором (положение цели - положение ракеты ) ; то есть вектор, указывающий от ракеты к цели. Каждый кадр, если два вектора не имеют одинакового направления, затем повернуть вектор скорости немного в сторону другого вектора, так что каждый кадр ракеты становится немного ближе к взгляду на свою цель.

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


[Edit] XNA-ish код (у меня нет XNA для проверки этого):

//Once a frame:

//Get vector spanning from missile to target
Vector2 vectorToTarget = target.Position - missile.Position;

//Convert to Vector3 to do cross-product
Vector3 vectorToTarget3 = new Vector3(vectorToTarget, 0);
Vector3 missileVelocity3 = new Vector3(missile.Velocity, 0);

//Rotate clockwise/counter-clockwise is determined by sign of cross-product
int crossProductSign = Vector3.Cross(missileVelocity3, vectorToTarget3).Z;

//Positive cross-product means rotate counter-clockwise, negative is clockwise
double rotationAngle = 0;
if(crossProductSign > 0)
    rotationAngle = -0.05;
else if(crossProductSign < 0)
    rotationAngle = 0.05;

//I'm not sure how to do rotation in XNA, but the internets tell me it's something like this:
missile.velocity = Vector2.Transform(missile.velocity, Matrix.CreateRotationZ(rotationAngle))

Обратите внимание, что, поскольку rotationAngleимеется только три возможных значения, все возможные значения Matrix.CreateRotationZ(rotationAngle)могут быть кэшированы, поэтому вам не нужно вызывать его каждый кадр.


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

@anonymouse: конечно, попробуйте это
BlueRaja - Дэнни Пфлюгофт

15

Есть два возможных метода:

Первая техника - это симуляция на основе кадров . Это хорошо, если вы делаете что-то похожее на самонаводящуюся ракету в игровом процессе, которая не должна точно поразить вашу цель.

В этом случае вы хотите отслеживать положение объекта и скорость. В каждом кадре посмотрите на направление к цели и текущее направление движения и скорректируйте скорость соответствующим образом.

Если вы мгновенно измените скорость, ваша ракета всегда будет поражать цель. Но если вы отрегулируете скорость на небольшую величину в каждом кадре, ваша ракета будет изгибаться к цели - и если она изгибается достаточно медленно, цель может увернуться от нее.

Второй метод заключается в использовании параметрического метода. Это полезно для анимации вещей, когда вы хотите точно и предсказуемо поразить цель. В этом случае вы обычно берете «время» в качестве параметра и помещаете его в какую-то функцию.

Особенно полезным набором функций являются уравнения движения, которые вы выучили в физике старших классов. Применяя их к обеим осям, вы можете получить баллистические траектории. С небольшим количеством математики вы можете определить начальные параметры для поражения цели - даже движущиеся, если она движется предсказуемо.

XNA также предоставляет ряд функций интерполяции и изогнутых движений. Посмотрите на документацию для Vector2 и дляMathHelper . Они предоставляют некоторые функции интерполяции, которые вы можете использовать и даже комбинировать для создания интересных вещей. Например, стрельба из ракеты: Lerp(линейная интерполяция) позиции вашей ракеты из начальной точки в позицию цели, а также перевод этой позиции цели из некоторой начальной цели в реальную (изменяющуюся) позицию объекта цели. Это даст вам хороший эффект «блокировки».

(Есть также некоторые функции для производящих кривых, например: CatmulRom, Hermite. Это, вероятно , труднее успешно использовать с движущейся мишени, однако.)

Если вы посмотрите на «замедление» (в контексте анимации), вы можете получить еще несколько интересных функций интерполяции, которые могут дать вам интересные эффекты, такие как ускорение.

Теперь - вы можете сказать, что эта техника дает странные результаты, когда ваша цель перемещается. Однако на практике, пока ваш снаряд движется быстрее, чем ваша цель, он обычно выглядит хорошо. Если это проблема, вы все равно должны использовать технику на основе фреймов.


3

Вы можете посмотреть синусоиды или, возможно, кривые Безье . Я не знаю, является ли синусоидальный подход нормальным, но я не могу понять, почему это так плохо.


Использование кривых Безье с B-сплайнами позволяет довольно точно представить любую кривую. Если вам нужна точность, сплайны кубического отшельника немного точнее. Имейте в виду, что иногда неточность обеспечивает приятное прикосновение органичности.
doppelgreener

+1 для кривых Безье. Для описанного использования это, вероятно, самый простой и самый управляемый.
ggambett

1

Вы можете взглянуть на Поведение рулевого управления, как определено Крейгом Рейнольдсом: http://red3d.com/cwr/steer/

Это часто используется в ИИ, чтобы NPC двигались к своей цели.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.