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've got a projectile working perfectly using the code below:

//initialised in loading screen 60 is the FPS - projectilEposition and velocity are Vector3 types

gravity = new Vector3(0, -(float)9.81 / 60, 0);
//called every frame
projectilePosition += projectileVelocity;

This seems to work fine but I've noticed in various projectile examples I've seen that the elapsedtime per update is taken into account. What's the difference between the two and how can I convert the above to take into account the elapsedtime? (I'm using XNA - do I use ElapsedTime.TotalSeconds or TotalMilliseconds)?

Edit: Forgot to add my attempt at using elapsedtime, which seemed to break the physics:

projectileVelocity.Y += -(float)((9.81 * gameTime.ElapsedGameTime.TotalSeconds * gameTime.ElapsedGameTime.TotalSeconds) * 0.5f);

Thanks for the help

share|improve this question

4 Answers 4

up vote 3 down vote accepted

If you assume a constant frame rate of 60, your game doesn't work with the same speed with any other frame rate. If your rendering is too slow, the physics will also slow down. Sometimes this is desirable, but usually games are running the physics with constant speed independent of the rendering frame rate.

You can change your formulas to use elapsed time instead of 60, but it is very hard to do that in a way that the physics will behave the same with different time differences. For linear movement it is not a problem, but already for a parabolic trajectory or collisions this becomes hard and for more complex trajectories there is no closed form formula.

The best solution usually is to use frame skipping. In this approach you take the elapsed time into account, but instead of updating the formulas you calculate how many times you need to update the physics in a row. This means that if the rendering is lagging, the physics will be updated several times per rendering frame. If the rendering is running faster than the physics should be updated, then frame skipping will skip the physics update as needed. The following code snippet does frame skpping. It assumes that the time units are in milliseconds, but it is easily adaptable to other units as well.

int TIMESTEP = 1000 / 60; // 1000 milliseconds in second, 60 Hz physics update
long previousTime = getTime();
long deltaTime = 0;

while (gameRunning) {
    long currentTime = getTime();
    deltaTime += currentTime - previousTime;
    while (deltaTime >= TIMESTEP) {
        updatePhysics();
        deltaTime -= TIMESTEP;
    }

    render();
}
share|improve this answer

Your formula is wrong, as 0.5*accel*t^2 gives a change in position, not a change in velocity. What you probably want to do is this:

gravity = new Vector3(0, -9.81f, 0);
projectileVelocity += gravity * gameTime.ElapsedGameTime.TotalSeconds;
projectilePosition += projectileVelocity * gameTime.ElapsedGameTime.TotalSeconds;

Note that the framerate of 60 is not needed, this will work for any framerate which is the main reason to use elapsed time in the first place.

share|improve this answer
    
Thanks for the correction. One thing I don't understand is that s = ut + 0.5at^2. Where does the 0.5 aspect go in your code? (Not saying it's wrong, just wondering). (edit: I'll upvote when I have enough points) –  XSL Mar 9 '11 at 4:02
    
My code isn't using that formula. The time 't' in s=ut+0.5at^2 is the total time since the projectile launched, not the elapsed time. Similarly the 'u' is the initial velocity, not the current velocity. My code is doing Euler integration, using the elapsed time since the last frame. First it integrates the current velocity with v += a*t, then it integrates the position with p += v*t. –  Niall Mar 10 '11 at 1:49
    
Oh I see, thanks! –  XSL Mar 10 '11 at 16:09

What you are doing is actually the starting point of what quite a few physics packages do, and that is used a fixed time step for your updates. By dividing the value by 60 you are using a fixed time step.

What using the elapsed time would do is allow that to happen even when you are Not running at 60fps. You would use the actual elapsed time instead of 1/60.

As for the error to why your switching didn't work as expected is I believe because you are using TotalSeconds.. Which is probably the number of seconds your game has been running instead of the number of seconds since the last frame update. Aside from that it looks like

share|improve this answer
2  
The TotalSeconds is the number of seconds since the last frame update since he's using ElapsedGameTime.TotalSeconds and not TotalGameTime.TotalSeconds –  Ray Dey Mar 7 '11 at 18:19

You could try to do more accurate integration. What you have is called the Euler method, and you have to use really small times steps to make it accurate. The next best method is to evaluate the acceleration at the beginning and end of the time step, i.e. compute the acceration at time t0, then advance at that velocity and acceleration by delta T. Then recalculate velocity/acceleration at that time step. Now take the average of the two, to advance from to to t0+dt. This is second order accurate rather than first, so errors won't accumulate nearly as fast.

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.