現在、次を使用して、互いに跳ね返る 2 つの球を計算しています。これは、3D オブジェクトを使用する 2D ピンポン ゲームで使用されています (頭を 3D に巻き付けようとしています)。ほとんどすべてが正常に機能しますが、時々 (通常、X または Y の速度が同じ方向に移動し、一方が他方よりも速い場合)、物理は奇妙なことを行います。
返されたフロートは、ボールが衝突したときに再生されるサウンドを変更するために使用する質量の違いです。誰でも私の計算の間違いを見ることができますか:
internal float ResolveCollision(Ball otherBall)
{
if (otherBall == this) { return 0f; }
if (this.GetBoundingSphere().Intersects(otherBall.GetBoundingSphere()))
{
// Attempt to step the balls back so they are just barely touching
Vector3 dd = Position - otherBall.Position;
dd.Normalize();
Position += dd / 2;
otherBall.Position -= dd / 2;
///http://williamecraver.wix.com/elastic-equations
Vector3 V1 = Velocity;
Vector3 P1 = Position;
float M1 = Mass;
float A1 = getMovementAngle(V1.X, V1.Y);
Vector3 V2 = otherBall.Velocity;
Vector3 P2 = otherBall.Position;
float M2 = otherBall.Mass;
float A2 = getMovementAngle(V2.X, V2.Y);
float CA = getContactAngle(P1, P2);
// Recalculate x and y components based of a rotated axis, having the x axis parallel to the contact angle.
Vector3 V1XR = V1 * (float)Math.Cos(A1 - CA);
Vector3 V1YR = V1 * (float)Math.Sin(A1 - CA);
Vector3 V2XR = V2 * (float)Math.Cos(A2 - CA);
Vector3 V2YR = V2 * (float)Math.Sin(A2 - CA);
//Now solve the x components of the velocity as if they were in one dimension using the equation;
Vector3 V1f = (V1 * (M1 - M2) + 2 * M2 * V2) / (M1 + M2);
Vector3 V2f = (V2 * (M2 - M1) + 2 * M1 * V1) / (M1 + M2);
Vector3 V1fXR = (V1 * (float)Math.Cos(A1 - CA) * (M1 - M2) + 2 * M2 * V2 * (float)Math.Cos(A2 - CA)) / (M1 + M2);
Vector3 V2fXR = (V2 * (float)Math.Cos(A2 - CA) * (M2 - M1) + 2 * M1 * V1 * (float)Math.Cos(A1 - CA)) / (M1 + M2);
//Now find the x and y values for the un-rotated axis by equating for the values when the axis are rotated back.
Vector3 V1fX = V1fXR * (float)Math.Cos(CA) + V1YR * (float)Math.Cos(CA + MathHelper.PiOver2);
Vector3 V1fY = V1fXR * (float)Math.Sin(CA) + V1YR * (float)Math.Sin(CA + MathHelper.PiOver2);
Vector3 V2fX = V2fXR * (float)Math.Cos(CA) + V2YR * (float)Math.Cos(CA + MathHelper.PiOver2);
Vector3 V2fY = V2fXR * (float)Math.Sin(CA) + V2YR * (float)Math.Sin(CA + MathHelper.PiOver2);
// Add it all up
Vector3 nV1 = V1fX + V1fY;
Vector3 nV2 = V2fX + V2fY;
///////////////////////////////////////////
// Correct Velocity & Move apart
//////////////////////////////////////////
Velocity = v3check(nV1, MAXSPEED, -MAXSPEED);
otherBall.Velocity = v3check(nV2, MAXSPEED, -MAXSPEED);
// Step the balls forward (by there Velocity) just a bit so they are no longer touching
Position += Velocity * _lastDT * .25f;
otherBall.Position += otherBall.Velocity * otherBall._lastDT * .25f;
return BMDMath.toFloat(Mass - otherBall.Mass);
}
return 0f;
}
いくつかの角度を変換する次のヘルパー メソッドがあります (これが問題の原因である可能性があります。
private static float getMovementAngle(double vx, double vy)
{
return MathHelper.ToDegrees((float)Math.Atan2(vy, vx));
}
private static float getContactAngle(Vector3 o1, Vector3 o2)
{
Vector3 d = o1 - o2;
return MathHelper.ToDegrees((float)Math.Atan2(d.Y, d.X));
}