【问题标题】:How do I keep the jump height the same when using delta time?使用增量时间时如何保持跳跃高度相同?
【发布时间】:2013-06-23 17:52:56
【问题描述】:

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

变量:

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

逻辑代码:

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

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

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

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

【问题讨论】:

  • “delta”是什么单位/类型?

标签: c++ time gravity delta


【解决方案1】:

计算新位置的公式为:

position = initial_position + velocity * time

考虑到重力会根据函数降低速度:

velocity = initial_velocity + (gravity^2 * time)

注意:在这种情况下,重力与重力不同。 那么最后的公式就变成了:

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

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

帧率越低,delta 的值就越大,因此角色会跳得更高。解决办法是改变

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

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

编辑:

上面应该给出一个很好的估计,但它并不完全正确。假设p(t) 是时间t 之后的位置(在本例中为高度),则速度由v(t) = p'(t)', and the acceleration is given bya(t) = v'(t) = p''(t)` 给出。因为我们知道加速度是恒定的;即重力,我们得到以下结果:

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

如果我们现在计算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

原始代码没有考虑delta 的平方或额外的术语g*delta*t*。更准确的方法是存储增量的增量,然后使用上面给出的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;
        }
    }
}

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

【讨论】:

  • 谢谢!尽管示例代码对我来说并没有真正奏效,因为我不知道verticalVel在哪里生效。但是您的回答仍然帮助我找到了解决问题的方法。
  • 抱歉,错过了那一行。它没有效果。在我的更新中删除了它。
【解决方案2】:

“增量时间”是指可变时间步长吗?例如,在每一帧,您计算的时间步长可能与前一帧完全不同?

如果是这样,不要

阅读:http://gafferongames.com/game-physics/fix-your-timestep/

TL;DR:对内部状态使用固定时间步长;如果需要,插入帧。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-11
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    相关资源
    最近更新 更多