Snooker / Pool / Billiards Physics by Hamish McHaggis28th Jan 2004 15:59
|
---|
Summary Shows how to do realistic collision between billiard balls. Description Uses triganometry to bounce and speed up and slow down the balls as they fly around the table. Also works with the balls in close range like in a break. Turn the variable "numSteps" up if you find the balls dancing around each other (this would happen if you turned the speed up too much). Code ` This code was downloaded from The Game Creators ` It is reproduced here with full permission ` http://www.thegamecreators.com `=================== ` Pool Physics Demo ` By Joseph Thomson ` 24/01/04 `=================== `If you use any of this code in any way please give `credit to me for the original code. `Position data for balls DATA 100,240 DATA 400,240 DATA 421,230,421,250 DATA 442,220,442,240,442,260 DATA 463,210,463,230,463,250,463,270 DATA 484,200,484,220,484,240,484,260,484,280 DATA 505,190,505,210,505,230,505,250,505,270,505,290 `Ball type with velocity and position TYPE ballType xPos AS FLOAT yPos AS FLOAT xVel AS FLOAT yVel AS FLOAT ENDTYPE `Number of balls and ball radius numBalls AS INTEGER = 16 ballRad AS INTEGER = 10 DIM balls(numBalls) AS ballType GOSUB placeBalls `Walls topWall = 10 bottomWall = 470 leftWall = 10 rightWall = 630 `Increase for increased accuracy numSteps AS INTEGER = 30 tableFriction AS FLOAT = 0.025 wallDecay AS FLOAT = 1.0 shotAng AS FLOAT shotPower AS FLOAT mouseHold AS INTEGER mouseHoldX AS FLOAT mouseHoldY AS FLOAT dist AS FLOAT angleBetween AS FLOAT ang1 AS FLOAT ang2 AS FLOAT vel1 AS FLOAT vel2 AS FLOAT velX1 AS FLOAT velX2 AS FLOAT velY1 AS FLOAT velY2 AS FLOAT totalVel AS FLOAT SYNC ON SYNC RATE 60 DO `Draw walls INK RGB(255,255,255),0 BOX leftWall-1,topWall-1,rightWall+1,bottomwall+1 INK RGB(0,0,0),0 BOX leftWall,topWall,rightWall,bottomwall `Do the movement of the balls and collision detection in steps, for increased accuracy FOR l=1 TO numSteps `Loop through all balls FOR x=1 TO numBalls `Move the ball INC balls(x).xPos,balls(x).xVel/numSteps INC balls(x).yPos,balls(x).yVel/numSteps `Control the shooting of the ball IF MOUSECLICK()=1 IF mouseHold = 0 mouseHold = 1 mouseHoldX = MOUSEX() mouseHoldY = MOUSEY() ELSE shotPower = SQRT((mouseHoldX-MOUSEX())^2+(mouseHoldY-MOUSEY())^2)*0.2 IF shotPower > 100.0 THEN shotPower = 100.0 shotAng = 360-(180-ATANFULL(mouseHoldX-MOUSEX(),mouseHoldY-MOUSEY())) ENDIF ELSE IF MOUSECLICK()=0 AND mouseHold = 1 mouseHold = 0 balls(1).xVel=SIN(shotAng)*shotPower balls(1).yVel=COS(shotAng)*shotPower ENDIF ENDIF `Replace the balls if space is pressed IF SPACEKEY()=1 GOSUB placeBalls ENDIF `Control balls' collision with walls (rebounding and energy loss) IF balls(x).xPos-ballRad < leftWall balls(x).xPos = leftWall+ballRad balls(x).xVel = -balls(x).xVel*wallDecay ENDIF IF balls(x).xPos+ballRad > rightWall balls(x).xPos = rightWall-ballRad balls(x).xVel = -balls(x).xVel*wallDecay ENDIF IF balls(x).yPos-ballRad < topWall balls(x).yPos = topWall+ballRad balls(x).yVel = -balls(x).yVel*wallDecay ENDIF IF balls(x).yPos+ballRad > bottomWall balls(x).yPos = bottomWall-ballRad balls(x).yVel = -balls(x).yVel*wallDecay ENDIF `Loop through all balls FOR y=1 TO numBalls `Don't check collision between the same ball IF y<>x `Get distance of balls from each other dist = SQRT((balls(x).xPos-balls(y).xPos)^2+(balls(x).yPos-balls(y).yPos)^2) `If they are touching IF dist < ballRad*2 `Get the angle between them angleBetween = ATANFULL(balls(x).xPos-balls(y).xPos,balls(x).yPos-balls(y).yPos) `Move the first ball back where it was DEC balls(x).xPos,balls(x).xVel/numSteps DEC balls(x).yPos,balls(x).yVel/numSteps `Get the angles of the balls velocities ang1 = ATANFULL(balls(x).xVel,balls(x).yVel) ang2 = ATANFULL(balls(y).xVel,balls(y).yVel) `Get the speed of the balls velocities vel1 = SQRT(balls(x).xVel^2+balls(x).yVel^2)*0.9 vel2 = SQRT(balls(y).xVel^2+balls(y).yVel^2)*0.9 `Work out the new velocities of the balls using trig velX1 = SIN(angleBetween+90)*SIN(360-(angleBetween-ang1))*vel1+SIN(angleBetween)*COS(angleBetween-ang2)*vel2 velY1 = COS(angleBetween+90)*SIN(360-(angleBetween-ang1))*vel1+COS(angleBetween)*COS(angleBetween-ang2)*vel2 velX2 = SIN(angleBetween)*COS(angleBetween-ang1)*vel1+SIN(angleBetween+90)*SIN(360-(angleBetween-ang2))*vel2 velY2 = COS(angleBetween)*COS(angleBetween-ang1)*vel1+COS(angleBetween+90)*SIN(360-(angleBetween-ang2))*vel2 `Set the balls' velocities balls(x).xVel = velX1 balls(x).yVel = velY1 balls(y).xVel = velX2 balls(y).yVel = velY2 ENDIF ENDIF NEXT y `If the loop is on the last step... IF l=numSteps `Draw graphics IF x=1 INK RGB(255,255,0),0 ELSE INK RGB(255,255,255),0 ENDIF CIRCLE balls(x).xPos,balls(x).yPos,ballRad IF MOUSECLICK()=1 THEN LINE balls(1).xPos,balls(1).yPos,balls(1).xPos+SIN(shotAng)*shotPower*3,balls(1).yPos+COS(shotAng)*shotPower*3 `Control ball friction totalVel = SQRT(balls(x).xVel^2+balls(x).xVel^2) DEC balls(x).xVel,tableFriction*totalVel*(balls(x).xVel/totalVel) DEC balls(x).yVel,tableFriction*totalVel*(balls(x).yVel/totalVel) ENDIF NEXT x NEXT l SYNC CLS LOOP `Replace the balls placeBalls: RESTORE FOR p=1 TO numBalls READ balls(p).xPos READ balls(p).yPos balls(p).xVel = 0.0 balls(p).yVel = 0.0 NEXT p RETURN |