スタック オーバーフロー コミュニティの助けを借りて、かなり基本的でありながら楽しい物理シミュレーターを作成しました。
マウスをクリックしてドラッグすると、ボールが発射されます。それは跳ね返り、最終的に「床」で止まります。
追加したい次の大きな機能は、ボールとボールの衝突です。ボールの動きは、x と y の速度ベクトルに分割されます。重力 (ステップごとに y ベクトルの小さな減少) があり、摩擦 (壁との衝突ごとに両方のベクトルの小さな減少) があります。ボールは正直、驚くほどリアルに動きます。
私の質問には2つの部分があると思います:
- ボール同士の衝突を検出する最良の方法は何ですか?
各ボールを反復処理し、半径が重複しているかどうかを確認するために他のすべてのボールをチェックする O(n^2) ループがありますか? - ボール同士の衝突を処理するには、どの方程式を使用すればよいですか? 物理学 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 と衝突するかどうかをチェックする必要はありません。また、それ自体との衝突のチェックもスキップします)。 )。
次に、私のボール クラスには、collliding() メソッドと 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 つは、ボールがよりリアルに転がるように角運動量です。他の提案はありますか?コメントを残す!