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
|