Pool Game
BlitzMax Forums/BlitzMax Beginners Area/Pool Game
| ||
Hi - complete newbie to Blitzmax, but I have worked with DarkBasic Pro (apologies for mentioning this in the blitz forum). I am looking at writing a pool / snooker game and am a little stuck. I have got a basic collision and motion routine working, so I can fire the cueball into the pack and send the balls bouncing around the table. Only problem is the balls bounce off the pockets too, instead of getting potted. Also the standard bounce angles are fine, but I need to consider the different bounce when a ball hits very close to the pocket. currently I am just using an bmp image for the table so will need to use some form of calculation to work out whether the ball is pocketed or needs a different rebound calculation, but am not sure of the best way forward on this. Anyway any help would be much appreciated. Thanks, Tim Strict 'Declare a user defined type to hold information about the balls Type typBall Field varXPos : Float Field varYPos : Float Field varXVel : Float Field varYVel : Float EndType 'Delcare constants the number of balls, the ball radius and the wall positions Const intNumberOfBalls : Int = 16 Const intBallRadius : Int = 10 Rem Const intWallLeft : Int = 10 Const intWallTop : Int = 10 Const intWallRight : Int = 630 Const intWallBottom : Int = 470 EndRem Const intWallLeft : Int = 40 Const intWallTop : Int = 40 Const intWallRight : Int = 984 Const intWallBottom : Int = 472 'Now some constants for the motion calculation Const IntNumberOfSteps : Int = 30 Const varTableFriction : Float = 0.025 Const varWallDecay : Float = 1.0 'An array to hold the ball information using the new type declared above Global arrBalls : typBall[intNumberOfBalls] For Local i = 0 Until intNumberOfBalls arrBalls[i] = New typBall Next 'Variables for taking a shot Local varShotAngle : Float Local varShotPower : Float Local intMouseHold : Int Local varMouseHoldX : Float Local varMouseHoldY : Float 'General variables to do with the angles and velocities of the balls. Local varDistance : Float Local varAngleBetween : Float Local varAngle1 : Float Local varAngle2 : Float Local varVel1 : Float Local varVel2 : Float Local varVelX1 : Float Local varVelX2 : Float Local varVelY1 : Float Local varVelY2 : Float Local varTotalVel : Float 'Load up the table 'Incbin "snookertable.png" 'Global imgTable = LoadImage ("incbin:: snookertable.png") 'Next call function to position the balls _place_balls() 'Graphics 640,480,0 Graphics 1024,768,0 SetBlend solidblend Local imgTable = LoadImage("TableSmall.bmp") SetBlend alphablend Local imgBlackBall = LoadImage("snookerball.png") Repeat SetColor 255,255,255 DrawImage imgTable,0,0 'DrawImage imgBlackBall,50,50 'SetColor 255,255,255 'DrawRect intWallLeft - 1, intWallTop - 1, intWallRight - intWallLeft + 2, intWallBottom - intWallTop + 2 'SetColor 0,0,0 'DrawRect intWallLeft, intWallTop, intWallRight - intWallLeft, intWallBottom - intWallTop 'loop through the main calculation for the ball motion - more steps greater accuracy For Local i = 1 To intNumberOfSteps 'loop through each of the balls For Local j = 0 Until intNumberOfBalls If arrBalls[j].varXVel <> 0.0 Then arrBalls[j].varXPos :+ arrBalls[j].varXVel / intNumberOfSteps If arrBalls[j].varYVel <> 0.0 Then arrBalls[j].varYPos :+ arrBalls[j].varYVel / intNumberOfSteps 'Control the shooting of the ball If MouseDown(1) If intMouseHold = 0 intMouseHold = 1 varMouseHoldX = MouseX() varMouseHoldY = MouseY() Else varShotPower = Sqr((varMouseHoldX - MouseX())^2 + (varMouseHoldY - MouseY())^2) * 0.2 If varShotPower > 100.0 Then varShotPower = 100.0 varShotAngle = 360-(180 - ATan2(varMouseHoldX - MouseX(), varMouseHoldY - MouseY())) EndIf Else If Not MouseDown(1) And intMouseHold = 1 intMouseHold = 0 arrBalls[0].varXVel = Sin(varShotAngle) * varShotPower arrBalls[0].varYVel = Cos(varShotAngle) * varShotPower EndIf EndIf 'Replace the balls If space is pressed If KeyHit(32) _place_balls() EndIf 'Control balls' collision with walls (rebounding and energy loss) If arrBalls[j].varXPos - intBallRadius < intWallLeft arrBalls[j].varXPos = intWallLeft + intBallRadius arrBalls[j].varXVel = -arrBalls[j].varXVel * varWallDecay EndIf If arrBalls[j].varXPos + intBallRadius > intWallRight arrBalls[j].varXPos = intWallRight - intBallRadius arrBalls[j].varXVel = -arrBalls[j].varXVel * varWallDecay EndIf If arrBalls[j].varYPos - intBallRadius < intWallTop arrBalls[j].varYPos = intWallTop + intBallRadius arrBalls[j].varYVel = -arrBalls[j].varYVel * varWallDecay EndIf If arrBalls[j].varYPos + intBallRadius > intWallBottom arrBalls[j].varYPos = intWallBottom - intBallRadius arrBalls[j].varYVel = -arrBalls[j].varYVel * varWallDecay EndIf 'Loop through all balls For Local k = 0 Until intNumberOfBalls 'Don't check collision between the same ball If j <> k 'Get distance of balls from each other varDistance = Sqr((arrBalls[j].varXPos - arrBalls[k].varXPos)^2 + (arrBalls[j].varYPos - arrBalls[k].varYPos)^2) 'If they are touching If varDistance < intBallRadius * 2 'Get the angle between them varAngleBetween = ATan2(arrBalls[j].varXPos - arrBalls[k].varXPos,arrBalls[j].varYPos - arrBalls[k].varYPos) 'Move the first ball back where it was If arrBalls[j].varXVel <> 0 Then arrBalls[j].varXPos :- arrBalls[j].varXVel / intNumberOfSteps If arrBalls[j].varYVel <> 0 Then arrBalls[j].varYPos :- arrBalls[j].varYVel / intNumberOfSteps 'Get the angles of the balls velocities varAngle1 = ATan2(arrBalls[j].varXVel,arrBalls[j].varYVel) varAngle2 = ATan2(arrBalls[k].varXVel,arrBalls[k].varYVel) 'Get the speed of the balls velocities varVel1 = Sqr(arrBalls[j].varXVel^2 + arrBalls[j].varYVel^2) * 0.9 varVel2 = Sqr(arrBalls[k].varXVel^2 + arrBalls[k].varYVel^2) * 0.9 'Work out the New velocities of the balls using trig varVelX1 = Sin(varAngleBetween + 90) * Sin(360 - (varAngleBetween - varAngle1)) * varVel1 + Sin(varAngleBetween) * Cos(varAngleBetween - varAngle2) * varVel2 varVelY1 = Cos(varAngleBetween + 90) * Sin(360 - (varAngleBetween - varAngle1)) * varVel1 + Cos(varAngleBetween) * Cos(varAngleBetween - varAngle2) * varVel2 varVelX2 = Sin(varAngleBetween) * Cos(varAngleBetween - varAngle1) * varVel1 + Sin(varAngleBetween + 90) * Sin(360 - (varAngleBetween - varAngle2)) * varVel2 varVelY2 = Cos(varAngleBetween) * Cos(varAngleBetween - varAngle1) * varVel1 + Cos(varAngleBetween + 90) * Sin(360 - (varAngleBetween - varAngle2)) * varVel2 'Set the balls' velocities arrBalls[j].varXVel = varVelX1 arrBalls[j].varYVel = varVelY1 arrBalls[k].varXVel = varVelX2 arrBalls[k].varYVel = varVelY2 EndIf EndIf Next 'If the loop is on the last step... If i = intNumberOfSteps 'Draw Graphics If j = 0 SetColor 255,255,255 Else SetColor 255,0,0 EndIf DrawOval arrBalls[j].varXPos - intBallRadius, arrBalls[j].varYPos - intBallRadius, intBallRadius * 2, intBallRadius * 2 If MouseDown(1) Then DrawLine arrBalls[0].varXPos, arrBalls[0].varYPos, arrBalls[0].varXPos + Sin(varShotAngle) * varShotPower * 3, arrBalls[0].varYPos + Cos(varShotAngle) * varShotPower * 3 'Control ball friction varTotalVel = Sqr(arrBalls[j].varXVel^2 + arrBalls[j].varXVel^2) If arrBalls[j].varXVel <> 0.0 Then arrBalls[j].varXVel :- varTableFriction * varTotalVel * (arrBalls[j].varXVel / varTotalVel) If arrBalls[j].varYVel <> 0.0 Then arrBalls[j].varYVel :- varTableFriction * varTotalVel * (arrBalls[j].varYVel / varTotalVel) EndIf Next Next Flip Cls Until KeyHit(key_escape) = 1 End Function _place_balls() 'Replace the balls RestoreData ballPositions For Local p = 0 Until intNumberOfBalls ReadData arrBalls[p].varXPos ReadData arrBalls[p].varYPos arrBalls[p].varXVel = 0.0 arrBalls[p].varYVel = 0.0 Next EndFunction 'Position data For balls #ballPositions DefData 100,240 DefData 400,240 DefData 421,230,421,250 DefData 442,220,442,240,442,260 DefData 463,210,463,230,463,250,463,270 DefData 484,200,484,220,484,240,484,260,484,280 DefData 505,190,505,210,505,230,505,250,505,270,505,290 |