使用增量时间时,如何保持跳跃高度不变?

use*_*924 4 c++ time gravity delta

我正在使用delta时间,所以我可以使我的程序帧速率独立.但是我无法获得相同的跳跃高度,角色总是在较低的帧速率下跳得更高.

变量:

const float gravity = 0.0000000014f;
const float jumpVel = 0.00000046f;
const float terminalVel = 0.05f;
bool readyToJump = false;
float verticalVel = 0.00f;
Run Code Online (Sandbox Code Playgroud)

逻辑代码:

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

verticalVel += gravity * delta;
y += verticalVel * delta;
Run Code Online (Sandbox Code Playgroud)

我确定增量时间是正确的,因为角色水平移动很好.

无论帧速率如何,我如何让我的角色跳跃?

TAS*_*TAS 5

计算新职位的公式是:

position = initial_position + velocity * time
Run Code Online (Sandbox Code Playgroud)

考虑到根据功能降低速度的重力:

velocity = initial_velocity + (gravity^2 * time)
Run Code Online (Sandbox Code Playgroud)

注意:在这种情况下,重力与重力不同.最终公式变为:

position = initial_position + (initial_velocity + (gravity^2 * time) * time
Run Code Online (Sandbox Code Playgroud)

从上面的等式可以看出,initial_position和initial_velocity不受时间的影响.但在你的情况下,你实际上设置的初始速度等于-jumpVelocity * delta.

帧速率越低,值越大delta,因此角色会跳得越高.解决方案是改变

if(readyToJump){
    verticalVel = -jumpVel * delta;
    readyToJump = false;
}
Run Code Online (Sandbox Code Playgroud)

if(readyToJump){
    verticalVel = -jumpVel;
    readyToJump = false;
}
Run Code Online (Sandbox Code Playgroud)

编辑:

以上应该给出一个很好的估计,但它并不完全正确.假设p(t)在时间之后是位置(在这种情况下是高度)t,那么由v(t) = p'(t)', and the acceleration is given by(t)= v'(t)= p''(t)'给出的速度.因为我们知道加速度是恒定的; 即重力,我们得到以下:

a(t) = g
v(t) = v0 + g*t
p(t) = p0 + v0*t + 1/2*g*t^2
Run Code Online (Sandbox Code Playgroud)

如果我们现在计算p(t+delta)-p(t),即从一个实例到另一个实例的位置变化,我们得到以下结果:

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
Run Code Online (Sandbox Code Playgroud)

原始代码没有考虑平方delta或额外的术语g*delta*t*.更准确的方法是存储delta的增加,然后使用p(t)上面给出的公式.

示例代码:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:我没有编译或测试上面的代码.