再利用可能なトップダウン衝突クラス


8

私は最近、モノゲームを始めて、簡単なトップダウンゲームに取り組んでいます。
マウスを追跡するための動きと回転を整理しましたが、衝突に悩まされています。
私が知りたいのは、基本的に次の2つです。

  1. 衝突を処理する最良の方法は何でしょうか?Rectangle.Intersects(Rectangle1, Rectangle2)重なり合う四角形が返されることはわかっていますが、上から下への移動はx / y軸上にあるため、衝突が発生している場所を知りたいので、プレーヤーが取得しないような「壁のスライド」を作成できます壁で立ち往生。
    プレーヤーのx / y座標をソリッドオブジェクトの座標と照合して確認し、ソリッドオブジェクトの境界に入る場合は、プレーヤーを以前の位置にスローしますか?あなたは何を提案しますか?
  2. すべてのソリッドやnpcなどに衝突を適用する最良の方法は何でしょうか?私は現在gameObject、すべてのオブジェクトが継承するクラスを作成し、そこで衝突を処理することを考えています。

読んでくれてありがとう、誰かが私にいくつかのヒントをくれることを願っています。


2番目の質問についての考えについては、ゲームアーキテクチャに関するこの回答をご覧ください。
Andrew Russell

回答:


9

一般に、ほとんどの物理エンジンがこの問題を処理する方法は、交差するオブジェクトを分離することです


したがって、オブジェクトが四角形( "Axis Aligned Bounding Boxes"とも呼ばれます)で表され、それらが次のように特定のフレームに衝突する場合:

衝突


次に、各軸の相互浸透の量を測定します。次に、相互侵入量が最も少ない軸を選択し、その軸に沿ってオブジェクトを分離します。

分ける


次に、これを「衝突」として登録し、適切なダイナミクスを適用します。

たとえば、壁に沿ってスライドする場合は、分離した軸(上の図ではX軸)の速度をゼロにして、他の軸の速度はそのままにします。

ただし、摩擦を適用したり、オブジェクトを跳ね返らせたりすることもできます。


これは、これをより詳細に行う方法を示す優れたインタラクティブなチュートリアルです。

ただし、この道をはるかに下る場合(単純なAABB衝突以外のもの)、Farseer Physicsなどの既存のエンジンの使用を検討することをお勧めします。


最後に、実装に関する注意事項(FarseerルートをRectangle使用しない場合):int値を使用します。これらの値は、ほとんどの場合、物理学を行うのに適切ではありません。代わりにAABBを使用する独自のクラスを作成することを検討してくださいfloat

あなたの2番目の質問は、ここでのゲームアーキテクチャに関する以前の回答でかなりよく答えられているので、ここでは繰り返しません。


理解できないことがあるかもしれませんが、このアプローチには欠陥がありますか?ここで問題を説明しました:jmp.sh/jEW2lvRこれは時々奇妙な振る舞いを引き起こすでしょう。
BjarkeCK 2014年

@BjarkeCK:はい、そのようなケースを処理するには追加の作業が必要です。私はそれらを適切に処理する方法を完全に説明するのに十分に精通していません(私はただFarseerを使用してそれを1日と呼んでいます)。おそらくこのリンクの「セクション5」をご覧ください
Andrew Russell

1

1:私は比較的単純なトップダウンアクションゲームにも取り組んでおり、1週間(-s?)の苦労の後、衝突の検出と応答に一種の段階的なアプローチを使用することになりました。主な理由は、最短の相互浸透を使用すると、移動オブジェクトが以前にはなかった新しい位置への「テレポーテーション」が発生する場合があるためです。

つまり、オブジェクトが移動したい場合、

  1. オブジェクトの位置+ moveAmountベクトルでオブジェクトのバウンディングボックスを作成し、一種のターゲットバウンディングボックスを作成します
  2. 次に、このターゲットバウンディングボックスをチェックして、ゲームオブジェクト、タイルなどとの交差がないか確認します。交差がある場合は、それらを新しいリストに追加し、現在のフレームで発生する可能性のあるすべての衝突を保持します。
  3. 交差がない場合、オブジェクトは移動します。交差点があれば
  4. 必要な動きを「ステップ」に分割しました。次に、持っているステップ数のループを実行します。各ステップでオブジェクトを1ピクセルだけxとy方向に移動します。
  5. 各ステップで、すべての新しい投影位置の衝突をチェックし、何もない場合は、ステップの移動ベクトルを最終的な移動ベクトルに追加します。
  6. 衝突がある場合(交差するとtrueが返されます)、移動するオブジェクトの前の位置(前のステップの位置)と、衝突しているものを比較します。
  7. この以前の位置に応じて、競合する軸に沿った移動を停止します(たとえば、移動するオブジェクトが衝突するオブジェクトに上から来る場合、移動ベクトルのy値を0に設定します)。
  8. これを連続するステップごとに繰り返し、調整されたステップベクトルを追加して、衝突が発生することなくオブジェクトを移動するために安全に使用できる1つの最終調整済みmoveAmountベクトルを作成します。

このアプローチは、オブジェクトが前の位置を修正するために「跳ね返る」ことを確実にし、壁、オブジェクト、何であれスライドすることを可能にします。

2:私自身、何でも使用できる静的衝突クラスを使用しています。それは衝突検出とベクトル調整メソッドを保持し、ほとんど何でも呼び出すことができます。これらのメソッドが「マスター」ゲームクラスから呼び出されるか、オブジェクトサブクラスによって呼び出されるかは、私の場合、実際には問題になりません。これは、衝突クラスが、移動するオブジェクトが交差するすべての長方形のフレームごとに新しいリストを作成するためです。これらの長方形は、タイル、装飾、NPCなど、境界があり、基本的に衝突可能なものであれば何でもかまいません。これは、衝突可能なすべてのゲームオブジェクトに必要なのは、境界矩形を持つことです。それらがある場合、衝突クラスが残りを処理します。

これが理解できたことを願っています。


0

1:私はこれを解決する手法をうまく使用しました。速度と位置を使用して、衝突を発見し、位置が正確な衝突点に非常に近くなるまで繰り返します。

これは最初の質問の回答の一部ではありませんが、互いに衝突する可能性のあるオブジェクトが多数ある場合は、四分木を使用してパフォーマンスを向上させる必要があります。ここには多くの例を含む非常に優れたチュートリアルがあります

2:私は常にEntity-Systemsをお勧めします。

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