; ID: 415 ; Author: Phish ; Date: 2002-09-03 11:43:20 ; Title: Billiards Style Collision Physics ; Description: 2D circle collision response which can be used for almost anything where 2 objects collide in 2 dimensions ;------------------------------------------ ;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 actualDistanceGraphicsWidth()-c\radius Then c\x=GraphicsWidth()-c\radius c\dx=c\dx*-0.9 End If If c\yGraphicsHeight()-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 ;------------------------------------------ ;------------------------------------------