Pool Game

BlitzMax Forums/BlitzMax Beginners Area/Pool Game

Qweeg(Posted 2005) [#1]
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