Stack Overflowコミュニティの助けを借りて、かなり基本的だが楽しい物理シミュレーターを作成しました。
ボールを発射するには、マウスをクリックしてドラッグします。跳ね返り、最終的には「フロア」で停止します。
追加したい私の次の大きな機能は、ボール同士の衝突です。ボールの動きは、axとyの速度ベクトルに分けられます。私は重力を持っています(各ステップでyベクトルの小さな減少)、私は摩擦を持っています(壁との衝突ごとに両方のベクトルの小さな減少)。ボールは驚くほど現実的な方法で正直に動き回ります。
私の質問には2つの部分があると思います。
- ボール同士の衝突を検出する最良の方法は何ですか?
各ボールを反復し、半径が重複しているかどうかを確認するために他のすべてのボールをチェックするO(n ^ 2)ループがあるだけですか? - ボール同士の衝突を処理するためにどのような方程式を使用しますか?Physics 101
2つのボールの速度x / yベクトルにどのように影響しますか?2つのボールが向かう方向は何ですか?これを各ボールにどのように適用しますか?
「壁」の衝突検出とその結果のベクトルの変更の処理は簡単でしたが、ボールとボールの衝突により多くの複雑さが見られます。壁の場合は、適切なxまたはyベクトルの負の値をとるだけで、正しい方向に進みます。ボールの場合はそうは思いません。
いくつかの簡単な説明:簡単にするために、今のところ完全な弾性衝突で大丈夫です。また、すべてのボールは現在同じ質量ですが、将来的に変更する可能性があります。
編集:参考になったリソース
ベクトルを使用した2Dボールの物理学:Trigonometry.pdfのない2次元の衝突
2dボールの衝突検出の例:衝突検出の追加
成功!
ボールの衝突検出と応答がうまく機能しています。
関連コード:
衝突検出:
for (int i = 0; i < ballCount; i++)
{
for (int j = i + 1; j < ballCount; j++)
{
if (balls[i].colliding(balls[j]))
{
balls[i].resolveCollision(balls[j]);
}
}
}
これは、すべてのボール間の衝突をチェックしますが、冗長なチェックをスキップします(ボール1がボール2と衝突するかどうかをチェックする必要がある場合、ボール2がボール1と衝突するかどうかをチェックする必要はありません。また、それ自体との衝突のチェックもスキップします)。
次に、私のballクラスにcolliding()とresolveCollision()メソッドがあります:
public boolean colliding(Ball ball)
{
float xd = position.getX() - ball.position.getX();
float yd = position.getY() - ball.position.getY();
float sumRadius = getRadius() + ball.getRadius();
float sqrRadius = sumRadius * sumRadius;
float distSqr = (xd * xd) + (yd * yd);
if (distSqr <= sqrRadius)
{
return true;
}
return false;
}
public void resolveCollision(Ball ball)
{
// get the mtd
Vector2d delta = (position.subtract(ball.position));
float d = delta.getLength();
// minimum translation distance to push balls apart after intersecting
Vector2d mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / ball.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2)));
// impact speed
Vector2d v = (this.velocity.subtract(ball.velocity));
float vn = v.dot(mtd.normalize());
// sphere intersecting but moving away from each other already
if (vn > 0.0f) return;
// collision impulse
float i = (-(1.0f + Constants.restitution) * vn) / (im1 + im2);
Vector2d impulse = mtd.normalize().multiply(i);
// change in momentum
this.velocity = this.velocity.add(impulse.multiply(im1));
ball.velocity = ball.velocity.subtract(impulse.multiply(im2));
}
ソースコード:ボールツーボールコライダーの完全なソース。
この基本的な物理シミュレーターを改善する方法についての提案がある場合は、お知らせください!まだ追加していないことの1つは、角運動量です。これにより、ボールがよりリアルに転がります。他に何か提案はありますか?コメントを残す!
Vector2d impulse = mtd.multiply(i);
は、i *正規化されたmtdベクトルでなければなりません。次のようなものVector2d impulse = mtd.normalize().multiply(i);