Реализация трансмиссии в автомобильной игре

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
        }
    }
}

Однако эта реализация на самом деле не работает. Первая передача работает нормально, но следующие изменения приводят к снижению скорости. Добавляя некоторые сообщения отладки, я получаю следующие значения скорости при изменении предела оборотов:

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

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

manabreak
источник
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)как вы хотите ограничить его. Как и в машине, это должно привести к довольно внезапной потере скорости

Baldrickk
источник
29

это потому, что в ваших вычислениях скорости нет инерции. Вы просто вычисляете это как абсолютное следствие оборотов двигателя и передачи. но когда вы вычисляете новое число оборотов после переключения передач, вы эмпирически понижаете его с фиксированными шагами в 3600 об / мин.

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

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

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

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

v.oddou
источник
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 

при переключении на 2-ю передачу 10000 - это скорость, поэтому, включив ее в ту же формулу, мы теперь имеем:

vehicleSpeed = 10000 #computed above
selectedGear = 2

Таким образом, наш новый rpm:

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

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

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

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

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

cristiancrc
источник
4

Имейте в виду, что включенная механическая коробка передач является двусторонним устройством. Двигатель может ускорять транспортное средство так же, как транспортное средство (точнее, его импульс) может ускорять двигатель.

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

Это было до тех пор, пока не была разработана синхромеша . Это механизм, который предотвращает включение передачи до синхронизации входных и выходных скоростей.

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

edgerunner
источник
2

Существующий ответ кажется слишком сложным. Для игры RPM - это просто индикатор на экране. Фактическая скорость является реальной переменной. Передаточное число определяет, как вы конвертируете частоту вращения двигателя в об / мин. Смена передач меняет передаточное отношение, но не скорость. Очевидно, что обороты также изменяются как обратное отношение передаточного числа.

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

MSalters
источник
2
Существующий ответ - именно то, что делает большинство игр, которые я видел, даже простые аркадные игры, потому что это действительно не так сложно. Число оборотов в минуту на экране может быть просто числом, но этот подход дает вам как число (которое в любом случае можно настроить для визуальных индикаторов), так и поведение, чтобы соответствовать этим числам
Selali Adobor
2

Как уже упоминалось, скорость транспортного средства должна быть реальной величиной, и из этого следует определять обороты. Повышение скорости должно привести к уменьшению скорости вращения двигателя, поскольку отношение оборотов в минуту на км будет изменяться «мгновенно», а скорость автомобиля - нет.

Однако я бы предложил, чтобы крутящий момент двигателя увеличивался с оборотами до определенного предела и выходил за его пределы. Скорость, с которой транспортное средство ускоряется, должна быть пропорциональна крутящему моменту, деленному на передаточное число, минус сопротивление воздуха, пропорциональное квадрату скорости. Если последовательные передачи имеют отношение 1: 41: 1, то оптимальное переключение для ускорения произойдет в точке, где крутящий момент на нижней передаче упал примерно до 70% от того, что было бы на следующей более высокой передаче.

Supercat
источник
2

Опираясь на @ v.oddou, используя

max(maxRPM, calc)

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

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

Решить для оборотов

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

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

White Development Studios
источник