You have two laws of physics, conservation of energy and conservation of momentum. The total energy after collision is equal to the total energy before collision. The total momentum after collision is equal to the total momentum before collision.
Momentum = mass * velocity
Kinetic energy = 0.5 * mass * velocity * velocity
Solve the simultaneous equations which will probably have a quadratic equation. Since velocity is a vector you need to consider these conservation laws in both the x and y directions.
This is a particularly difficult problem if the balls do not hit head-on. Also if the balls roll up to each other or spin as a result of an off-centre collision it is harder still. Rolling or spinning are conserved as angular energy and angular momentum.
Look for the sticky link at the top of Libraries on this forum because you might be better using the ODE library
http://ode.org/ Or Newton
http://www.physicsengine.com/
Here is some code to handle the general case, in C or Fortran.
http://www.plasmaphysics.org.uk/programs/coll2d_cpp.htm
http://www.plasmaphysics.org.uk/collision2d.htm
Here is an UNtested translation to FB from Fortran. No warranty.
Code: Select all
' ******************************************************************************
' This program is a 'remote' 2D-collision detector for two balls on linear
' trajectories and returns, if applicable, the location of the collision for
' both balls as well as the new velocity vectors (assuming a fully elastic
' collision).
' All variables apart from 'ErrorCode' are of Double Precision Floating Point type.
' In 'free' mode no positions but only the initial velocities and an impact
' angle are required.
' All variables apart from 'mode' and 'ErrorCode' are of Double Precision
' Floating Point type.
'
' The Parameters are:
'
' mode (character*4) (if='free' alpha must be supplied; otherwise arbitrary)
' alpha (impact angle) only required in mode='free';
' should be between -PI/2 and PI/2 (0 = head-on collision))
' m1 (mass of ball 1)
' m2 (mass of ball 2)
' r1 (radius of ball 1) not needed for 'free' mode
' r2 (radius of ball 2) "
' * x1 (x-coordinate of ball 1) "
' * y1 (y-coordinate of ball 1) "
' * x2 (x-coordinate of ball 2) "
' * y2 (y-coordinate of ball 2) "
' * vx1 (velocity x-component of ball 1)
' * vy1 (velocity y-component of ball 1)
' * vx2 (velocity x-component of ball 2)
' * vy2 (velocity y-component of ball 2)
' * ErrorCode (Integer*2) (0: no error
' 1: balls do not collide
' 2: initial positions impossible (balls overlap)
'
' In the calling program, the arguments corresponding to the parameters
' with an asterisk (*) will be updated (the positions and velocities however
' only if 'ErrorCode'=0).
' All variables should have the same data types in the calling program
' and all should be initialized before calling the subroutine.
'
' This program is free to use for everybody. However, you use it at your own
' risk and I do not accept any liability resulting from incorrect behaviour.
' I have tested the program for numerous cases and I could not see anything
' wrong with it but I can not guarantee that it is bug-free under any
' circumstances.
' I do in general not recommend the use of single precision because for
' iterative computations the rounding errors can accumulate and render the
' result useless if there are not enough decimal places; however for uncritical
' applications or if speed is of paramount importance, you can change the
' program to single precision by changing the variable declaration to REAL*4
' and remove the 'D' in front of the mathematical function names.
'
'
' I would appreciate if you could report any problems to me
' (for contact details see http://www.plasmaphysics.org.uk/feedback.htm ).
'
' Thomas Smid, January 2004
' December 2005 (corrected faulty collision detection;
' a few minor changes to improve speed;
' added simplified code without collision detection)
' **********************************************************************************
Sub collision2D(_
Byref mode As String,_
Byref alpha As Double,_
Byref m1 As Double,_
Byref m2 As Double,_
Byref r1 As Double,_
Byref r2 As Double,_
Byref x1 As Double,_
Byref y1 As Double,_
Byref x2 As Double,_
Byref y2 As Double,_
Byref vx1 As Double,_
Byref vy1 As Double,_
Byref vx2 As Double,_
Byref vy2 As Double,_
Byref ErrorCode As Integer)
' **** initialize some additional variables ****
Dim As Double PI2, R12, M21, X21, Y21, VX21, VY21, GAMMAV, D
Dim As Double GAMMAXY, DGAMMA, DDGAMMA, DR, DC, SQS, T, A, DVX2
PI2 = 2.0D0*Atn(-1.0D0)
ErrorCode = 0
R12 = r1+r2
M21 = m2/m1
X21 = x2-x1
Y21 = y2-y1
VX21 = vx2-vx1
VY21 = vy2-vy1
' **** return if relative velocity =0 ****
If (vx21 = 0 And vy21 = 0) Then
ErrorCode = 1
Exit Sub
End If
' *** calculate relative velocity angle
GAMMAV = Atan2(-vy21,-vx21)
' ******** this block only if initial positions are given ***
If (mode <> "free") Then
D = Sqr(x21*x21+y21*y21)
' **** return if distance between balls smaller than sum of radii ***
If (d < r12) Then
ErrorCode = 2
Exit Sub
End If
' **** calculate relative position angle and normalized impact parameter ***
GAMMAXY = Atan2(y21,x21)
DGAMMA = gammaxy-gammav
If (dgamma > pi2) Then
DGAMMA = dgamma-pi2
Else
If (dgamma < -pi2) Then
DGAMMA = dgamma+pi2
End If
End If
DR = d*Sin(dgamma)/r12
' **** return old positions and velocities if balls do not collide ***
If ((dgamma > pi2/4.0D0 And ddgamma < 0.75D0*pi2 ) Or Abs(dr) > 1.0D0 ) Then
ErrorCode = 1
Exit Sub
End If
' **** calculate impact angle if balls do collide ***
ALPHA = Asin(dr)
' **** calculate time to collision ***
DC = d*Cos(dgamma)
If (dc > 0) Then
SQS = 1.0D0
Else
SQS = -1.0D0
End If
T = (dc-sqs*r12*Sqr(1-dr*dr))/Sqr(vx21*vx21+vy21*vy21)
' **** update positions ***
X1 = x1+vx1*t
Y1 = y1+vy1*t
X2 = x2+vx2*t
Y2 = y2+vy2*t
End If
' ******** END 'this block only if initial positions are given' ***
' *** update velocities ***
A = Tan(gammav+alpha)
DVX2 = -2*(vx21+a*vy21)/((1+a*a)*(1+m21))
VX2 = vx2+dvx2
VY2 = vy2+a*dvx2
VX1 = vx1-m21*dvx2
VY1 = vy1-a*m21*dvx2
End Sub
' ******************************************************************************
' Simplified Version
' The advantage of the 'remote' collision detection in the program above is
' that one does not have to continuously track the balls to detect a collision.
' The program needs only to be called once for any two balls unless their
' velocity changes. However, if somebody wants to use a separate collision
' detection routine for whatever reason, below is a simplified version of the
' code which just calculates the new velocities, assuming that the balls are
' already touching and approaching each other (these two conditions are
' important as otherwise the results will be incorrect)
' ****************************************************************************
Sub collision2Ds(_
Byref m1 As Double,_
Byref m2 As Double,_
Byref x1 As Double,_
Byref y1 As Double,_
Byref x2 As Double,_
Byref y2 As Double,_
Byref vx1 As Double,_
Byref vy1 As Double,_
Byref vx2 As Double,_
Byref vy2 As Double)
Dim As Double M21, X21, Y21, VX21, VY21, FY21, Sign, A, DVX2
M21 = m2/m1
X21 = x2-x1
Y21 = y2-y1
VX21 = vx2-vx1
VY21 = vy2-vy1
' *** I have inserted the following statements to avoid a zero divide;
' *** (for single precision calculations,
' *** 1.0D-12 should be replaced by a larger value). **********
FY21 = 1.0D-12*Abs(y21)
If ( Abs(x21) < fy21 ) Then
If (x21 < 0) Then
SIGN = -1.0D0
Else
SIGN = 1.0D0
End If
X21 = fy21*sign
End If
' *** update velocities ***
A = y21/x21
DVX2 = -2*(vx21+a*vy21)/((1+a*a)*(1+m21))
VX2 = vx2+dvx2
VY2 = vy2+a*dvx2
VX1 = vx1-m21*dvx2
VY1 = vy1-a*m21*dvx2
End Sub