The SDL_Delay()
and SDL_GetTicks()
solution is less-than-desirable due to its imprecision.
We could hot-loop:
while (1)
if stopwatch.time() < 16666 // in usec
break
stopwatch.reset()
input()
update()
render()
But this is less-than-desirable as it'll eat up CPU cycles that could be put elsewhere or save energy.
We could act only even frames
while (1)
if frameCount = 1
frameCount = 0
else
frameCount++
input()
update()
render()
waitForVSync // aka SDL_GL_SwapWindow(window)
But this only gets us to 72 fps.
If we need to get as close to 60 FPS as possible, it may be best to use a hybrid of the above two approaches: hot-loop on even frames until we've gotten to 16.666 ms.
while (1)
if frameCount = 1
frameCount = 0
else
while stopWatch.time() < 16666 // in usec
break
stopwatch.reset()
frameCount++
input()
update()
render()
waitForVSync // aka SDL_GL_SwapWindow(window)
A bonus of this: you don't have to just skip odd frames, you could use them for various things. Perhaps update on odd frames, render on evens? Apply video filters on odd frames? Lots of possibilities.
A note: you should probably be looking at frame-times overall. This solution only works when framerates are at least 120 fps. When framerates drop below 20s, and you want to be more accurate than OS threads will give you, hot-looping is your best bet.
The other alternative is to tap into OS scheduling, which tends to be more accurate than OS thread sleeping. However, accuracy is still not guaranteed for all systems.