Basically, I've been experimenting with some simple physics in XNA 4.0, and I've become completely stuck while trying to make objects rebound correctly. I've tried to use my own knowledge of mechanics and failed, so I eventually resorted to looking up formulae on Wikipedia. These aren't working. My circular objects seem to transfer their momentum only if they feel like it, and often add a few radians to their final directions just to make it look cooler (or something... I didn't ask).
Anyway, here's the code for the collision:
- Code: Select all
public void Collide(Item Item1, Item Item2)
Vector2 TotalSpeed = Item1.Speed - Item2.Speed;
float u1 = GetHypoteneuse(TotalSpeed);
float m1 = Item1.Mass;
float m2 = Item2.Mass;
//The location of the overall centre of mass before(1) and after(2) the collision.
Vector2 MassCentre1 = ((Item1.Position * m1) + (Item2.Position * m2)) / (m1 + m2);
Vector2 MassCentre2 = (((Item1.Position + Item1.Speed) * m1) + ((Item2.Position + Item2.Speed) * m2)) / (m1 + m2);
//The angle through which the overall centre of mass was deflected
float MassDeflection = XYToBearing(MassCentre2 - MassCentre1);
//The angles from Item1's initial direction through which Item1 and Item2 have been deflected
float Deflection1 = (float)Math.Atan((m2 * Math.Sin(MassDeflection))/(m1 + (m2 * Math.Cos(MassDeflection))));
float Deflection2 = (float)(-1 * MassDeflection);
//The final velocities of Item1 and Item2
float v1 = (float)(u1 * ((Math.Sqrt(Math.Pow(m1, 2) + Math.Pow(m2, 2) + (2 * m1 * m2 * Math.Cos(MassDeflection)))) / (m1 + m2)));
float v2 = (float)(u1 * ((2 * m1) / (m1 + m2)) * Math.Sin(MassDeflection / 2));
Item1.Speed = new Force(Deflection1, v1).ForcetoXY() - Item2.Speed;
Item2.Speed += new Force(Deflection2, v2).ForcetoXY();
Those lines that start "float Deflection1/2" and "float v1/2" are the formulae copied from here.
Some clarity, if needed:
- GetHypoteneuse(Vector2 Value) returns Sqrt(Value.X^2 + Value.Y^2).
ForceToXY() converts a Force object (with magnitude and angular direction) into a Vector2 (I've used my Force type here for convenience, not because I'm simulating actual forces)
XYToBearing(Vector2 Value) converts Value into a bearing, with 0 pointing at the top of the screen and 2(PI) pointing at the bottom (I'm using radians because that's XNA's default).
Thanks to anyone who helps