Реалізація передачі в грі на автомобілі


23

Я намагаюся створити просту гру з автомобілем з ручною зміною передач. Однак у мене виникають певні проблеми із впровадженням змін передач.

Ось мій поточний код для "машини":

int gear = 1; // Current gear, initially the 1st
int gearCount = 5; // Total no. of gears

int speed = 0; // Speed (km/h), initially 0
int[] maxSpeedsPerGear = new int[]
{
    40,  // First gear max. speed at max. RPM
    70,  // Second gear max. speed at max. RPM
    100, // and so on
    130,
    170
}

int rpm = 0; // Current engine RPM
int maxRPM = 8500; // Max. RPM

public void update(float dt)
{
    if(rpm < maxRPM)
    {
        rpm += 65 / gear; // The higher the gear, the slower the RPM increases
    }

    speed = (int) ((float)rpm / (float)maxRPM) * (float)maxSpeedsPerGear[gear - 1]);

    if(isKeyPressed(Keys.SPACE))
    {
        if(gear < gearCount)
        {
            gear++; // Change the gear
            rpm -= 3600; // Drop the RPM by a fixed amount
            if(rpm < 1500) rpm = 1500; // Just a silly "lower limit" for RPM
        }
    }
}

Однак ця реалізація насправді не працює. Перша передача працює чудово, але наступні зміни передач спричиняють падіння швидкості. Додаючи кілька повідомлень про налагодження, я отримую ці значення швидкості при зміні на межі RPM:

Speed at gear 1 before change: 40
Speed after changing from gear 1 to gear 2: 41

Speed at gear 2 before change: 70
Speed after changing from gear 2 to gear 3: 59

Speed at gear 3 before change: 100
Speed after changing from gear 3 to gear 4: 76

Speed at gear 4 before change: 130
Speed after changing from gear 4 to gear 5: 100

Як бачите, швидкість після кожної зміни перед зміною повільніше. Як би ви взяли до уваги швидкість перед зміною передачі, щоб швидкість не знижувалася при зміні передач?


1
Мені нагадали чудовий поглиблений підручник: Автомобільна фізика для ігор . Приблизно в третині статті йдеться про передачу сили двигуна.
Ерік

Відповіді:


17

Розрахуйте новий об / хв виходячи з нової передачі та поточної швидкості автомобіля.

speed = (int) ((float)rpm / (float)maxRPM) * (float)maxSpeedsPerGear[gear - 1]);

так: замість:

rpm -= 3600; // Drop the RPM by a fixed amount

використання:

rpm = max(maxRPM,(float)maxRPM * (float)speed / (float)maxSpeedsPerGear[gear - 1]);

Швидкість тепер буде однаковою до і після зміни передачі, і ви можете прискорити / уповільнити звідти.

редагувати: додано, max(maxRPM, calc)як потрібно обмежити. Як і в автомобілі, це повинно призвести до досить раптової втрати швидкості


29

це тому, що у вашому обчисленні швидкості немає інерції. Ви просто обчислите це як абсолютний наслідок обертів і передач двигуна. але коли ви обчислюєте новий об / хв після перемикання передач, ви емпірично опускаєте його фіксованими кроками 3600 об / хв.

Це ваша помилка. падіння обертів не фіксується між передачами. Ви можете виправити це, створивши другий масив, у якому зберігається точна кількість оборотів в хвилину між кожною передачею.

Другий спосіб виправити це - за допомогою обчислень, заснованих на фізичній основі. Ви робите моделювання, тож ви можете зробити числову інтеграцію. Використання часу dtта інтеграції euler або інтеграції Verlet. Це звучить складно з іменами і все, але насправді це не так.

В основному це означатиме, що ви створюєте таблицю пошуку для крутного моменту двигуна при заданих оборотах в секунду. Тоді ви б врахували деякий опір повітря, що збільшується з квадратом швидкості. Тоді моделювання буде обчислити наступну швидкість, перевернувши ньютонів другий закон, f=m a.
Для того, щоб знайти a=f/m, то інтеграція Ейлера: speed=speed+a*dt. mстановить близько 1200 (типового ваги автомобіля). f- сила, отримана від обертового моменту двигуна, зменшена в коробці передач, а потім перетворена на силу, використовуючи важільну формулу, враховуючи радіус колеса. (векторний перехресний добуток, але його можна спростити шляхом множення крутного моменту на радіус. Тому що число метрів на метр / метр помножено на метри = ньютони.)

таким чином оберти двигуна двигуна обчислюються назад, як функція лінійної швидкості автомобіля.


2
Немає exact number of RPM drop between each gear. Це співвідношення, як вказує @Baldrickk. І хоча гарна ідея, щоб вихід трансмісії був крутний момент, а не швидкість, дискусія про опір вітру та інтеграцію верлетів трохи не виходить за межі питання, ні?
Джастін

Так. для місця відповіді на запитання, я б рекомендував відповідь Балдріка. Я це схвалив.
v.oddou

5

Шестірні використовуються як механізм редукції.

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

Отже, для вхідної передачі з x зубцями та вихідної передачі x / 2 зубів швидкість вихідної шестірні вдвічі перевищує швидкість вхідної передачі (співвідношення два до одного)

rpm2 = rpm1 * gearRatio

де:

gearRatio = teeth1 / teeth2

Тож замість обмеження кожної передачі жорстко кодованою швидкістю ми можемо обмежити її за співвідношенням. Потім ви можете обчислити швидкість для певної пари (rpmEngine, gear), і, коли передачу змінено, обчислити оберти двигуна, враховуючи відому швидкість і нову пару.

Для спрощення використовуйте лише двигун, підключений до двох передач:

rpmEngine = 5000

gearRatio[1] = 2 #low gear:  one rotation of the engine results in 2 rotations output
gearRatio[2] = 3 #high gear: one rotation of the engine results in 3 rotations output

vehicleSpeed = rpmEngine * gearRatio[selectedGear]

так:

selectedGear = 1
vehicleSpeed = rpmEngine * gearRatio[selectedGear] #5000 * 2 = 10000 

при переключенні на другу передачу 10000 - це швидкість, тому підключивши цю формулу, ми маємо:

vehicleSpeed = 10000 #computed above
selectedGear = 2

таким чином наш новий об / хв:

rpmEngine = vehicleSpeed / gearRatio[selectedGear] #10000 / 3 = 3333.3

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

Вам потрібно було б врахувати той факт, що перехід на нижчу передачу збільшує оберти двигуна, тому простий підхід - перевірити maxRPM та обмежити оберти в хвилину після переключення до максимальної обороти, зменшуючи тим самим швидкість руху автомобіля.

Отже, щоразу, коли відбувається перемикання передач, ви обчислюєте двигун RPM від швидкості руху транспортного засобу, обмежуєте його maxRPM, а потім повертаєтесь до "нормального", коли ви оновлюєте оберти на хвилину від введення користувача та обчислюєте швидкість на основі цього.

Для реалістичного моделювання ви повинні врахувати принаймні крутний момент двигуна (відповідь v.oddou) та ковзання зчеплення, що в поєднанні матиме такі наслідки: - при перемиканні вгору, припускаючи, що зміна буде досить швидкою, щоб оберти двигуна двигуна не падали , швидкість буде підвищена в той час, як оберти двигуна знизяться до тих пір, поки вони не будуть збалансовані - при зміщенні вниз швидкість транспортного засобу буде знижуватися до тих пір, поки двигун не буде піднятий до нових оборотів, але це, ймовірно, виходить за рамки "простої" реалізації.


4

Майте на увазі, що задіяна ручна коробка передач - це двосторонній пристрій. Двигун може прискорити автомобіль так само, як автомобіль (точніше його імпульс) може прискорити двигун.

Це було справжньою проблемою в ранніх ручних передачах. Зниження швидкості перетворило б двигун на більш високі обороти, викинувши цикли запалювання не синхронізувавшись і, можливо, призвело до того, що двигун зупиниться. Це було компенсовано керуванням експертом, коли водієві довелося обертати двигун до потрібної швидкості, перш ніж відпустити зчеплення, щоб увімкнути передачу.

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

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


2

Існуюча відповідь здається занадто складною. Для гри RPM - це лише показник на екрані. Фактична швидкість - реальна змінна. Передаточне співвідношення визначає, як ви перетворите оберти двигуна в обертові. Зміна передач змінює відношення, але не швидкість. Очевидно, що частота обертів також змінюється як обернена передача.

Овервевінг (зменшення переходу за межі вашого обмеження в 8500 об / хв) - це те, що ви реалізуєте окремо, але в автомобілях це погані речі, і ви можете дозволити йому бути поганою справою у вашій грі.


2
Існуюча відповідь - це саме те, що роблять більшість ігор, які я бачив, навіть прості аркадні ігри, адже це насправді не так складно. RPM на екрані може бути просто числом, але такий підхід дає вам як кількість (яку можна будь-коли налаштувати на візуальні індикатори), так і поведінку, щоб відповідати цим числам
Selali Adobor

2

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

Я б припустив, що крутний момент двигуна повинен збільшуватись із оборотами в хвилину до певної межі і виходити за межі цього. Швидкість, з якою автомобіль розганяється, повинна бути пропорційною крутному моменту, поділеному на передаточне число, мінус повітря, який пропорційний квадрату швидкості. Якщо послідовні передачі мають відношення 1: 41: 1, оптимальне перемикання для прискорення відбудеться в тому місці, коли крутний момент у нижній передачі впав приблизно до 70% від того, який був би в наступній вищій передачі.


2

На основі @ v.oddou, використовуючи

max(maxRPM, calc)

може спричинити максимальну швидкість обертання частоти передач швидко, коли перемикаються передачі, не допускаючи плавного переходу від шестерні до передачі. Правильним способом було б вирішити для RPM, використовуючи змінну швидкості як рівняння.

speed = (int) ((float)rpm / (float)maxRPM) * (float)maxSpeedsPerGear[gear - 1]);

Розв’язати на об / хв

rpm = (maxRPM * speed) / maxSpeedsPerGear[gear - 1] ;

оскільки швидкість передачі на 1 вища, ніж була раніше, обертові обороти будуть нижчими.

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