Delta_time locks up my fixed-step game loop

Hello everyone,

currently I am trying to implement a fixed-step game loop to cap my FPS to 60 with SDL_Delay but somehow my game locks up.

2.cc)

Uint32 FPS = 60;
Uint32 MS_PER_SEC = 1000 / FPS;
Uint32 current_time, last_time, delta_time;
current_time = delta_time = 0;

last_time = SDL_GetTicks();

// Poll for Input
while(Platform.Poll())
{
	current_time = SDL_GetTicks();
	delta_time = current_time - last_time;


	// Clear Window
	Renderer.Clear();

	// Update Input
	//...

	// Draw
	Renderer.Draw();
	
	// Update Window
	Renderer.Update();

	last_time = current_time;

	 SDL_Delay(MS_PER_SEC - delta_time);
}

I found out, that

MS_PER_SEC - delta_time

locks my game if a frame takes longer than MS_PER_SEC to process which leads to a negative value and thus to a conversion to unsigned int which as a result is a large value leading to a huge delay.

I tried to delay if and only if:

(MS_PER_SEC - delta_time < MS_PER_SEC)

but this leads to an FPS > 60, in my case 116-118 FPS.

My alternative method is:

1.cc)

while(Platform.Poll())
{
	current_time = SDL_GetTicks(); // Get time of frame begin

	// Clear Window
	Renderer.Clear();

	// Update Input

	// Draw
	Renderer.Draw();
	
	// Update Window
	Renderer.Update();

	last_time = SDL_GetTicks(); // Get time of frame end
	delta_time= last_time - current_time; // calculate frametime

	SDL_Delay(MS_PER_SEC - delta_time);
}

which works but I do not want to use this.
Is not 1.cc and 2.cc equivalent regarding the delta_time or am I missing something?

Is there a way to fix my first attempt?

sincerely yours,
lithium

This is not working:

(MS_PER_SEC - delta_time < MS_PER_SEC)

Try this instead:

(delta_time < MS_PER_SEC)

I struggled with timing for a while, I feel your pain…
Try looking at SDL_GetPerformanceCounter and SDL_GetPerformanceFrequency .

Also, use floats (or better yet, doubles) to represent time (and count it in seconds). 60 FPS is 16.666666… milliseconds, which you cannot represent evenly using whole numbers for milliseconds.

Use SDL_GetPerformanceCounter(), not SDL_GetTicks(). It measures time at below 1ms resolution (use SDL_GetPerformanceFrequency() to find out exactly), so you can calculate much more precisely how long you need to delay for. Then repeatedly call SDL_Delay(1) in a loop, and inside the loop measure how long it actually delayed for (will be a little more than 1 millisecond), and keep adding that up until you’ve reached or exceeded how long you need to delay to hit 60 FPS and exit the loop. This will get you close to 60 FPS.

If you really want to lock to 60 FPS, use vertical sync. If you’re using SDL’s accelerated 2D renderer, I believe the flag is SDL_RENDER_PRESENTVSYNC when creating the renderer. Plus, this way it will lock to whatever the monitor’s actual refresh rate is; some monitor’s are only 59hz, others go as high as 144! So don’t hard code to 60 FPS anyway (SDL can tell you what the monitor’s refresh rate is).