Я хочу створити реалістичний рух автомобіля за допомогою векторів


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);

Ознайомтеся з цим сайтом щодо поведінки в рульовому режимі: red3d.com/cwr/steer
MichaelHouse

Вам потрібно визначити "реалістичний рух автомобіля"
Майк Семер

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, що означає, що ваш автомобіль повернеться миттєво. Ви можете виправити це за допомогою дуже простої лінійної інтерполяції (лерпінгу):

 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

Заключні записки

Я згадав, як слід застосовувати лерпінг до керма; Я думаю, що вам може знадобитися зробити те ж саме для прискорення і, можливо, для кута повороту (вам доведеться зберігати їхні значення з попереднього кадру та лерп з цього). Також всі вектори відносно машини (вперед, вправо, вгору) повинні бути довжиною 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 (безкоштовно для некомерційного використання) та отримати просту демонстраційну версію та роботу (у них фактично є демонстрації, які закінчуються у вікні [отримати компільований у вашій системі, весь код є], вам не потрібно нічого робити, щоб його скласти ... просто відкрийте проект і натисніть збірку).

Коли ви маєте уявлення про кулуарні аспекти фізики автомобілів (хоча реальної реалізації фізики ви не побачите, це приховано, ви побачите інтерфейси), я вірю, що ви будете в кращому становищі щоб правильно це зробити, коли ви починаєте самостійно.

Я теж не так давно задав подібне питання . Посилання там також можуть допомогти. А ось ще одне посилання .


Подивившись на вашу редакцію, вам здається, що ви хочете просто змінити швидкість руху автомобіля залежно від обчислених кутів (це нереально доречно, тому вам слід змінити оригінальне запитання, щоб це відобразити). Якщо кути є частиною питання (який ви не можете змінити), і вам доведеться використовувати кути для обчислення нової швидкості, тоді перейдіть до того, що @teodron помістив у коментарях.

Інший спосіб - використовувати лише вектори. Існує кілька підходів із використанням векторів, я збираюся представити один.

Швидкість - це напрямок * величина (де величина - швидкість, а напрямок - нормалізований вектор). Обчисліть поточну швидкість та напрямок автомобіля. Візьміть напрямок і додайте вектор (назвемо його D') до перпендикулярного йому. Це змінить швидкість автомобіля. Жодних кутів не возитися (хоча ви можете використовувати кути, щоб визначити довжину перпендикулярного вектора, який може бути коефіцієнтом повороту [див. Нижче])

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


Я б, але мені заборонено використовувати двигун фізики, гра - 3D, і все, що мені потрібно змінити, - це вектори X і Z, які мені просто потрібно розробити, якими вони є.
bobthemac

@bobthemac: Це питання домашнього завдання? Якщо так, відредагуйте своє запитання, щоб вказати на ваші обмеження та, можливо, опублікувати якийсь відповідний код, щоб ми могли надбудувати щось. До речі, останнім посиланням може бути те, що ви шукаєте з точки зору розуміння функціональності.
Самаурса

Я додав потрібну інформацію та переглянув надані посилання, але все ще не розумію її.
bobthemac

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