Advertisement

Is this loop any good?

Started by November 28, 2015 11:34 AM
3 comments, last by tapped 9 years ago

I tried to make a loop that updates only 60 times per second but i tried to make it without any help soooo...i think its pretty bad but i want your opinions and if you can, some advice. Is this the way it should be done or is there a better algorithm? Or is this even working? xD

I am not asking this from my computer and until Monday i won't be able to compile this myself and this is why i am asking. I really wanna know if this works so hope you don't mind.


const int microseconds = 1000000;
	int fps = 0;

	
	while (window.isOpen()){
		clock.restart();
		while (clock.getElapsedTime().asMicroseconds() < microseconds)
		{

		//LOGIC
		        fps++;

			if (fps == 60)
			{
		          cout << fps << endl;
			  fps = 0;
			  break;
			}
		}
	}

I would expect a delay somewhere in the loop, as in


while true:
    pre_now = getCurrentTime();

    // do stuff

    post_now = getCurrentTime();
    if post_now - pre_now < 1/60th second: wait (1/60th - (post_now - pre_now));
end

Ie you wait until the frame time is 1/60th of a second.

If you use physics, you want another solution. You run the physics as often as possible, and update game state eg 60 times/second.

In the latter case, some reading materials:

http://gafferongames.com/game-physics/

http://lspiroengine.com/?p=378

Advertisement


If you use physics, you want another solution. You run the physics as often as possible

Wait... what? You certainly don't want to run physics "as often as possible" with a variable timestep. You especially want to run physics with a fixed timestep, both articles you linked explicitely mention this. Physics is actually the reason you really need a fixed timestep in the first place, its nice for gamestate but not actually necessary (makes some things more consistent and easier to debug though).

Did you perhaps miswrite this, or do I fail to understand what you exactly mean?

I made a mistake in expressing myself, sorry for the confusion.

For me this looks like a main loop doing rendering (you call each iteration for frames) and logic.
The loop you made is not deterministic, which means how long your 60 frames takes, depends on how long your logic takes to execute, and will differ from system or amount of work.
But that is without knowing how you have setup your rendering API, in other words I am not sure your frames is bound to the screen refresh rate. If VSYNC is enabled(should be to prevent screen tearing or jiggered pixel movement), your loop could be rewritten to something like:


stopwatch frameTime;
setSwapBufferInterval(1); // Swap buffer by an interval of one frame. 
while(window.isOpen())
{
  frameTime.restart();
  // LOGIC/RENDERING
  swapBuffer(); // Will block until it is time to swapBuffer based on screen refresh rate.
  frameTime.stop();
  
  std::cout << "FPS: " << 1.0 / frameTime.seconds << std::endl; // You should probably throttle FPS printing, by for example taking average FPS every sec.
}

Beware that there exist screens with 120 hz (and more than that too), which may not be suitable for your physics engine or game logic (too low precision per timestep etc.).
Also having a dedicated rendering thread is what is recommended today. There are unfortunately no standard way of doing it, but there exist per platform solutions. On OS X and iOS you have something called CADisplayLink (CVDisplayLink on OS X). On android you have something called Choreographer. In browser you have requestAnimationFrame. On Windows you make your own thread and use https://msdn.microsoft.com/en-us/library/windows/hardware/ff547265(v=vs.85).aspx from GDI+ (Only works on Vista and upwards).

So now you need to sync rendering and logic, since rendering happens in its own thread, and event handling and other things on the main thread. This can be done by simple communication (in hardware) between your main thread and rendering thread. For example by using semaphores.
Also all the per platform methods above gives you the current frame duration, which is very accurate and can be used later in your time independent code to do proper physic integration or movement.

I guess this may seem a bit daunting to you, however I have seen a lot of weird solutions to this problem, and in my experience the best way to make a main loop is by reading the docs for your target platform.

This topic is closed to new replies.

Advertisement