[A5] How to properly implement limiting FPS?
wixy00

Hi, I've been trying to implement my game loop without using Allegro timers for practice. I came up with something like this:

#SelectExpand
1double frameStart = 0.0f; 2double frameTime = 0.0f; 3double TimePerFrame = 1.0f / 60.0f; 4double lastFrameTime = 0.0f; 5 6while (!gameOver) 7{ 8 lastFrameTime = al_get_time(); 9 10 ProcessEvents(); 11 Update(TimePerFrame); 12 Render(); 13 14 if (TimePerFrame > lastFrameTime - al_get_time()) 15 al_rest(TimePerFrame - (lastFrameTime - al_get_time())); 16}

It works, CPU usage is significantly lower, but animation isn't as great as without FPS limit. How could I fix it?

Chris Katko

Why aren't you using timers? They're simple. You don't even need an event loop. It can be as simple as:

al_start_timer(...); //at say 60 hz

do{
if(al_get_timer_count(timer) > 0) //it incremented at least once
  {
  al_set_timer_count(timer, 0);
  
  logic();
  draw();

  }
}while(true);

You're currently assuming al_rest has both high enough precision (5 ms vs 5.00023 ms) to compare the floats, and, enough repeatability (5 ms = 5.012341ms then 5.023 ms then 5.2 ms then ...)) to be consistant.

al_rest per the docs is not a high precision delay function.

Quote:

With some operating systems, the accuracy can be in the order of 10ms.

that's a huge difference if you're running a high frame rate. For example, 60 FPS is 16 milliseconds per frame. If you can only select 10 ms, or 20 ms, you're never going to hit it correctly and constantly be over-correcting.

If you need high precision, use a C library that offers it. Or... just use events like you're supposed to which have no problem even at 120 hz and higher. (Note: You can still use "events" exactly like the above code, just to trigger a frame every X milliseconds when a timer fires off. It's not complex.)

Thread #617935. Printed from Allegro.cc