我正在尝试在可变时间步长(准确地说是 Slick2D)中复制为固定时间步长系统(60 FPS)编写的Sonic 物理引擎的逻辑。
在原始按下跳跃按钮时,玩家的velocity.y
设置为 -6.5,并且每个刻度都添加 0.21875velocity.y
以模拟重力。
每次调用我的逻辑更新时,都会传递一个时间增量参数,指定已传递多少毫秒。如果经过的毫秒数比我预期的要多,那么我重复更新逻辑,传递一个最多为 1 的“内部增量”,或者如果我们正在处理目标帧的“剩余”则更少。
例如,如果我们预计一帧需要 16 毫秒,而它确实需要 16 毫秒,则循环将迭代一次并thisMiniTick
作为 1 传递。如果增量不是 16 毫秒而是 40 毫秒,则循环将执行 3 次,传递 1、1,最后传递0.5。
我错误地认为在每个内部更新循环中我都可以做到velocity.y += (gravity * thisMiniTickRelative)
,但这不起作用。在较快的帧速率上,没有施加足够的重力导致更高的跳跃,而在较慢的帧速率上,跳跃较低(尽管没有那么明显)。
有没有一种方法可以适用于几乎所有的帧速率,或者我必须求助于设置上限和下限delta
吗?
“内部更新”循环:
float timeRemaining = delta/1000f;
while(timeRemaining > 0)
{
float thisMiniTick = Math.min(timeRemaining, 1f / FRAMES_PER_SECOND);
float thisMiniTickRelative = thisMiniTick / (1f / FRAMES_PER_SECOND);
updateInput(container, game, thisMiniTickRelative);
if (playerAirState)
{
playerVelocity.y += (GRAVITY * thisMiniTickRelative);
}
clampPlayerVelocity();
playerPosition.add(playerVelocity);
doCollisions();
timeRemaining -= thisMiniTick;
}