15

重力のあるゲームは、プレイヤー、モンスター、オブジェクトなどの動くものと床との関係をどのように処理しますか? プレーヤーは常に床に「落ち」、跳ね返されていますか?

私が見つけた衝突に反応する2つの方法は、プレイヤーを衝突前の以前の場所に戻すことと、移動する前に新しい位置をテストして衝突が発生するかどうかを確認することですが、これらのいずれかがどのように機能するかわかりません上向きに上昇し、プレーヤーを持ち上げることができる必要があるプラットフォームに対処できます。これは 2D ゲーム デザインの観点から見ていますが、3D ゲーム デザインでも同じ問題が発生するのではないかと想像します。ヒントはありますか?チェックアウトする必要がある参照はありますか?ありがとう。

4

5 に答える 5

18

基本的な情報については、 GameDev.net の Gravity FAQを確認してください。

あなたはゲームを作っているのであって、非常に正確な物理モデラーではないので、オイラーの統合を行うことで逃げることができます。精度の必要性が高まる場合、私が使用していると思われる最も一般的な統合方法は、ルンゲクッタ (RK4) 統合です。単純なゲームでは必要ない可能性が高いですが、より高度な物理シミュレーションや 3D ゲームでは確実に使用されます。RK4 を使用する場合の欠点は、複雑さがわずかに増し、速度がわずかに遅くなることです。それは非常に正確ですが、今のところ、古き良きオイラーに固執しましょう。

「弾む球技に重力を適用するにはどうすればよいですか」という同様の質問をしたところ、いくつかの適切な回答が得られました。最初に行うことは、ゲームの任意の重力定数を選択することです。私の弾むボール アプリケーションでは、デフォルトの重力定数 2000px/s を使用しています。この重力定数を使用して、特定のゲームで目的の効果を得ることができます。

次に、ゲームをレンダリングし、ゲーム オブジェクトを個別に更新していることを確認します。これは、ゲーム内のオブジェクトが高速のコンピューターでは非常に速く動き、低速のコンピューターでは遅くなるのを防ぐためです。オブジェクトが動き回る物理学と速度がコンピューターの速度に依存しないようにする必要があります。これに関する良い記事はGame Physics: Fix your timestep! です。.

では、どうすればよいのでしょうか。Update メソッドを最後に呼び出してから経過した時間を追跡します。直接必要ではありませんが、2 つのスレッドを作成しました。ゲームの更新スレッドとレンダリング スレッドがあります。更新スレッドは、ゲーム オブジェクト内の位置の更新を制御します。更新スレッドは、前回呼び出された時刻と現在の時刻を認識し、そこから update メソッドが呼び出されてからの経過時間を計算します。

重力を適用するには、オブジェクトの Y 速度に、重力定数に経過時間を掛けた値を単純に加算します。

private long previousTime = System.currentTimeMillis();
private long currentTime = previousTime;

public void updateGame()
{
    currentTime = System.currentTimeMillis();
    float elapsedSeconds = (currentTime - previousTime) / 1000f; 

    foreach(GameObject gameObject in gameObjects)
    {
        // Apply gravity to velocity vector
        gameObject.velocity.y += (gravityConstant * elapsedSeconds); 

        // Move objects x/y position based off it's velocity vector
        gameObject.position.x += (gameObject.velocity.x * elapsedSeconds); 
        gameObject.position.y += (gameObject.velocity.y * elapsedSeconds);

    }

    checkCollisions();

    previousTime = currentTime;
}

これにより、速度ベクトルに基づいてすべてのオブジェクトが移動し、重力定数に基づいて重力が適用されます。何よりも、コンピューターの速度に関係なく実行できます。

あなたの他の質問に答えるために、はい、オブジェクトは常にyベクトルに重力の「力」を持っています。そのため、常に床に衝突します。ただし、実行したいことの 1 つは、Epsilon 値を使用して、最終的にゲームオブジェクトの速度をゼロにすることです。次に、剪定プロセスの一部としての衝突検出中に、通常、動かないオブジェクトが何かと衝突しているかどうかのチェックをスキップできます (ただし、その逆はありません!)。

私が衝突でやりたいことは、衝突している (互いに貫通している) オブジェクトを見つけたら、それらを分離する最小移動距離 (MTD) だけそれらを押し離すことです。このステップが重要です。そうしないと、オブジェクトが「くっついた」ゲームで頻繁に見られるバグが発生し、ぎくしゃくして動き回ることになります。それらが分離されたら、衝突応答を計算します。

この方法を使用すると、説明した上昇中のプラットフォームのシナリオでうまく機能します。プラットフォームは上昇し続け、gameObject はそれ自体とプラットフォームの間の MTD を使用して分離し、それに伴って自然に上昇します。

衝突応答について助けが必要な場合は、以下を参照することをお勧めします。

于 2009-01-13T02:26:01.773 に答える
2

一部のゲームで使用される 1 つのアプローチはチートです。つまり、歩行と空中で別の状態を用意します。歩いている間、ゲーム エンジンは、歩いている表面の傾斜を判断し、あまりにも急ではない場合は、キャラクターを表面の方向に移動させ、表面に対して適切な垂直方向の配置をキャラクターに与えます。

物理に関しては、 Gamasutra: Advanced Character Physicsで説明されているように、verlet 統合のファンになりつつあります。物理演算の更新方程式を単純化し (速度を追跡する必要はありません!)、衝突を単純化します (速度を調整する必要はありません!)。とはいえ、正確さが必要な場合は、いくつかのニュアンスがあります。

于 2009-01-13T03:43:13.677 に答える
1

私は特にゲームプログラマーではありませんが、これは私の理解です:

  • 「無限フレーム レート」の理想的な世界では、衝突が発生した正確な瞬間に衝突を検出し、標準的な物理学を少し使用して、衝突後の物体の新しい速度と加速度をモデル化します (標準的な高速度を参照)。学校の力学の教科書、または「ゲームプログラマーのための物理学」などのタイトルのさまざまな本)
  • 実際には、フレームレートが固定されているため、ボディは特定の粒度でしか移動しないため、通常、次のフレームでボディが移動する相対パスを事前に計算し、パスが交差します
  • それらが交差する場合、交点は実際には推定値になりますが、ボディが実際に衝突したであろう点のわずかに不正確です。次に、気にせずにその推定値を交点として取り、線形補間して衝突点での速度を取得するか、それらが交差することがわかったので、より正確な計算を実行して、衝突の実際のポイント/時間/速度
于 2009-01-13T01:37:31.793 に答える
1

衝突のモデル化に加えて、エネルギー (またはシミュレーションの複雑さに応じて運動量、または単に速度) の継続的な転送もモデル化することをお勧めします。プレーヤーがプラットフォームに立っているとき、プラットフォームを表すオブジェクトにその情報を保存し、オブジェクトの速度が調整されるたびに、このようにリンクされたプレーヤーまたは他のオブジェクトにその変更を直接適用できます。

于 2009-01-13T02:22:21.437 に答える
1

この主題に関する最も完全な教科書の 1 つは、Christer Ericson によるRealtime Collision Detectionです。彼は仲間のブログも持っています。Eric Lengyel のMathematics for 3D Game Programming and Computer Graphicsも役に立ちます。

于 2009-01-13T01:30:47.937 に答える