This is how I handle the game loop:
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();
}
It is intended to be a fixed timestep game locked to 60FPS (it's a re-made emulation of an SNES game) however it runs on 144 timestep on my 144hz screen, making it far too fast. Vsync can't solve this, so what can?
Here is a quick example of how game loop can be implemented:
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;
}
I would recommend to look close on this topic.
UPD.
One might be concerned with uint32_t
overflow. And yes it will overflow. After almost two months of uninterrupted run of the game (49.7 days to be precise). What will happen then? currentTime
will be a very small positive integer, lastUpdateTime
will be a very large positive integer. But the subtraction of two will not overflow no matter what. Moreover if the difference does not fit into int32_t
it will be wrapped around modulo of UINT_MAX + 1
resulting in a small positive integer that will be the exact number of ticks these two values different (with regard to unsigned overflow of one).