固定タイムステップシステム(60 FPS)用に作成されたSonic物理エンジンのロジックを可変タイムステップ年齢(正確にはSlick2D)でコピーしようとしています。
オリジナルでは、ジャンプボタンを押すと、プレーヤーのvelocity.y
値が-6.5に設定され、各ティック0.21875がvelocity.y
モデルの重力に追加されます。
ロジックアップデートが呼び出されるたびに、何ミリが経過したかを指定するタイムデルタパラメータが渡されます。予想よりも多くのミリ秒が経過した場合は、更新ロジックを繰り返し、ターゲットフレームの「余り」を処理している場合は最大1以下の「内部デルタ」を渡します。
たとえば、フレームに16ミリ秒かかると予想され、 16ミリ秒かかる場合、ループは1回繰り返され、1として渡さthisMiniTick
れます。デルタが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;
}