Code archives/Algorithms/Billiards Style Collision Physics

This code has been declared by its author to be Public Domain code.

Download source code

Billiards Style Collision Physics by Phish2002
This type of collision response isn't just useful for pool and billiard style games, and in fact, I didn't write it for that reason at all. I wrote it because I needed to have collision for the space ships in my game 'Unity'. When their shields are up, they use this relatively simple method. It can be used for almost anything - player character bouncing off enemies in a platform game, to space ship collision, to a game which does actually involve balls. The basic algorithm which I used would work for both 2d and 3d so if you would like to see it, email me at phish@.... I think that realistic physics, even if pretty simple, can make a game feel a lot more immersive and interesting. The idea is that you should read my code, see how I use the collision response section, hack it up, and use it in your own game :-)
;------------------------------------------
;2D COLLISION DEMO CODE
;------------------------------------------
; By Joseph 'Phish' Humfrey
; This type of collision response isn't
; just useful for pool and billiard style
; games, and in fact, I didn't write it for
; that reason at all. I wrote it because I
; needed to have collision for the space
; ships in my game 'Unity'. When their
; shields are up, they use this relatively
; simple method. It can be used for almost
; anything - player character bouncing off
; enemies in a platform game, to space
; ship collision, to a game which does
; actually involve balls. The basic
; algorithm which I used would work for
; both 2d and 3d, so if you would like to
; see it, email me at phish@aelius.com
;------------------------------------------
; The actual code which works out what
; happens after a collision is in the
; UpdateCirclePhysics() function.
;------------------------------------------
; Enjoy!
;------------------------------------------
;------------------------------------------

Graphics 800, 600, 16, 2
SetBuffer BackBuffer()
SeedRnd MilliSecs()



;------------------------------------------
; MAIN DATA TYPE
;------------------------------------------
; This exact type isn't supposed to be used
; Instead, you should use some of the fields
; in your own type, or just use this one
; for reference, to see what each field does
Type circle
	Field x#, y#		;position
	Field dx#, dy#		;x and y speeds
	
	Field radius#		;radius of circle
	Field mass#			;mass of circle
End Type
;------------------------------------------
;------------------------------------------






;------------------------------------------
; SET UP BALLS INTO A POOL STYLE ARRANGEMENT
; FOR DEMO
;------------------------------------------
.Setup
ballTriangleSize=5
For xloop = ballTriangleSize To 1 Step -1
	For yloop = 1 To xloop
		c.circle = New circle
		c\x = (5-xloop)*27 + 200
		c\y = yloop*31-(xloop*31)/2.0 + 300
		c\dx=0
		c\dy=0
		c\radius = 15
		c\mass = 50
	Next
Next

;Cue ball (smaller so you know which it is :)
cue.circle = New circle
cue\x = 800
cue\y = 300 +20
cue\dx = -20
cue\dy = Rnd(4)-2
cue\radius = 14
cue\mass = 50
;------------------------------------------
;------------------------------------------







;------------------------------------------
;MAIN LOOP
;------------------------------------------
; This is the main While..Wend game loop
While Not KeyDown(1)

	Cls
	
	UpdateCirclePhysics()
	RenderCircles()
	
	;------------
	; Reset button
	Text 10, 10, "Press a mouse button to reset."
	Text 10, 25, "Press Esc to exit."
	If GetMouse() Then
		For c.circle = Each circle
			Delete c
		Next
		Goto setup
	End If
	;------------
	
	Flip
	
Wend
;------------------------------------------
;------------------------------------------
End









;------------------------------------------
Function UpdateCirclePhysics()
;------------------------------------------
; This is the main physics function for the
; circles. It contains the very basic
; movement physics as well as the collision
; response code.
;------------------------------------------

	For c.circle = Each circle
	
		;update positions
		c\x=c\x+c\dx
		c\y=c\y+c\dy
		
		;gradually slow down
		c\dx=c\dx*0.99
		c\dy=c\dy*0.99
		
		;------------------------------------------
		;COLLISION CHECKING
		;------------------------------------------
		; Check each circle in the loop against
		; every other (c against c2)
		For c2.circle = Each circle
		
			collisionDistance# = c\radius+c2\radius
			actualDistance# = Sqr((c2\x-c\x)^2+(c2\y-c\y)^2)
			
			;Collided or not?
			If actualDistance<collisionDistance Then
				
				collNormalAngle#=ATan2(c2\y-c\y, c2\x-c\x)

				;Position exactly touching, no intersection
				moveDist1#=(collisionDistance-actualDistance)*(c2\mass/Float((c\mass+c2\mass)))
				moveDist2#=(collisionDistance-actualDistance)*(c\mass/Float((c\mass+c2\mass)))
				c\x=c\x + moveDist1*Cos(collNormalAngle+180)
				c\y=c\y + moveDist1*Sin(collNormalAngle+180)
				c2\x=c2\x + moveDist2*Cos(collNormalAngle)
				c2\y=c2\y + moveDist2*Sin(collNormalAngle)
				
				
				;------------------------------------------
				;COLLISION RESPONSE
				;------------------------------------------
				;n = vector connecting the centers of the circles.
				;we are finding the components of the normalised vector n
				nX#=Cos(collNormalAngle)
				nY#=Sin(collNormalAngle)
				
				;now find the length of the components of each movement vectors
				;along n, by using dot product.
				a1# = c\dx*nX  +  c\dy*nY
				a2# = c2\dx*nX +  c2\dy*nY
				
				;optimisedP = 2(a1 - a2)
				;             ----------
				;              m1 + m2
				optimisedP# = (2.0 * (a1-a2)) / (c\mass + c2\mass)
				
				;now find out the resultant vectors
				;r1 = c1\v - optimisedP * mass2 * n
				c\dx = c\dx - (optimisedP*c2\mass*nX)
				c\dy = c\dy - (optimisedP*c2\mass*nY)
				
				;r2 = c2\v - optimisedP * mass1 * n
				c2\dx = c2\dx + (optimisedP*c\mass*nX)
				c2\dy = c2\dy + (optimisedP*c\mass*nY)

			End If

		Next
		;------------------------------------------
		;------------------------------------------
		
		
		;Simple Bouncing off walls.
		If c\x<c\radius Then
			c\x=c\radius
			c\dx=c\dx*-0.9
		End If
		If c\x>GraphicsWidth()-c\radius Then
			c\x=GraphicsWidth()-c\radius
			c\dx=c\dx*-0.9
		End If
		If c\y<c\radius Then
			c\y=c\radius
			c\dy=c\dy*-0.9
		End If
		If c\y>GraphicsHeight()-c\radius Then
			c\y=GraphicsHeight()-c\radius
			c\dy=c\dy*-0.9
		End If
		
	Next

End Function





;------------------------------------------
Function RenderCircles()
;------------------------------------------
; Simple function draws all the circles
; on the screen.
;------------------------------------------

	For c.circle = Each circle
		If c\radius=15 Then Color 200, 50, 50 Else Color 255, 255, 255
		Oval c\x-c\radius, c\y-c\radius, c\radius*2, c\radius*2
	Next
	
End Function
;------------------------------------------
;------------------------------------------

Comments

Ching2012
I could have scored much better in my advanced graphics module if I'd found this code a couple of years ago.
This code is really good.


Matty2012
The magic numbers in there for friction and elasticity of collision would be better replaced with parameters/fields that can be set as required.


BlitzSupport2012
This is great stuff! Here are some quick-and-dirty BMX/Monkey ports...

BlitzMax:



Monkey:




Matty2012
In the monkey example my browser freezes when compiled either for html5 or flash as soon as the user clicks the mouse after the balls have moved. I'm using Chrome, and Monkey 45c. Otherwise looks good.


BlitzSupport2012
Bit odd -- I'm on Chrome and it's fine here. I also ran it without problems on GLFW and my Android phone.


Jesse2012
works fine here in Safari and Chrome using monkey 53.

I have been using this code for a few years although not for pool. Actually this code was what motivated me to do more research on vector physics and start learning all about vectors.

it's good for fairly simple simulation. I wasn't able to use it as it moves balls apart when they over lap(causes a collision inaccuracy) instead of finding the exact point of collision and it fails completely if the speed of a ball exceed its diameter. I needed something that works dynamically.

I find it useful for other things but was not able to use it for my pool game where I needed to find the exact point of collision.

I am not nocking it down as it has it's uses and the collision response is really good but not for acceptable pool physics, at least for me it wasn't.


Hardcoal2012
great submission


Captain Wicker (crazy hillbilly)2012
lovely! :)


Code Archives Forum