Skip to main content
gamedev.net
🔒 Locked

Game Timing

Started by moleary 15 replies 1.8k views
Original Post
moleary
moleary
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.
ToohrVyk
ToohrVyk
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.
matches81
matches81
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.
Cacks
Cacks
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
moleary
moleary
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?
Cacks
Cacks
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
moleary
moleary
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. :)
sirGustav
sirGustav
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 ;)
TDragon
TDragon
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
ToohrVyk
ToohrVyk
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.
Holy Fuzz
Holy Fuzz
I'll add my recommendation for "fixed update, variable render". Fixed update is useful for games and applications that require completely deterministic simulations, which is the case in many types of multiplayer games and applications which make heavy use of physics. Variable update, though suitable for many games, cannot provide deterministic results. Even if your particular game doesn't require deterministic updates, it's still good practice to use them - and it also makes your game-logic update code simpler since it doesn't have to worry about how long it took to run the last frame or anything like that.

Note also that it is not necessary to cap the render rate to the update frequency. It's not too hard to make a renderer which takes the values of two update steps and uses the current time to interpolate between them, which provides for silky-smooth graphics even when the update frequency is not high. By changing the update frequency you can affect the speed of the game without making it really jerky.

EDIT: If you wanted to get really fancy, you could cap your render code at 60fps regardless of the update frequency, still interpolate between update ticks to produce silky-smooth 60fps graphics, *and* give any remaining CPU back to the OS.
5MinuteGaming
5MinuteGaming
Quote:
Original post by Holy Fuzz
...
Note also that it is not necessary to cap the render rate to the update frequency. It's not too hard to make a renderer which takes the values of two update steps and uses the current time to interpolate between them, which provides for silky-smooth graphics even when the update frequency is not high. By changing the update frequency you can affect the speed of the game without making it really jerky.
...
I don't understand exactly what you mean there Holy Fuzz if you could illustrate that with an example or further explanation I'd appreciate it.



Leo_E_49
Leo_E_49
Anyone here know anything about using 64 bit high precision timers?
Holy Fuzz
Holy Fuzz
Quote:
Original post by 5MinuteGaming
Quote:
Original post by Holy Fuzz
...
Note also that it is not necessary to cap the render rate to the update frequency. It's not too hard to make a renderer which takes the values of two update steps and uses the current time to interpolate between them, which provides for silky-smooth graphics even when the update frequency is not high. By changing the update frequency you can affect the speed of the game without making it really jerky.
...
I don't understand exactly what you mean there Holy Fuzz if you could illustrate that with an example or further explanation I'd appreciate it.


Okay, I'll try an example:

Let's say we want to have a fixed update rate at 20 hertz, meaning we want to update every 50 milliseconds. But we also want to let the renderer run as fast as possible. For this example, our game has one object which exists in one dimension. So heres a timeline (in milliseconds) of what happens in the application.

1000: obj.position = 5
1006: draw obj at 5.48
1015: draw obj at 6.2
1020: draw obj at 6.6
1024: draw obj at 6.92
1030: draw obj at 7.4
1038: draw obj at 8.04
1044: draw obj at 6.52
1049: draw obj at 8.92
1050: obj.position = 9

So here, the game knows that obj should be at position 5 at time 1000 and position 9 at time 1050, and the rendering code uses these two values and times to calculate a new value at which obj will be drawn.

Now, the thing to realize here is that the object's position cannot be set to 9 at time 1050 because the rendering code running prior to 1050 needs to know where the obj will be at 1050. Typically, one will choose where an object will be at 1050 during the immediately previous update at 1000.

Hope that helps.

- Fuzz
5MinuteGaming
5MinuteGaming
I read Gaffer's article and it seems that I'd probably use something like that of course specific to my own purposes.

Holy Fuzz@ I think I understand what you are saying,
Would this be correct then? You have a ship and the user or AI moves that ship to a new location your renderer would then display the ship at intermediate positions to show smooth movement of your ship to the desired location.

If that is correct then your Renderer is coupled with your Objects since the Renderer needs to know whether the object was moved or not and then obtain the projected position and the current position somehow and as you said, "interpolate" how many times to render and when to render the object along with the posistions to render the objects at. You'd probably have a Renderer for each and ever object as different objects would require different time intervals based on their movement and positions. How would you manage multiple objects being rendered if the rendering frequency is determined by movement. And what about idle sprites how would you determine the frequency for those. Was your posting just an idea or have you already implemented what you were describing?

Just curious cause it sounds like an interesting way to present movement.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.