I am trying to create a simple elastic collision simulation in java. (I am using some helper libs like StdRandom)
Here is my Ball class :
class Ball
{
double cx, cy;
Vector velocity;
double radius;
double mass;
public Ball()
{
mass = 1.0;
radius = 0.025;
cx = StdRandom.uniform( 0.000+radius, 1.000-radius );
cy = StdRandom.uniform( 0.000+radius, 1.000-radius );
// vx = 0.015;
// vy = 0.025;
velocity = new Vector();
velocity.setX( StdRandom.uniform( 0.0010, 0.015 ) );
velocity.setY( StdRandom.uniform( 0.0010, 0.015 ) );
}
public void move()
{
cx = cx + velocity.getX();
cy = cy + velocity.getY();
}
// getter methods
public double getCx(){ return cx; }
public double getCy(){ return cy; }
public double getVx(){ return velocity.getX(); }
public double getVy(){ return velocity.getY(); }
public double getRadius(){ return radius; }
public double getMass(){ return mass; }
// setter methods
public void setCx( double val ){ cx = val; }
public void setCy( double val ){ cy = val; }
public void setVx( double val ){ velocity.setX( val ); }
public void setVy( double val ){ velocity.setY( val ); }
public void setRadius( double val ){ radius = val; }
public void setMass( double val ){ mass = val; }
}
And here is my method for resolving collisions:
if ( distSqr == radii_sum*radii_sum )
{
double phi, theta1, theta2; // collision angle, a's movement angle, b's movement angle
double v1, v2; // scalar values of velocity for balls a and b
double m1, m2; // mass for ball's a and b
double v1xf, v1yf, v2xf, v2yf; // x and y components of final velocities after collision
// calculate angles
phi = Math.atan2( cy1-cy2, cx1-cx2 );
theta1 = Math.atan2( a.getVy(), a.getVx() );
theta2 = Math.atan2( b.getVy(), b.getVx() );
// get mass
m1 = a.getMass();
m2 = b.getMass();
// calculate scalar values of velocities
v1 = Math.sqrt( a.getVx()*a.getVx() + a.getVy()*a.getVy() );
v2 = Math.sqrt( b.getVx()*b.getVx() + b.getVy()*b.getVy() );
v1xf = ((((v1 * Math.cos(Math.toRadians(theta1 - phi)) * (m1 - m2)) + (2 * m2 * v2 * Math.cos(Math.toRadians(theta2 - phi)))) / (m1 + m2)) * Math.cos(Math.toRadians(phi))) + (v1 * Math.sin(Math.toRadians(theta1 - phi)) * Math.cos(Math.toRadians(phi + (Math.PI/2))));
v2xf = ((((v2 * Math.cos(Math.toRadians(theta2 - phi)) * (m2 - m1)) + (2 * m1 * v1 * Math.cos(Math.toRadians(theta1 - phi)))) / (m1 + m2)) * Math.cos(Math.toRadians(phi))) + (v2 * Math.sin(Math.toRadians(theta2 - phi)) * Math.cos(Math.toRadians(phi + (Math.PI/2))));
v1yf = ((((v1 * Math.cos(Math.toRadians(theta1 - phi)) * (m1 - m2)) + (2 * m2 * v2 * Math.cos(Math.toRadians(theta2 - phi)))) / (m1 + m2)) * Math.sin(Math.toRadians(phi))) + (v1 * Math.sin(Math.toRadians(theta1 - phi)) * Math.sin(Math.toRadians(phi + (Math.PI/2))));
v2yf = ((((v2 * Math.cos(Math.toRadians(theta2 - phi)) * (m2 - m1)) + (2 * m1 * v1 * Math.cos(Math.toRadians(theta1 - phi)))) / (m1 + m2)) * Math.sin(Math.toRadians(phi))) + (v2 * Math.sin(Math.toRadians(theta2 - phi)) * Math.sin(Math.toRadians(phi + (Math.PI/2))));
a.setVx( v1xf );
a.setVy( v1yf );
b.setVx( v2xf );
b.setVy( v2yf );
}
I had some questions -
- Have I calculated the scalar velocities and angles correctly? The code does not work and balls pass through each other, sometimes even pushing other balls beyond boundary.
- How do I reflect velocity? As x and y components given above OR single speed var and an angle? If latter then can I use different speeds for x and y components?
- Should I use a timestep for collision detection? If yes, an example would help!
- I tried using a randomly generated angle and changed it on collision as:
- (vertical wall) newangle = 180-oldangle
- (horizontal wall) newangle = (oldangle > 180) ? 360 -(oldangle - 180) : 180-oldangle
it worked but it becomes a specialized case. How to use a generic case for all lines(since x,y axis are lines indeed)? I know it uses normals but don't know the whole thing.
The collision method has been programmed by following the below link.
Wikipedia Elastic collision in two dimensions, both balls moving