Game Timing

Started by
15 comments, last by 5MinuteGaming 18 years, 8 months ago
Currently my game engine strives for a fixed frame rate, e.g. 30 Hz. Everything works beautifully when this frame rate is being hit and I even get to sleep to give some time to my fellow processes. However, when I am blowing frame rate, things are not so good. If I am currently getting 15 FPS, my objects update assuming that they are hitting the 30Hz. Effectively anything that moves begins to move twice as slow because the object is updating only half as frequently but moving the same distance because it thinks it is getting 30Hz. I’ve debated the best way to handle this problem, and was looking for input. There are two options as I see them. If I am missing something please please fill me in. Or if you see big problems ahead, let me know. It would be much appreciated. I’m a newbie at this and looking for any valuable input. 1) Keep track of the time to complete last frame. Continue the way I am now and if I am hitting the target frame rate, do nothing. If I am blowing frame, then I will have all objects use the last frame time to do movement computations, etc. And the process will not sleep and keep going. I wonder if this will prove to result in jerky movement for both the first person player I have and anything walking around in the scene or projectiles, etc also since the amount of movement per frame will be bouncing around all of the time. Maybe not. 2) Keep track of the time to complete last frame. Forget about sleeping. Hog the processor. Blow through objects updating them as fast as possible. Every object can determine for itself the next time it should run by accumulating the length of the last frame. For example, say the player only needs to update 30 times per second for whatever reason. The player won’t update until it has witnessed as least 33 ms of time pass by accumulating the length of the last frame. When it moves, it will use the accumulated time to determine how big of a step to take. This value will not always be the same. Again, I question if this will also lead to jerky movement of the player and anything walking around. Thanks for any advice you can give.
Advertisement
Ideally, your game logic should not even be aware that there is rendering going on - let alone take into account the rendering of frames! Determine, for all objects in your game, the next time they should be updated, and once that time is reached, update them.

while( game_running() ) {  while( next_update_time() < time() ) update();  if( render_required() ) render();  else sleep();}


EDIT: for instance, for 30Hz, update() will increase next_update_time() by 33ms every time it is called.

On the other hand, your rendering system is aware that updates are going on, and you can always take into account the time since the last update happened to interpolate values using the velocity and position of objects. But this will only affect the position of rendered objects, and has absolutely no impact whatsoever on the actual positions of objects.
I would use a different approach for updating. What I dislike ToohrVyk´s approach is that it might use more than one call to update() per frame if frame gets really low. I would do something like this:
while(game_running){    if(currentTime - lastUpdate > 33) update();    render();}


this way you only do one update per frame maximum. In each objects update() methode I would then use currentTime - lastUpdate (the time passed since the last update) to determine the distance an object should move, should rotate or anything. For that you would need to store the objects directional / angular velocity instead of storing their targets for the next frame or anything.
What I don´t like about doing more than one call to update() is that it might take quite some time to do an update() on every object if you have many of them and the player doesn´t care for position updates he doesn´t see because they´re never rendered.
If you got a physics system or anything like that running you might really need to use ToohrVyk´s approach, or you think of a way to take that physics system into account and keep doing only one update() per frame max.
Hi, this might help:

frequency = 50; //50 Frames Per Second for example

long timelastcall = getTickCount() //get current time

while(!GAME_OVER)
{
if((getTickCount()-timelastcall) > 1000/frequency)
//1 second = 1000 milliseconds
{
game_logic();
timelastcall = getTickCount();
}
presentation();
}

This loop performs game logic updates at a rate of 50 times per second.
Then performs as much rendering as possible.


I'm wondering does any1 know how accurate the - ctime clock() function is for
timing game loops, thanks!
Reject the basic asumption of civialisation especially the importance of material possessions
My game objects do not know that rendering is going on. I treat my renderer as any other object. It specifies what frequency it wants to run at, just like every other object. When I referred to frame time, I meant the time to update all objects and render. So when I gave the example of striving for 30 Hz, but hitting 15 Hz, I meant that I was striving to achieve all object updates and render in under 33 ms, but it was currently taking 66 ms.

By looking at both ToohrVyk and Matches81 suggestions, it appears that you do not care about the actual time it takes the render the scene. So, does this mean when a game reports its FPS, it only means the time required to render the scene and does not include the time taken to update all objects? Maybe that’s my problem. I shouldn’t be expecting to get the rendering into the 33 ms frame slice (if running at 30Hz for example).

ToohrVyk:
Looking at your pseudocode, it appears that this is your top level loop. That is, is update() updating all objects (except the renderer)? If so, that means all of your objects run at the same frequency or does update() call an update method for each object and it determines if it should run or not based on its desired frequency? Also, what does the pseudo code of render_required() look like? Again, I am a newbie. Sorry for all of the questions. I’m just learning.

Matches81:
Are you missing a “if( render_required() )” before your render()? Or do you always render at the end of the updates? Same question for you. Are all objects being run at the same frequency or does update() call an update method for each object and it determines if it should run or not based on its desired frequency?

Cacks:
It appears that your method would render the same frame multiple times. Is there an advantage to this?
Yeah, your right, the loop would render the same frame multiple times, you could place a sleep in the loop if you didn't want to render the same scene multiple times.

The renderer is called as often as possible, but the game logic is updated based on a frequency. This means that your game will run the same speed regardless of the system its run on.

The advantage? Not that I've used it but you can use a percentage parameter to the renderer fuction that will allow you to specify what percentage of the current update's rendering is complete. This will allow you to perform fine interpolation so not all the frames in a given update look alike.

I'm a relative newbie too, im getting this info from a book- Core Techniques & Algorithms In Game Programming, its pretty good.

Reject the basic asumption of civialisation especially the importance of material possessions
Looking these methods over, the only difference I notice between the suggested approaches and my proposed method of keeping track of the last time to complete frame (updating all objects and rendering) and using that to update object positions is that the methods proposed by others guarantees a fixed logic update frequency (well with certain processor speeds). My method does not guarantee this because in areas of high graphic intensity, it could take a long time to render. Well, these methods don't guarantee this either. So, in effect the only difference between the proposed methods and my current approach is that I need to account for the time to complete the last frame and use this for computations in objects.

Could someone correct me if I'm way off here. :)
Main Loop with Fixed Time Steps - nice IMHO
I'm using a simple
timeStart = timeEnd = currentTime();while( running ) {  timeStart = currentTime();  update( getTimeDelta() );  render();  timeEnd = currentTime();}

I got the impression that ToohrVyk was talking about threads, ie letting the renderer or the updator running in it's own thread. If not then that's another idea that I know people (atleast some) have used ;)
Nope, you're pretty close to the mark, moleary.

As it turns out, there are about two distinct categories that modern game logic timing, or game state updating as I like to call it, falls under: fixed update with variable render, and variable update with variable render. (There is also fixed update with fixed render, but that breaks down in your initial scenario when the processor can't keep up with the timer. Definitely not an option -- usually never is). It's practically imperative that you separate your game state updating from your rendering -- i.e., the game state updating handles everything in your game world, usually checking user input and updating positions and animation frames as necessary, and the renderer just throwing all the polygons and pixels at the screen.

Fixed update with variable render can be implemented in several ways. ToohrVyk's method is an example of this: as long as game state updates are needed (next_update_time is less than the current time, or "we've fallen behind"), it performs them; otherwise, it renders. This method only fails if the time for the game state update is longer than your target update rate, but this is almost never the case and can be compensated for. Another way that the fixed update / variable render method can be accomplished is by setting a callback timer in another thread that calls a function you create every x milliseconds. This function increments an update counter variable that says "we need to update the game state x times". (In most cases you want this counter to be 0 or 1, but during heavy render it can grow). Then in the main loop, you have a sub-loop that updates the game state and decrements the counter each time until it reaches 0. The effect of this is the same as with ToohrVyk's.
The advantage of fixed update with variable render is that you can leave your objects' update methods the way they are, with a specific distance moved each update frame, animation changes every x frames, and so forth. As you noted, all objects do run at the same frequency in this method; this is typically not a concern. Here's my generic, flexible sample of fixed update, variable render:
const int UPDATE_FPS = 160;const int RENDER_FPS = 60;int next_update_time = time();int next_render_time = time();while (game_running == TRUE){    while (next_update_time <= time())    {        UpdateGameState();        next_update_time += (1000 / UPDATE_FPS); // this assumes time() returns milliseconds    }    if (next_render_time <= time())    {        next_render_time = time() + 1000 / RENDER_FPS; //as with update        RenderDisplay();    }    else        Sleep(0); //or whatever function yields the current timeslice}

Note: there's an eensy-weensy bug in this: when you reach the maximum value an int can store, next_update_time and next_render_time will do weird things and the engine will do weird things. Fixing this is left as an exercise for the reader :)
You might say, "But isn't that fixed render also, because the render frame rate is fixed to 60 FPS?" Not quite. Rather, the render frame rate is capped at 60 but can vary downwards (and will during hard-to-render scenes); whereas the update frame rate takes priority and is made always to stay at 160.

Variable update with variable render is slightly more intuitive, but also slightly more difficult. Basically, you keep track of the time it took to complete the last frame (total time for everything, update and render), and update each object's position and animation based on that. For movement, for example, each object has a base speed in units distance per units time; then when you update the object, you multiply that speed by the number of units time it's been since the last update. In this method, the game state update and the render generally happen in the same loop -- it's easy to intertwine them, but I would prefer to keep them in separate objects and/or function calls that are indeed differentiated between at the basic level. Here's a generic sample of variable update with variable render:
float last_time = time();float this_time, frame_time;while (game_running == TRUE){    this_time = time();    frame_time = this_time - last_time;    last_time = this_time;    UpdateGameState(frame_time); //use the frame time to calculate movement, etc.    RenderDisplay();}

time() should have a resolution of milliseconds at least, and preferably greater.

Note that jerkiness can build up in either of these cases, but there's not a lot you can do about it, because it's a product of longer render time. The time it takes to render a frame is the time it takes to render a frame, and the game state update time is usually much lower than this (run a profiler on your code and you'll see what I mean).

Hope all that helps,
Twilight Dragon

EDIT: sirGustav's method (posted while I was formulating mine) is an example of variable update, variable render.

EDIT2: major bug fixed in fixed update, variable render code...sorry
{[JohnE, Chief Architect and Senior Programmer, Twilight Dragon Media{[+++{GCC/MinGW}+++{Code::Blocks IDE}+++{wxWidgets Cross-Platform Native UI Framework}+++
Quote:Original post by matches81
What I don´t like about doing more than one call to update() is that it might take quite some time to do an update() on every object if you have many of them and the player doesn´t care


It really depends on your implementation of update(). The code above is a framework that can indeed be adapted to perform one update for every 33ms (what the OP was trying to do), regardless of rendering (such as the code that might be running on a very simple server). However, I generally use it combined with a priority queue sorted by the update times for all objects in the game:

update() dequeues an object and calls its update() function
next_update_time() returns the scheduled time for the first object in the queue

Also, I didn't suggest multi-threading, because I find it makes data coherence harder to implement because of concurrency, but if you can provide said coherence then you might want to consider it.

This topic is closed to new replies.

Advertisement