2Dプラットフォーマー:なぜ物理学をフレームレートに依存させるのですか?


12

「スーパーミートボーイ」は、最近PC用に登場した難しいプラットフォーマーであり、優れた制御とピクセル単位の完璧なジャンプが必要です。ゲーム内の物理コードはフレームレートに依存しており、60fpsにロックされています。これは、コンピューターがゲームをフルスピードで実行できない場合、物理現象が異常な状態になり、(特に)キャラクターの実行速度が遅くなり、地面に落ちてしまうことを意味します。さらに、vsyncがオフの場合、ゲームは非常に高速に実行されます。

2Dゲームプログラミングの経験者は、ゲームがこのようにコーディングされた理由を説明できますか?一定の速度で実行される物理ループは、より良い解決策ではありませんか?(実際には、一部のエンティティはフレームレートに関係なく正常に移動し続けるため、物理ループはゲームの一部に使用されると思います。一方、キャラクターは正確に[fps / 60]だけ正確に実行されます。)

この実装で気になるのは、ゲームエンジンとグラフィックスレンダリングの間の抽象化が失われることです。これは、モニター、グラフィックスカード、CPUなどのシステム固有のものに依存します。何らかの理由でコンピューターがvsyncを処理できない場合、または正確に60fpsでゲームを実行できない場合、それは劇的に壊れます。レンダリングステップが物理計算に何らかの影響を与えるのはなぜですか?(最近のほとんどのゲームは、ゲームの速度を落とすか、フレームをスキップします。)一方、NESとSNESの昔ながらのプラットフォーマーは、制御と物理の多くを固定フレームレートに依存していることを理解しています。これはなぜですか、フレームレート依存性なしでその静脈にパフォーマーを作成することは可能でしょうか?グラフィックレンダリングを他のエンジンから分離すると、必ずしも精度が失われますか?

質問がわかりにくい場合は、ありがとうございます。


あなたの質問に接しています。ここに、あなたが説明している問題を正確にカバーする素晴らしい記事と、タイムステップとフレームレートを処理する「正しい」方法があります。gafferongames.com/game-physics/fix-your-timestep
num1

実際、彼らがこのようにしてくれたことに本当に驚きました。フレームレートを信頼できる主にコンソール用に構築されたためだと思います。残念!
イアン

回答:


7

どうして?

いくつかの理由があります。選んでください。迅速かつ簡単に実装できます。彼らはゲームプレイに重点を置き、ほとんどの場合に発生しない可能性のあるエッジケースに焦点を当てませんでした。

その理由を説明するのにかなり良い仕事をしました。主題カバーするトピックがたくさんあることに気づいたと思います。私がリストしたもの以外に満足のいく答えが見つかるかどうかはわかりません。


「彼らはそれ以上よく知りませんでした」は、「Jack is a Fool」でそのアプローチをとった理由を説明しています。しかし、私はすべてのロジックで最後のフレームからdtを呼び出すことに大きく依存しています。しかし-浮動小数点座標を使用すると、奇妙で​​再現しにくいバグが発生する可能性があります
-lochok

4

SMBはもともと、すべてのXbox360で60 fpsで実行できると想定しても安全なコンソールゲームでした(一部のPALプレーヤーでは50になります)。固定タイムステップを仮定すると、コードがかなり簡単になります。

可変タイムステップ-'pos + = velocity * timestep'で多くのことをスケーリングするのは簡単ですが、加速度や加速度の変化率などを扱う場合、正確に行うのは非常に難しくなります。

理論的には、ゲームプレイとレンダリングを分離することは素晴らしい解決策ですが、それを適切に(適切な補間を使用して)実装することは非常に注意が必要であり、事態は簡単に乱雑になります。この手法が実際のゲームで使用されることはほとんどありません(一部の大規模なゲームでは実行されますが、特にRTSゲームですが、ネットワークゲームの同期には使用されます)。

固定の画面解像度と固定のフレームレートを設計する場合、スクロールをさらにスムーズにするためにできることがもう1つあります。ゲームがフレームあたりのピクセル数でスクロールすることを確認できます-フレームあたりのピクセル数をスクロールすることで発生する「サブピクセルウォブル」を回避できます。


1

明らかな解決策は、2つのループを並行して実行することです-60分の1秒ごとのレンダリングと60分の1秒ごとのゲームループ。

しかし、Flash(AS3、Super Meat Boyが作成されたと確信している)での私の経験では、スケジューラーは必ずしも非常に正確ではありません。精度も環境に大きく依存します。スタンドアロンのフラッシュプレーヤーでは、サブミリ秒の解像度を持つ場合があります。ただし、一部のWebブラウザーで実行すると、フレームレートの精度になります。

したがって、レンダリングループとゲームロジックループを分離するための最も近い方法は、すべての動きを時間ベースにすることです(そして、最後のフレームから経過した時間に基づいて各フレームを実行します)。これにより、いくつかのより複雑な数学を導入できます(設定された間隔でオブジェクトの速度に追加するのではなく、重力を連続的に適用するなど)。ゲームが1秒遅れることがあり、プレイヤーが1ステップで200ピクセル移動するため、衝突の検出と応答はさらに複雑になる可能性があります。プログラマがフレームベースの衝突検出(タイムステップごとに衝突をチェックする)を行っていた場合、時間ベースの衝突検出にも切り替える必要があります。そして、自然に感じたい場合は、上記の重力法を使用する必要があります。これにより、オブジェクトの動きは曲線(線ではなく)になります。


2
オリジナルのミートボーイはフラッシュゲームでした。Super Meat BoyはC ++ゲームです。
アルカゴン

0

もう2D PCゲームを60fpsでプレイすることを要求することはあまりないと思います。現在、ほとんどの2Dゲームはハードウェアアクセラレートされているため、個人的にはfps要件について心配する必要はありません。

本当の問題は、なぜピクセルベースを使用しないのか、ゲームにはチートとショートカットがいっぱいだということです。

物理学に基づいたゲームを作成している場合(おそらく鳥を投げる?)、答えは明らかですが、スーパーマリオクローンですか?時間ベースの動きは少し大きいかもしれません。


60fpsで再生することは難しくありませんが、ネイティブのリフレッシュレートが50Hz、70-85Hz、および120Hzのディスプレイはまだ簡単に見つかります。

0

彼らが使用している2D物理学で奇妙な動作を避けるために?

正直に推測できます。私は説明を試みます:

ゲームの中心はメインゲームループです。基本的には次のようになります:

while(gameRunning)
{
  updateGame(timestep);
  renderGame(timestep);
}

updateGameはgameStateを更新します。プレーヤーの入力を確認し、プレーヤーの入力をゲームワールドに適用し、物理シミュレーションなどを実行します。

renderGameは、ゲームを描画してアニメーション化します。

これにより、物理更新がレンダリングに結合されます。分離したい場合は、スレッドを使用し、レンダリングとgameUpdateスレッドの各データアクセスをプレーヤーの位置などの共有データに適切に同期する必要があります。これを行うことができます。

別の問題は、物理シミュレーションが安定して実行するために一定のタイムステップを必要とすることです。これは、supermeatboyがどのように動きを計算するかに依存します(繰り返しますが、どのようにそれを行ったかを推測できます;)

素朴なアプローチは次のとおりです(私のゲームで使用している*ため息*):

position=position+speed*timestep;
speed=speed+acceleration*timestep;

これはオイラー統合と呼ばれ、一般的に悪い考えと考えられています。タイムステップが一定でない場合、計算エラーが発生し、シミュレーションの安定性が低下します。オブジェクトが過度の速度で移動したり、すべてではない場合や、画面から壁を飛び抜ける場合があります。タイムステップが一定であっても、オイラー積分により小さな計算エラーが発生します。RK4などの別の統合方法を使用するか、物理エンジンを使用することをお勧めします。

それとは別に、タイムステップが大きくなりすぎると、衝突検出の実行に問題が生じる可能性があります。2つのgameUpdate間の衝突はチェックされないため、オブジェクトは障害物を通過する可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.