Back to Richel Bilderbeek's homepage.

Back to Richel Bilderbeek's Code Snippets.

 

 

 

DoPerfectElasticCollision

 

When two perfect globes (or disks) collide and bounce perfectly elastically, all impulse is maintained and transferred maximally. Near-perfect elastic collisions can be observed when playing snooker or air-hockey. It is a relatively mathematical complex function and the image showing all angles and vectors should clear up on the function's working. The function assumes equals mass of both players.

 

I re-developed this function for one of my games called 'Boenken'.

 

* View an image showing all angles and vectors.

* View the code of 'DoPerfectElasticCollision' in plain text.

 

The function assumes you have already defined the GetAngle function.

 

#include <cmath>

 

//From http://www.richelbilderbeek.nl/CppDoPerfectElasticCollision.htm

void DoPerfectElasticCollision(

  const double angleCollision,

  double& angle1,

  double& speed1,

  double& angle2,

  double& speed2)

{

  //The length of the impulse of player 1 (assumes both players have equal mass!)

  const double A = speed1;

  //The length of the impulse of player 2 (assumes both players have equal mass!)

  const double E = speed2;

  //The angles between the two globes

  const double c = angleCollision;

  //The angle between c and the impulse direction of player 1

  const double a = c - angle1;

  //The angle between c and the impulse direction of player 2

  const double b = c + M_PI - angle2;

 

  //Seperate the impulses to their impulses paralel and othoganal the angle of collision

  //The length of the impulse of player 1 parallel to the collision

  const double B = A * std::cos(a);

  //The length of the impulse of player 1 orthogonal to the collision

  const double C = A * std::sin(a);

  //The length of the impulse of player 2 parallel to the collision

  const double F = E * std::cos(b);

  //The length of the impulse of player 2 orthogonal to the collision

  const double G = E * std::sin(b);

 

  //Seperate the impulses in X and Y directions

  const double BdX = B *  std::sin(c + (0.0 * M_PI));

  const double BdY = B * -std::cos(c + (0.0 * M_PI));

  const double CdX = C *  std::sin(c + (1.5 * M_PI));

  const double CdY = C * -std::cos(c + (1.5 * M_PI));

  const double FdX = F *  std::sin(c + (1.0 * M_PI));

  const double FdY = F * -std::cos(c + (1.0 * M_PI));

  const double GdX = G *  std::sin(c + (0.5 * M_PI));

  const double GdY = G * -std::cos(c + (0.5 * M_PI));

 

  //The resulting impulses

  //The resulting impulse of player 1 in the X direction

  const double DdX = CdX + FdX;

  //The resulting impulse of player 1 in the Y direction

  const double DdY = CdY + FdY;

  //The resulting impulse of player 2 in the X direction

  const double HdX = BdX + GdX;

  //The resulting impulse of player 2 in the Y direction

  const double HdY = BdY + GdY;

 

  //Write the final results

  angle1 = GetAngle(DdX, DdY);

  angle2 = GetAngle(HdX, HdY);

  speed1 = std::sqrt( (DdX * DdX) + (DdY * DdY) ); //Pythagoras

  speed2 = std::sqrt( (HdX * HdX) + (HdY * HdY) ); //Pythagoras

}

 

 

Back to Richel Bilderbeek's Code Snippets.

Back to Richel Bilderbeek's homepage.