Saturday 15 October 2011

2-D Simple Elastic collision using the XNA framework

Lately I've been having a look at XNA and I think it's really good or at least it's a very good way of getting started in game design. It's Microsoft doing what Microsoft does best, i.e. make life simpler for developers. I grabbed a sample to get me started and decided to have a look at a very crude of Brownian motion simulation or in layman's terms, a lot of balls randomly colliding with each other.

I decided to tackle elastic collisions first and ignored rotations, so this is really as simple as it gets in 2D. I won't go into details of the physics and I know that I could've used inbuilt XNA framework methods to do same operations that I do here manually (dot product, vector modulus), but it's good to have them written long hand, for portability to other languages.

Without further ado here's the code. Note that Ball is a class that defines a position (Vector2), velocity (Vector2) and mass (float). 

   1 private void EllasticCollisionPhysics(Ball ball1, Ball ball2)
   2 {
   3     //find normal vector
   4     Vector2 normal = new Vector2(ball2.Position.X - ball1.Position.X, ball2.Position.Y - ball1.Position.Y);
   5 
   6     //find normal vector's modulus, i.e. length
   7     float normalmod = (float)Math.Sqrt(Math.Pow(normal.X, 2) + Math.Pow(normal.Y, 2));
   8 
   9     //find unitnormal vector
  10     Vector2 unitnormal = new Vector2((ball2.Position.X - ball1.Position.X) / normalmod, (ball2.Position.Y - ball1.Position.Y) / normalmod);
  11 
  12     //find tangent vector
  13     Vector2 unittan = new Vector2(-1 * unitnormal.Y, unitnormal.X);
  14 
  15     //first ball normal speed before collision
  16     float inormalspeedb = unitnormal.X * ball1.Velocity.X + unitnormal.Y * ball1.Velocity.Y;
  17     
  18     //first ball tangential speed 
  19     float itanspeed = unittan.X * ball1.Velocity.X + unittan.Y * ball1.Velocity.Y;
  20 
  21     //second ball normal speed before collision
  22     float ynormalspeedb = unitnormal.X * ball2.Velocity.X + unitnormal.Y * ball2.Velocity.Y;
  23    
  24     //second ball tangential speed
  25     float ytanspeed = unittan.X * ball2.Velocity.X + unittan.Y * ball2.Velocity.Y;
  26 
  27     //tangential speeds don't change whereas normal speeds do
  28 
  29     //Calculate normal speeds after the collision
  30     float inormalspeeda = (inormalspeedb * (ball1.mass - ball2.mass) + 2 * ball2.mass * ynormalspeedb) / (ball1.mass + ball2.mass);
  31     float ynormalspeeda = (ynormalspeedb * (ball2.mass - ball1.mass) + 2 * ball1.mass * inormalspeedb) / (ball1.mass + ball2.mass);
  32     
  33     //Calculate first ball Velocity vector components (tangential and normal)
  34     Vector2 inormala = new Vector2(unitnormal.X * inormalspeeda, unitnormal.Y * inormalspeeda);
  35     Vector2 itana = new Vector2(unittan.X * itanspeed, unittan.Y * itanspeed);
  36     
  37     //Calculate second ball Velocity vector components (tangential and normal)
  38     Vector2 ynormala = new Vector2(unitnormal.X * ynormalspeeda, unitnormal.Y * ynormalspeeda);
  39     Vector2 ytana = new Vector2(unittan.X * ytanspeed, unittan.Y * ytanspeed);
  40     
  41     //Add Vector components to each balls' Velocity
  42     ball1.Velocity = Vector2.Add(inormala, itana);
  43     ball2.Velocity = Vector2.Add(ynormala, ytana);
  44 }

No comments:

Post a Comment