2012-01-27 6 views
1

私は、Javaでプログラムを作っています。ここで、円はお互いに跳ね返り、互いに向かって重力をかけることができます。2D物理シミュレーションで重なっているボディ

ほとんどの場合(画面の円はほとんどありません)、目立つバグはありません。この問題は、画面に大量の円がある場合に発生します。場合によっては、混雑しすぎるとサークルが重複することがあります。まるで他のすべてのサークルの重さがサークルを一緒に粉砕して重なり合っているかのようです。もちろん、そこにはサークルの重さがどれくらいか分からないので、実際には粉砕していません。おそらく、衝突の解決を処理するロジックは混雑した状況を処理できません。

円は配列に格納され、各円はforループを使用して配列を通過し、それ自体を他の円と比較します。この円の中心と他の円の中心との間の距離がそれらの半径の合計よりも小さい場合、円は衝突している。両方の円の速度は、衝突の式を使用して更新されます。

円が囲まれていると、後ろの円に更新されたベロシティが表示されることがあります。言い換えれば、2つのサークルは、既に接触していても、互いに向かって移動するように指示されます。このようにオーバーラップすると、オーバーラップを元に戻さない理由はわかりません。

私は重なり合っている場合、それらが重なっている距離を見つけて、それらを互いに離して移動することで、タッチシナリオを復元しようとしました。それぞれがオーバーラップ距離の半分を動かします。これはサークルの速度を変更せず、その位置だけを変更します。

これでも問題は解決しません。円が囲まれ、隣接する円のいずれかと重なっている場合、その位置は重複しないように変更されますが、この新しい位置によって別の円と重なることがあります。同じ問題。

重力が無ければ、最終的に広がって重なり合う問題は解決されますが、重力が原因でこのことが回避されます。

詳しい情報:衝突後に新しい速度を計算する際

重力を考慮しません。

答えて

4

問題を引き起こしていることについてのあなたの嫌悪感のようなサウンドは、どちらの場合でも正しいです。

残念ながら、この問題を簡単に解決する方法はありません。これは、完全に衝突検出&のコードを最初から書き直すことを意味します。最初の衝突の正確なタイミングを計算し、それまでのものだけを更新し、衝突を解決して(速度の更新を行います)、次の衝突の正確なタイミングを計算してから、繰り返す必要があります。

良い物理エンジンは難しいですが、このテーマについて市場に多くの教科書があるという良い理由があります!

問題の安価な「修正」は、更新の時間間隔を短縮することです。物理を33msステップ(〜30fps)で更新する代わりに、16msステップ(〜60fps)で更新してみてください。これにより問題は解決されませんが、発生する可能性は低くなります。タイムステップを半分にすることで、プロセッサが物理的な更新を行うのに費やす時間も2倍になります!

安価な修正プログラムを使用する場合、最適なタイムステップは、衝突が発生する頻度によって決まります。衝突が増えるほど時間ステップが小さくなることを意味します。どのくらいの頻度で衝突が発生するかは、基本的には、サークルがどのくらい速く動くか、および人口密度(サークルでどれくらいの領域が満たされているか)によって決まります。

更新:「正しい」アプローチに関するもう少し情報。

更新はこのような何かを行くだろう:

  1. スタートフレームを更新します。時間がtFまで更新したいとします。
  2. すべての円のペアについて、衝突が発生すると予想されたときに動きます(他のすべての円は無視されます)。今回はtCとしましょう。
  3. tCの最小値を見つけます。これが円ABの衝突の場合、その衝突をcABとしましょう。
  4. tC < = tFの場合、すべての円を時刻tCまで更新します。それ以外の場合は、手順6に進みます。
  5. 解決方法cAB。手順2に戻ってください!
  6. すべてのサークルを時刻tFに更新してください。

想像のとおり、これはかなり複雑になる可能性があります。ステップ2は、非円形オブジェクト(特に、角運動量などのものを含めば)には非常にトリッキーな(しかも共謀的に高価な)ことがありますが、スピードを上げるためにここでできることはたくさんあります。また、手順2と5の間で何回ループするかを知ることは基本的に不可能です。

私が言ったように、良い物理シミュレーションを行うのは難しいです。それをリアルタイムで行うことはさらに困難です!

+0

返信いただきありがとうございます。私は安い修理を最初に試してみたいと思います。今のところです。私はおそらく最終的に適切な修正をしたいと思うでしょう。あなたは「時間を逆転」しなければならないと言っていますか?プログラムが衝突を検出すると、サークルはすでに重複している可能性があります。だから、円が触れていて、衝突を解決したときの速度が何であったかを把握すれば、これは私の問題を解決するでしょうか?これは複雑になるようです。彼らは円が衝突するのを加速したので、衝突に関与していないサークルの「時間を逆転させる」必要がありますか? – Croolsby

+0

私の答えは、適切なアプローチに関するいくつかの情報で更新されました。時間を逆にする必要はありませんが、将来の衝突を予測し、任意の量だけ時間を進めることができる必要があります。 – vaughandroid

関連する問題