Back
to Richel Bilderbeek's homepage.
Back
to Richel Bilderbeek's Code Snippets.
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.