Игра SDL / OpenGL работает слишком быстро на экране 144 Гц; не может использовать vsync

Вот как я справляюсь с игровым циклом:

while (running) {
diff = duration_cast<milliseconds>(end - start).count();
start = clock::now();

dt = diff / (16.0);

handleInput(); // get input
update(dt); // game logic
render(); // render game

SDL_GL_SwapWindow(window); // swap frame buffer

end = clock::now();
}

Предполагается, что это игра с фиксированным временным шагом, рассчитанная на 60FPS (это переработанная эмуляция игры SNES), однако она работает на 144 тактах на моем экране 144 Гц, что делает ее слишком быстрой. Vsync не может решить эту проблему, так что же можно?

2

Решение

Вот быстрый пример того, как игровой цикл может быть реализован:

int32_t tickInteval = 1000/FPS; // frequency in Hz to period in ms
uint32_t lastUpdateTime = 0;
int32_t deltaTime = 0;
while (running) { // running condition
uint32_t currentTime = SDL_GetTicks();
deltaTime = currentTime - lastUpdateTime;

int32_t timeToSleep = tickInteval - deltaTime;
if(timeToSleep > 0)
{
SDL_Delay(timeToSleep); // energy saving
}

update(deltaTime); // game logic
lastUpdateTime = currentTime;
}

Я бы рекомендовал присмотреться к этой теме.


UPD.
Кто-то может быть обеспокоен uint32_t переполнение. И да, это переполнится. После почти двух месяцев непрерывного запуска игры (точнее 49,7 дня). Что будет потом? currentTime будет очень маленькое положительное целое число, lastUpdateTime будет очень большое положительное целое число. Но вычитание двух не будет переполнено, несмотря ни на что. Более того, если разница не вписывается в int32_t это будет обернуто вокруг модуля UINT_MAX + 1 в результате получается небольшое положительное целое число, которое будет точным числом тиков, эти два значения различны (в отношении беззнакового переполнения единицы).

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]