Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I learned from game class that in update function, every movements must be time dependent for the sake of linearity in movement.

We made a simple game. Every move like going left, right or jump is written time dependent.

But, in some other computers, our game is worked very differently. For example, our character jumps higher than it should be. I guess this is because each computer has different FPS rate according to its specification.

My question is that what should we do to make this game work in same way in every computer? Setting FPS rate to a constant is a solution?

share|improve this question
1  
If it is really time dependent, instead of frame rate dependent, how can be different in different computers? I think you should study either your code or your definitions. That said, if the system has a timer of high enough resolution, there is no problem in updating it at a constant rate –  Ioachim Mar 18 '12 at 20:07
2  
FPS will always vary on different machines, although your updates can use a fixed time step: gamedev.stackexchange.com/questions/1589/… –  John McDonald Mar 18 '12 at 20:25

2 Answers 2

up vote 21 down vote accepted

You will want to separate the game speed from frame rate. Check out this article: http://gafferongames.com/game-physics/fix-your-timestep/

I'll sum up parts that apply to your problem. We face 2 issues:

  • Frame rates may fluctuate and vary across different hardware, so you want to keep game speed constant and independent of frame/rendering rate.

  • It is also important to keep each time step you advance your physics to be a constant because that keeps the physics stable due the way most physics engines are designed (such as Box2D which Angry Bird uses); they use something called an integrator to do the math

To solve these problems, as the article states, we want our loop to be structure so that "the renderer produces time and the physics simulation consumes it in discrete dt sized chunks."

Each loop we update physics according to how much time is given, then render the final state. See code from article (I simplified it a bit and commented):

const double dt = 0.01; 

double currentTime = current_time_in_seconds();
double accumulator = 0.0;

while ( !quit )
{
     double newTime = current_time_in_seconds();
     double frameTime = newTime - currentTime; //total time available this frame,
                                               //or the amount of time passed since                                                      
                                               //last iteration of main loop
     currentTime = newTime;

     accumulator += frameTime; //accumulator keeps track of how much time left

     while ( accumulator >= dt ) //consume available time in fix-sized chunks (dt)
                                 //Why fixed? for stable physics
     {
          integrate( &state, dt ); //step forward physics/game engine by time dt
          accumulator -= dt; //we used up dt amount of time, update accumulator
     }
//NOTE: there might still be some time left in accumulator, see explanation below
     render(state); //Render current state of the game given by physics/game engine
}

Because we consume time in fix-sized chunks (dt), there might be say half a (dt) amount of time left in accumulator. In above code this may cause physics to fall behind for a few iterations until accumulator sums up to at least 1 (dt). This may cause stuttering as we render state of the game advanced by different time steps each iteration. Therefore, we smooth this out by linearly interpolating between current and previous physical states; I'll explain more below the code:

const double dt = 0.01;

double currentTime = current_time_in_seconds();
double accumulator = 0.0;

State currentState;
State nextState;

while ( !quit )
{
     double newTime = current_time_in_seconds();
     double frameTime = newTime - currentTime;
     if ( frameTime > 0.25 )
          frameTime = 0.25;   // note: max frame time to avoid spiral of death
     currentTime = newTime;

     accumulator += frameTime;

     while ( accumulator >= dt )
     {
          currentState= nextState;
          integrate( nextState, dt );
          accumulator -= dt;
     }

     const double alpha = accumulator / dt;

     State state = nextState*alpha + currentState * ( 1.0 - alpha );

     render( state );
}

I saw a lot of confusion about the above code from article's comments about the interpolation so I changed the variable names to make it more understandable.

I'll explain it in my way here:

  • When accumulator = 0, alpha = 0, state = currentState. We simply render currentState.

  • When accumulator = 1/3*dt, this means we need to render a state that is currentState plus 1/3*dt ahead in time. To do this, we actually make our physics engine advance 1 dt ahead of rendering to produce nextState and linearly interpolate between currentState and nextState to get currentState plus 1/3*dt.

In this case, our physics engine is actually running 1 time step(dt) ahead of rendering for the sake of keeping game speed and rendering consistent.

Any questions about above explanation, please do ask.

Note: I take no credit for above approaches; they all from the article mentioned.

share|improve this answer
2  
Could you potentially sum up some of the most important parts of the article to guard against link-decay? :D –  Gordon Gustafson Mar 19 '12 at 1:07
1  
Similar is this: koonsolo.com/news/dewitters-gameloop. Basically, you want to separate out your update-loop and draw-loop so that if it's taking a long time, you can skip frames, but keep updating just fine. Also, if it runs fast, you can interpolate frames so that it appears to be running smoother than the update-loop is actually running. –  AlbeyAmakiir Mar 19 '12 at 3:33
    
Ok I edited my answer to include sort of summary of second half of the article. –  XiaoChuan Yu Mar 19 '12 at 5:49
    
Thank you for your detailed answer. It helped a lot. –  Ozan Mar 19 '12 at 18:40

The way to go is to use the delta time since the last update (ie. deltatime=1/fps or just the time since last update)

The thing is that you seems already to do that, so what can be wrong then?

I use milliseconds on an integer so I force my games to not run over say 200-300fps (~4msec) and if they run over say 200msec/frame I block that too (5fps). This is so I won't have any underflows/overflows in the calcs and so most rounding errors won't be big enough to notice.

On say a platformer where you 'add' the delta to say a jump speed (or its acceleration), you might want to use floats everywhere (for all variables connected to the deltatime: position, acceleration, ...)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.