zerostrain
zerostrain

Reputation: 43

How to use deltaTime to produce consistent movement

I want to create a 2d game with velocity based movement. As the code currently is, I am using delta time to make the velocity changes consistent between framerates. When jumping, however, the jump height is very slightly different each jump (up to about 3 pixels difference with a maximum height of about 104 pixels) when running on a 144hz monitor, but when I switch to a 60hz, the jump height instantly increases by about 5 pixels average with a maximum height of about 109 pixels.

I have tried many different variations of what values I should normalise with delta time but I always come back to this one being the closest to the output I want.

static bool grounded = false;  

if (!grounded) {  
    velocity.y += (5000.0f * deltaTime);   //gravity  
}  

if (keys[SPACE_INPUT]) {       //jump command  
    if (grounded) {  
        position.y = 750;  
        velocity.y = -1000.0f;  
        grounded = false;  
    }   
}  

//Used to measure the max height of the jump  
static float maxheight = position.y;  

if (position.y < maxheight) {  
    maxheight = position.y;  
    std::cout << maxheight << std::endl;  
}

//if at the top of the screen  
if (position.y + (velocity.y * deltaTime) < 0) {  
    position.y = 0;  
    velocity.y = 0;  
    grounded = false;  

//if at the bottom of the screen minus sprite height  
} else if (position.y + (velocity.y * deltaTime) >= 800.0f - size.y) {  
    position.y = 800 - size.y;  
    velocity.y = 0;  
    grounded = true;  

//if inside the screen  
} else {  
    grounded = false;  
    position.y += (velocity.y * deltaTime);  
}  

I would expect the result to be that the sprite moves up the same height each time regardless of refresh rate but instead it moves up a varying amount, even on the same refresh rate and especially so between different rates.

Upvotes: 2

Views: 1601

Answers (1)

Jeffrey
Jeffrey

Reputation: 11410

The accepted technique is as follow:

// this is in your mainloop, somewhere
const int smallStep = 10;

// deltaTime is a member or global, or anything that retains its value.
deltaTime += (time elapsed since last frame); // the += is important

while(deltaTime > smallStep)
{
    RunPhysicsForTenMillis();
    deltaTime -= smallStep;
}

Basically, what you do is: each time you get to run your physics, you process a given number of steps of, say 10ms, that add up to the time between frames. The runPhysicsForTenMillis() function will do similar to what you have above, but for a constant delta time (10 ms is my suggestion).

This gives you:

  • determinism. No matter your FPS, the physics will always run with the same exact steps.
  • robustness. Event if you have a long disk access, or some streaming delays, or anything that makes a frame longer, your objects won't jump into outer space.
  • online-play readiness. Once you go to online multi-player, you'll have to pick an approach. For many techniques like input-passing, the small steps will be significantly easier to make online.

Upvotes: 10

Related Questions