;------------------------------------------
;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
cx = (5-xloop)*27 + 200
cy = yloop*31-(xloop*31)/2.0 + 300
cdx=0
cdy=0
c
adius = 15
cmass = 50
Next
Next
;Cue ball (smaller so you know which it is :)
cue.circle = New circle
cuex = 800
cuey = 300 +20
cuedx = -20
cuedy = Rnd(4)-2
cue
adius = 14
cuemass = 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
cx=cx+cdx
cy=cy+cdy
;gradually slow down
cdx=cdx*0.99
cdy=cdy*0.99
;------------------------------------------
;COLLISION CHECKING
;------------------------------------------
; Check each circle in the loop against
; every other (c against c2)
For c2.circle = Each circle
collisionDistance# = c
adius+c2
adius
actualDistance# = Sqr((c2x-cx)^2+(c2y-cy)^2)
;Collided or not?
If actualDistance<collisionDistance Then
collNormalAngle#=ATan2(c2y-cy, c2x-cx)
;Position exactly touching, no intersection
moveDist1#=(collisionDistance-actualDistance)*(c2mass/Float((cmass+c2mass)))
moveDist2#=(collisionDistance-actualDistance)*(cmass/Float((cmass+c2mass)))
cx=cx + moveDist1*Cos(collNormalAngle+180)
cy=cy + moveDist1*Sin(collNormalAngle+180)
c2x=c2x + moveDist2*Cos(collNormalAngle)
c2y=c2y + 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# = cdx*nX + cdy*nY
a2# = c2dx*nX + c2dy*nY
;optimisedP = 2(a1 - a2)
; ----------
; m1 + m2
optimisedP# = (2.0 * (a1-a2)) / (cmass + c2mass)
;now find out the resultant vectors
;r1 = c1v - optimisedP * mass2 * n
cdx = cdx - (optimisedP*c2mass*nX)
cdy = cdy - (optimisedP*c2mass*nY)
;r2 = c2v - optimisedP * mass1 * n
c2dx = c2dx + (optimisedP*cmass*nX)
c2dy = c2dy + (optimisedP*cmass*nY)
End If
Next
;------------------------------------------
;------------------------------------------
;Simple Bouncing off walls.
If cx<c
adius Then
cx=c
adius
cdx=cdx*-0.9
End If
If cx>GraphicsWidth()-c
adius Then
cx=GraphicsWidth()-c
adius
cdx=cdx*-0.9
End If
If cy<c
adius Then
cy=c
adius
cdy=cdy*-0.9
End If
If cy>GraphicsHeight()-c
adius Then
cy=GraphicsHeight()-c
adius
cdy=cdy*-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
adius=15 Then Color 200, 50, 50 Else Color 255, 255, 255
Oval cx-c
adius, cy-c
adius, c
adius*2, c
adius*2
Next
End Function
;------------------------------------------
;------------------------------------------