Reputation: 2250
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?
Upvotes: 4
Views: 3720
Reputation: 2079
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 by
a(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.
Upvotes: 5
Reputation: 4517
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.
Upvotes: 0