Question

I'm using delta time so I can make my program frame rate independent. However I can't get the jump height it be the same, the character always jumps higher on a lower frame rate.

Variables:

const float gravity = 0.0000000014f;
const float jumpVel = 0.00000046f;
const float terminalVel = 0.05f;
bool readyToJump = false;
float verticalVel = 0.00f;

Logic code:

if(input.isKeyDown(sf::Keyboard::Space)){
    if(readyToJump){
        verticalVel = -jumpVel * delta;
        readyToJump = false;
    }
}

verticalVel += gravity * delta;
y += verticalVel * delta;

I'm sure the delta time is correct because the character moves horizontally fine.

How do I get my character to jump the same no matter the frame rate?

Was it helpful?

Solution

The formula for calculating the new position is:

position = initial_position + velocity * time

Taking into account gravity which reduces the velocity according to the function:

velocity = initial_velocity + (gravity^2 * time)

NOTE: gravity in this case is not the same as the gravity. The final formula then becomes:

position = initial_position + (initial_velocity + (gravity^2 * time) * time

As you see from the above equation, initial_position and initial_velocity is not affected by time. But in your case you actually set the initial velocity equal to -jumpVelocity * delta.

The lower the frame rate, the larger the value of delta will be, and therefore the character will jump higher. The solution is to change

if(readyToJump){
    verticalVel = -jumpVel * delta;
    readyToJump = false;
}

to

if(readyToJump){
    verticalVel = -jumpVel;
    readyToJump = false;
}

EDIT:

The above should give a pretty good estimation, but it is not entirely correct. Assuming that p(t) is the position (in this case height) after time t, then the velocity given by v(t) = p'(t)', and the acceleration is given bya(t) = v'(t) = p''(t)`. Since we know that the acceleration is constant; ie gravity, we get the following:

a(t) = g
v(t) = v0 + g*t
p(t) = p0 + v0*t + 1/2*g*t^2

If we now calculate p(t+delta)-p(t), ie the change in position from one instance in time to another we get the following:

p(t+delta)-p(t) = p0 + v0*(t+delta) + 1/2*g*(t+delta)^2 - (p0 + v0*t + 1/2*g*t^2)
                = v0*delta + 1/2*g*delta^2 + g*delta*t

The original code does not take into account the squaring of delta or the extra term g*delta*t*. A more accurate approach would be to store the increase in delta and then use the formula for p(t) given above.

Sample code:

const float gravity = 0.0000000014f;
const float jumpVel = 0.00000046f;
const float limit = ...; // limit for when to stop jumping

bool isJumping = false;
float jumpTime;

if(input.isKeyDown(sf::Keyboard::Space)){
    if(!isJumping){
        jumpTime = 0;
        isJumping = true;
    }
    else {
        jumpTime += delta;
        y = -jumpVel*jumpTime + gravity*sqr(jumpTime);
        // stop jump
        if(y<=0.0f) {
            y = 0.0f;
            isJumping = false;
        }
    }
}

NOTE: I have not compiled or tested the code above.

OTHER TIPS

By "delta time" do you mean variable time steps? As in, at every frame, you compute a time step that can be completely different from the previous?

If so, DON'T.

Read this: http://gafferongames.com/game-physics/fix-your-timestep/

TL;DR: use fixed time steps for the internal state; interpolate frames if needed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top