Как получить и использовать дельта время

14

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

Марк Федурин
источник
C11 и C ++ 11 теперь также имеют наносекундные часы: stackoverflow.com/a/36095407/895245 || stackoverflow.com/a/5524138/895245
Сиро Сантилли 新疆 新疆 中心 法轮功 六四 事件

Ответы:

18

«Дельта-время» - это время, прошедшее между обновлениями двух кадров (но оно также может использоваться в других контекстах; обычно это результат вычитания времени).

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

Следующая строка возвращает количество миллисекунд с момента вызова glutInit (или первого вызова glutGet (GLUT_ELAPSED_TIME)):

int timeSinceStart = glutGet(GLUT_ELAPSED_TIME);

Поэтому, если вы регистрируете текущее время timeSinceStart в каждом цикле рендеринга, вы можете узнать deltaTime, вычитая старое значение в новое.

int oldTimeSinceStart = 0;

while( ... )
{
     int timeSinceStart = glutGet(GLUT_ELAPSED_TIME);
     int deltaTime = timeSinceStart - oldTimeSinceStart;
     oldTimeSinceStart = timeSinceStart;

     //... stuff to update using deltaTime
}

Вы также можете сделать это почти так же, используя библиотеку ctime C / C ++ с clock () и макрос-константное выражение CLOCKS_PER_SEC, которое определяет отношение между тактом и секундой.


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


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

Position.x += 10/1000 * deltaTime;

Таким образом, независимо от того, обновлялась ли ваша программа 2 раза или 100 раз, через 1 секунду позиция должна быть почти такой же, и на игровой процесс меньше влияют низкие fps небольшого компьютера, чем если бы он использовал фиксированные значения.

  • С фиксированными значениями ==> низкие fps = меньше обновлений = медленные движения, тогда как высокие fps = больше обновлений = очень быстрые движения.

  • С deltaTime ==> «почти» те же движения.


Наконец, вы должны прочитать Фиксированный временной шаг по сравнению с переменным временным шагом в gamedev.stackexchange.

Valkea
источник
Возвращает миллисекунды как целое число? Брутто, и, возможно, недостаточно. Мне всегда приходилось использовать таймеры для платформ, а затем просто избегать глютена, как чумы, потому что это супер не очень хорошо для игр.
Шон Мидлдич
@Sean Я тоже не использую GLUT, но это было в параметре вопроса, поэтому я ответил с учетом этого;) Однако я заинтригован вашей позицией в отношении "недостаточности" int для обработки миллисекунд в играх , A positive intобычно поднимается до 2.147.483.647, если подписано, и до 4.294.967.295, если не подписано ... так что даже если мы рассмотрим меньшее, 2.147.483.647 миллисекунд - это почти 25 дней ... Этого должно быть достаточно для обработки большинства игр. таймеры и даже если этого недостаточно, мы все равно можем разумно использовать unsigned int(~ 50 дней) или даже long long(как я обычно делаю).
Валкеа
1
@Valkea Дело не в максимуме, а в низком разрешении. Поскольку один кадр с частотой 60 кадров в секунду составляет всего 16 2 / 3rds мс, точность в 1 мс (от представления миллисекунд в виде целых чисел) составляет погрешность более 5% - более чем достаточно, чтобы выбрасывать симуляции далеко от удара. Целое число микросекунд будет терпимым, но миллисекунды слишком грубые.
Стивен Стадницки
Да, вам понадобится таймирование менее миллисекунды для многих вещей и таймер высокого разрешения, чтобы найти то, что GLUT не предоставляет (что я знаю). Неплохо просто написать небольшой код платформы для использования QueryPerformanceCounterна Windows и gettimeofdayна большинстве других. Вам придется запачкать руки и стремиться к чему-то большему, чем наименьший общий знаменатель API-интерфейсов платформы, особенно в C и C ++.
Шон Мидлдич
Такая точность не полезна для всех игр. Однако это очень интересное объяснение, которое полностью отвечает на мой вопрос о вашей точке зрения на int и часы. Мне никогда не нужны были высокоточные часы, но я думаю, пришло время углубить мои знания по этому вопросу. Спасибо;)
Valkea