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

12

Я посмотрел, как это сделать, и нашел это http://www.helixsoft.nl/articles/circle/sincos.htm. Я попробовал это сделать, но большинство показанных функций не работало. Я просто получил ошибки потому что их не было. Я посмотрел на функции cos и sin, но не понимаю, как их использовать или как правильно настроить движение автомобиля, используя векторы. У меня нет кода, потому что я не уверен, что делать извините.

Любая помощь приветствуется.

РЕДАКТИРОВАТЬ:

У меня есть ограничения, что я должен использовать движок TL для своей игры, мне не разрешено добавлять какой-либо физический движок. Это должно быть запрограммировано в C ++. Вот пример того, что я получил, пытаясь следовать тому, что было сделано по ссылке, которую я предоставил.

if(myEngine->KeyHeld(Key_W))
    {
        length += carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_S))
    {
        length -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_A))
    {
        angle -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_D))
    {
        angle += carSpeedIncrement;
    }

    carVolocityX = cos(angle);
    carVolocityZ = cos(angle);

    car->MoveX(carVolocityX * frameTime);
    car->MoveZ(carVolocityZ * frameTime);
bobthemac
источник
Проверьте этот сайт на рулевое поведение: red3d.com/cwr/steer
MichaelHouse
Вы должны определить «реалистичное автомобильное движение»
Maik Semder
1
Я предполагаю, что ваш угол исходит от руля, возможно. Длина должна быть величиной вашей скорости. Таким образом, последний фрагмент кода может быть что - то на линии: carVecloityX = length* cos(angle);, carVelocityZ = length *sin(angle);, кроме этого, пожалуйста , скажите , что ваш вклад и как автомобиль должен себя вести. Прямо сейчас, это должно рулить в основании земли, но опять же, это не вообще. Там вы только что сделали нам грубый шаг интеграции Эйлера ..
teodron

Ответы:

23

Не так сложно создать довольно хорошее автомобильное движение (но этот пост будет довольно длинным). Вам нужно «смоделировать» пару основных сил, чтобы сделать автомобиль физически правдоподобным.

(Все примеры кода являются псевдокодом.)

ускорение

Во-первых, вам, очевидно, понадобится ускорение. Что-то простое, как в следующей строке:

acceleration_vector = forward_vector * acceleration_input * acceleration_factor
  • forward_vector - Вектор, указывающий в том же направлении, что и автомобиль.
  • acceleration_input - Вход должен быть в интервале [-1, 1].
  • acceleration_factor - Значение ускорения (в пикселях в секунду ^ 2 или каковы ваши единицы измерения).

Рулевое управление

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

steer_angle = steer_input * steer_factor
new_forward_vector = rotate_around_axis(forward_vector, up_vector, steer_angle)

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

 amount = time_since_last_frame * steer_lerp_factor
 forward_vector = lerp(forward_vector, new_forward_vector, amount)

Сумма должна зависеть от времени так, чтобы ваше движение не зависело от вашей частоты кадров. Количество должно быть между [0, 1] и чем оно меньше, тем плавнее будет переход между старым и новым векторами.

(В этот момент вы обнаружите, что автомобиль будет поворачиваться, даже если он стоит на месте. Чтобы этого не произошло , умножьте steer_angleна значение current_speed / max_speed, max_speedопределяемое вами как постоянная.)

перемещение

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

current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

Ваша машина сейчас скользит

Если я прав, ваша машина должна теперь скользить, когда вы поворачиваете, как если бы она была на льду. Это потому, что нет трения. На реальной машине высокое боковое трение (из-за того, что колеса не могут вращаться вбок: P).

Вам нужно будет уменьшить боковую скорость. Не уменьшая его полностью, вы также можете сделать автомобиль дрейфующим.

 lateral_velocity = right_vector * dot(velocity_vector, right_vector)
 lateral_friction = -lateral_velocity * lateral_friction_factor 

Поскольку мы говорим о трении, вам также может понадобиться сила (трения), которая уменьшает вашу скорость, так что, когда вы прекращаете ускоряться, ваша машина в конечном итоге остановится.

 backwards_friction = -velocity_vector * backwards_friction_factor

Ваш код для перемещения машины теперь должен выглядеть так:

// Friction should be calculated before you apply the acceleration
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
backwards_friction = -velocity_vector * backwards_friction_factor
velocity_vector += (backwards_friction + lateral_friction) * time_since_last_frame


current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{ 
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

Закрытие заметки

Я упоминал, как вы должны применить lerping к рулевому управлению; Я думаю, что вам может понадобиться сделать то же самое для ускорения и, возможно, для угла поворота (вам придется хранить их значения из предыдущего кадра и отрываться от него). Также все векторы относительно автомобиля (вперед, вправо, вверх) должны иметь длину 1.

Кроме того, трение немного сложнее, чем я показал здесь. Вы должны всегда следить за тем, чтобы его длина никогда не превышала длины ускорения, необходимого для остановки автомобиля (иначе трение заставило бы автомобиль двигаться в противоположном направлении). Таким образом, вы должны иметь что-то вроде:

dt = time_since_last_frame
backwards_friction.resize(min(backwards_friction.norm(), velocity_vector.norm() / dt))
lateral_friction.resize(min(lateral_friction.norm(), lateral_velocity.norm() / dt))
Пол Манта
источник
Вау, это отличный ответ!
ezolotko
0

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

Вы не упомянули 2D / 3D ограничения, поэтому я собираюсь предложить вам скачать Havok SDK (бесплатно для некоммерческого использования) и получить простую демоверсию и запустить ее (на самом деле у них есть демо-версии, которые запускаются из коробки [get скомпилирован в вашей системе, весь код есть], вам не нужно ничего делать, чтобы заставить его скомпилировать ... просто откройте проект и нажмите build).

Как только у вас появится некоторое представление о скрытых аспектах физики автомобилей (хотя вы не увидите реальную реализацию физики, которая скрыта, вы увидите интерфейсы), я думаю, вы окажетесь в лучшем положении чтобы сделать это правильно, когда вы начинаете самостоятельно.

Я тоже задал похожий вопрос не так давно. Ссылки там тоже могут помочь. И вот еще одна ссылка .


Посмотрев на ваши изменения, кажется, что вы просто хотите изменить скорость автомобиля в зависимости от рассчитанных углов (это нереально, кстати, поэтому вы должны изменить исходный вопрос, чтобы отразить это). Если углы являются частью вопроса (который вы не можете изменить), и вам нужно использовать углы для вычисления новой скорости, тогда используйте то, что @teodron поместил в комментариях.

Другой способ - использовать только векторы. Есть несколько подходов с использованием векторов, я собираюсь представить один.

Скорость - это направление * величина (где величина - это скорость, а направление - нормализованный вектор). Рассчитайте текущую скорость и направление автомобиля. Возьмите направление и добавьте к нему вектор (назовем его D'), перпендикулярный ему. Это изменит скорость автомобиля. Нет углов, чтобы возиться (хотя вы можете использовать углы, чтобы определить длину перпендикулярного вектора, который может быть коэффициентом поворота [см. Ниже])

Как рассчитатьD' : чтобы найти перпендикулярный вектор, возьмите направление исходной скорости, скрестите его с вектором направления, приближающимся к экрану, где порядок, в котором вы пересекаете векторы, определяет направление перпендикулярного вектора. Затем умножьте этот перпендикулярный коэффициент на некоторый коэффициент поворота, который определяет, насколько быстро автомобиль поворачивает.

Samaursa
источник
Я бы не смог использовать физический движок, игра 3D, и все, что мне нужно изменить, это векторы X и Z, мне просто нужно разобраться, что они из себя представляют.
bobthemac
@bobthemac: Это домашнее задание? Если да, отредактируйте свой вопрос, чтобы указать на имеющиеся у вас ограничения, и, возможно, опубликуйте какой-нибудь соответствующий код, чтобы у нас было что построить. Кстати, последняя ссылка может быть то, что вы ищете с точки зрения понимания функциональности.
Самаурса
Я добавил запрашиваемую вами информацию и просмотрел предоставленные ссылки, но все еще не понимаю ее.
bobthemac
@bobthemac: См. мое редактирование
Самаурса