🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

"Fixed Timeslices"?

Started by
4 comments, last by h8CplusplusGuru 2 years, 9 months ago
    int  gameOn = 1
    int simulationTime = 0;

    while (1){

      int realTime = Gettime();

      while (simulationTime < realTime){
             simulationTime += 16; //Timeslice is ALWAYS 16ms. 
             UpdateWorld(16);
      }

      RenderWorld();
    }

This system is very well known in the game industry and is actually the keystone of games such as Starcraft II or id Software engines !


I measured the time inside the second while, and it always alternates between 0 and 1 ms (using SDL_GetTicks). While the frame rate outside the loop remains variable. (Different FPS values on each iteration.)
I also don't understand why the argument 16 is necessary in his “UpdateWorld” function.
Furthermore, the second loop runs exactly once every frame on my machine. I don't see how this is supposed to work at all. Do you?

Source:
- https://www.fabiensanglard.net/timer_and_framerate/index.php

Advertisement

The outer loop is the render loop (draw graphics), this frame rate is variable because it depends on the amount of CPU that this program receives from the system. If you computer is busy with other tasks, you game will receive small CPU time and the FPS will drop. Anyway, the loop keeps the game state where it is suppose to be, I mean that if an object is moving with constant velocity, you will see it always where it is expected to be. Just the game will skip some frames.
If there is enough CPU, some render frameworks, limit the FPS to a set value (example 60 FPS). Anyway, by definition, the outer loop is 1 frame (drawing function call).

About the inner loop, it is the Logic loop with fix step, it runs your game 16ms each time. How many? Those needed to reach to the current time.

The parameter 16 passed to the UpdateWorld function is to advance the game only 16ms. All the moving objects will be translated 16ms only. This step must be small enough to avoid the collision tunneling.

https://uploads.toptal.io/blog/image/127158/toptal-blog-image-1536860905937-23af5e10dc743ca09b13985cb6be01f2.png

So the game loop is mainly


    while (1){

      int realTime = Gettime();

      UpdateWorld(realTime - simulationTime);  // but this is split in small steps of 16ms, to simplify the game physics
	  simulationTime = realTime;
	  
      RenderWorld();
      
    }

None

Interesting note about 16ms needed to avoid tunneling. I am using a different technique for detecting if a projectile hit something. I basically calculate the time required for the projectile (a bullet) to hit an object (like a wall). If the calculated time < delta time, a collision occured. If no collision occurs, the routine will just return a big number guaranteed to be way larger than delta time.

If everything in simulation was hard-coded to always assume 16 milliseconds for a step, then the argument 16 isn't needed for UpdateWorld().

If your frame rate is locked with VSync to 60 Hz, then you will always spend 16.6 milliseconds in the overall loop, and generally only run the inner loop once at a time. Except about one every hundred frames or whatever when the slight difference between vsync rate and world step rate accumulates to a full step, and you run the simulation loop twice. Or if your computer temporarily gets overloaded with other work, and falls behind, and then needs to catch up. (This was more common before quad-core was considered minimum spec.)

16 milliseconds is not enough to avoid tunneling in all cases, btw. It depends on the specifics of the simulation. Generally, for things that move fast, you'll want to use swept collision tests, rather than move-and-test. Some physics engines switch between modes, others always do swept (continuous) collision detection, and yet others will subdivide the step (taking, say, four 4ms steps) when they detect that things are close.

enum Bool { True, False, FileNotFound };

an error in your code is that you set simulation time to zero, on the first iteration, its going to run about a ton of sim steps.

the steps for your game, the simulation steps, are called steps.

timeslices, the term, refers to doing work across multiple steps.

For instance, instead of updating all of your units ai each step (16ms), you update 33% of them each step, 100% of them every three steps.

This topic is closed to new replies.

Advertisement