2

Pyglet を使用して、Python で小惑星の (一種の) クローンを作成しようとしています。少し凝って、衝突を行うために分離軸定理を実装しようと考えました。私はそれを動作させましたが、問題はそれがひどく遅いことです. プレイヤーが発射する弾丸と画面上の小惑星との衝突を、二重の for ループでテストします。これは 2 次時間だと思いますが、約 6 個の小惑星と 6 個の弾丸になるまでに、フレーム レートは約 60 から 30 fps に低下します。衝突を検出する最適化されていない方法であっても、信じられないほど遅く見えます。

そこで、プロファイラーを実行して、プログラムがハングアップしているコードの正確な場所を特定しました。形状の頂点をワールド空間に変換する方法にハングアップしているようです (原点の周りの形状を定義し、OpenGL コードを使用して描画用のワールド空間に変換します。これが正しい方法だと思います)。OpenGL から変換行列を取得し、それを NumPy 配列に変換してから、各頂点にこの行列を掛けて、変換された頂点を取得します。衝突チェックごとにこれを行うことは注目に値します。以前は XNA を使用していましたが、その中で SAT を実装したとき (そこにも小惑星のクローンを作成しました)、頂点も原点の周りに定義されていたため、変換する必要がありました。世界行列を使用してそれらを。

(0, 0) の周りに頂点を保存して各呼び出しを変換するのが最善ですか、それとも変換された頂点を保存するだけですか? アルゴリズムがこれほど遅くあるべきではないと感じているので、何かの実装を台無しにしたことに賭けても構わないと思っています。私がプロファイリングに長けていれば (私はそれにかなり慣れていません)、より完全な全体像を把握できるかもしれませんが、皆さんが何らかのアイデアを持っていることを望んでいました.

すべての衝突ロジックが発生する Shape クラスを含むファイルへの直接リンクを次に示します: shape.py。プロファイラーがボトルネックとしてマークしたように見える特定のメソッドは、__get_transformed_verts でした。もちろん、そこからレポ全体にアクセスすることもできますが、まだコメントされていないものがかなりあることに注意してください。

4

1 に答える 1

3

Nico がコメントで示唆しているように、高速化を実現する簡単な方法は、最初に単純なジオメトリを確認することです。小惑星のクローンの場合、円 (または 3D の場合は球) が適していると思います。円 (少なくとも実際の形状をカバーするのに十分な大きさ) が重ならない場合は、より高価なジオメトリ テストを行う必要はありません。

多くのオブジェクトがある場合、フレームごとに n*n テストを実行することは避けたいと思うでしょう。空間分割構造/アルゴリズムを見てください。2D で多数の移動オブジェクトを使用する最も単純なスキームは、グリッドです。次に、同じグリッド セルまたは隣接するグリッド セルに属するオブジェクトの衝突をテストするだけで済みます。

私が気付いたもう 1 つの点は、衝突をテストするたびに、変換された頂点を生成することです。circle-circle テストに失敗したオブジェクトごとに、タイムステップ (フレーム) ごとに 1 回だけ生成する方が高速です。

于 2013-05-10T11:26:36.220 に答える