Breakout problem

Blitz3D Forums/Blitz3D Beginners Area/Breakout problem

Ash_UK(Posted 2006) [#1]
Hi guys :o) Could anyone help me out here please. For some reason my code isn't working properly. When the ball hits the bricks, it is deleting the wrong ones :o(


here's the code:


Graphics 800,600
SetBuffer BackBuffer()


Global SCREEN_WIDTH = 800
Global SCREEN_HEIGHT = 600
Global AREA_X = 150   ; the X origin for drawing the bricks
Global AREA_Y = 30    ; the Y origin for drawing the bricks
Global AREA_WIDTH = 10   ;width of game area (in bricks)
Global AREA_HEIGHT = 5   ;height of game area (in bricks)
Global BRICK_WIDTH = 50
Global BRICK_HEIGHT= 15
Global BALL_WIDTH = 10
Global BALL_HEIGHT = 10

Global ball_x = 10
Global ball_y = 10
Global ball_x_dir = 1   ; ball x direction(1 means forwards)
Global ball_y_dir = 1   ; ball y direction(1 means down)
Global ball_x_speed = 3
Global ball_y_speed = 3


Dim Bricks(AREA_WIDTH-1,AREA_HEIGHT-1)

For y=0 To AREA_HEIGHT-1
	For x=0 To AREA_WIDTH-1
		Bricks(x,y)=1
	Next
Next

;Bricks(2,1)=0

While Not KeyHit(1)
Cls
	
	update_ball()
	
	For y = 0 To AREA_HEIGHT-1
		For x = 0 To AREA_WIDTH-1
			If Bricks(x,y)=1 Then 
				Color 255,Rand(0,135),55
				Rect AREA_X+x*BRICK_WIDTH,AREA_Y+y*BRICK_HEIGHT,BRICK_WIDTH,BRICK_HEIGHT,1
				Color 255,255,255
				Rect AREA_X+x*BRICK_WIDTH,AREA_Y+y*BRICK_HEIGHT,BRICK_WIDTH,BRICK_HEIGHT,0
			EndIf
		Next
	Next
	
	Rect ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,1
	
	Text 0,0,"BALL X:"+ball_x+" BALL:Y"+ball_y
	
	Flip
	
	
Wend
End





Function update_ball()


	If ball_x_dir = 1 Then ball_x = ball_x+ball_x_speed
	If ball_x_dir = 0 Then ball_x = ball_x-ball_x_speed
	If ball_y_dir = 1 Then ball_y = ball_y+ball_y_speed
	If ball_y_dir = 0 Then ball_y = ball_y-ball_y_speed
	
	If ball_x>(SCREEN_WIDTH-BALL_WIDTH) Then ball_x_dir = 1-ball_x_dir
	If ball_x<0 Then ball_x_dir = 1-ball_x_dir
	If ball_y>(SCREEN_HEIGHT-BALL_HEIGHT) Then ball_y_dir = 1-ball_y_dir
	If ball_y<0 Then ball_y_dir = 1-ball_y_dir
	
	
	For y = 0 To AREA_HEIGHT-1
		For x = 0 To AREA_WIDTH-1
			If Bricks(x,y)<>0
				If ball_y_dir=0 And ball_y<AREA_Y+y*BRICK_HEIGHT+BRICK_HEIGHT Then ball_y_dir = 1-ball_y_dir:Bricks(x,y)=0
			EndIf
		Next
	Next

End Function




Thanks for any help, this is driving me mad :o)


DH(Posted 2006) [#2]


Problem was you
A. Weren't taking the Ball X into account (since the for next was counting up, that explains why it started to take bricks from the left, and move right)
B. Were just checking if the ball was lower than the first box

Whereas you have to check each box fully as in my above modified version of your code :-)

Hope this helps.


Ash_UK(Posted 2006) [#3]
Thanks DH. This has really helped me out. I really appriciate it :o)

Thanks again!


DH(Posted 2006) [#4]
No problem what-so-ever :-) Love to play with other people's code from time to time.


Ash_UK(Posted 2006) [#5]
Erm, sorry to trouble you again but I seem to have a new problem with my code. When the ball is going upwards and hits a brick, it doesn't change direction for some reason.

Here is my code:





The problem seems to be on the following piece of code:

If ball_y_dir=0 And ball_y<HEIGHT_CHECK And ball_y>Y_CHECK And ball_x>X_CHECK And ball_x<WIDTH_CHECK Then
	ball_y_dir = 1-ball_y_dir
	Bricks(x,y) = 0
EndIf


Thanks again for your help :o)


Ross C(Posted 2006) [#6]
Surely ball direction should never be 0? If it is, then

ball_y_dir = 1-ball_y_dir


Would do nothing :o)


Ross C(Posted 2006) [#7]
Ah, i get it, your using 0 as the ball going upwards. Hmmm, i'll have a closer look.


Ash_UK(Posted 2006) [#8]
Ahh, good point Ross :o) I also have another problem which I have just this minute found. If you let the code run and let it clear all the bricks, you'll see what I mean. There's a sort of strange collision detection thing going on and it's not clearing the bricks properly.
This happens near the end when there's only about three bricks left.

Thanks for your help :o)


Ross C(Posted 2006) [#9]
Hmmm, i think you should try to use the rectsoverlap command, instead of checking all the directions.

If rectsoverlap( ball_x,ball_y,ball_width,ball_height, brick_x,brick_y,brick_width,brick_height) then

; reverse direction

Now, to make it easy to reverse direction, move the ball along the X axis, then check every brick for collisions. If a collision occurs, you simply reverse the X direction. Then, you move the BALL along the Y axis. Again, check every brick. If there is found to be a collision, then reverse the Y direction :o)


Ash_UK(Posted 2006) [#10]
Hmmm, have I done this right? :o)
It doesn't doesn't seem to work.

If RectsOverlap(ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,X_CHECK,Y_CHECK,BRICK_WIDTH,BRICK_HEIGHT) Then
	ball_x_dir = -ball_x_dir
	ball_y_dir = -ball_y_dir
	Bricks(x,y) = 0
EndIf




Ross C(Posted 2006) [#11]
Well, you need to move the ball along the X or Y axis first, then check against all the blocks. Then, move the ball along the other axis, then check against all the blocks...

Move ball along X AXIS
Check Ball collisions against bricks
Reverse ball direction on X AXIS if collided.

Move ball along Y AXIS
Check Ball collisions against bricks
Reverse ball direction on Y AXIS if collided.



Ash_UK(Posted 2006) [#12]
Hi Ross :o) Sorry to be a pain but could you show me how best to implement that into my code please?

Thanks again :o)


Ash_UK(Posted 2006) [#13]
Ahh, I think I've got this one down now :o) Everything seems to working fine.

Here is my code:

Graphics 800,600
SetBuffer BackBuffer()


Global SCREEN_WIDTH = 800
Global SCREEN_HEIGHT = 600
Global AREA_X = 0;(SCREEN_WIDTH/2)/4;20;150
Global AREA_Y = 30
Global AREA_WIDTH = 11
Global AREA_HEIGHT = 8
Global BRICK_WIDTH = 50
Global BRICK_HEIGHT= 15
Global BALL_WIDTH = 10
Global BALL_HEIGHT = 10

Global ball_x = AREA_X+10
Global ball_y = 10
Global ball_x_dir = 1
Global ball_y_dir = 1
Global ball_x_speed = 3
Global ball_y_speed = 3

Global BOUNDARY_X = AREA_X
Global BOUNDARY_Y = 0
Global BOUNDARY_WIDTH = (BRICK_WIDTH*AREA_WIDTH)+(BRICK_WIDTH*2)
Global BOUNDARY_HEIGHT = 600

Global USER_WIDTH = 100
Global USER_HEIGHT = 15
Global user_x = (BOUNDARY_X+BOUNDARY_WIDTH)/2 
Global user_y = 550
Global user_score = 0

Global TEXT_X = (BOUNDARY_X+BOUNDARY_WIDTH)+2


Dim Bricks(AREA_WIDTH-1,AREA_HEIGHT-1)

For y=0 To AREA_HEIGHT-1
	For x=0 To AREA_WIDTH-1
		Bricks(x,y)=1
	Next
Next




read_level()

While Not KeyHit(1)
Cls
	
	Color 0,0,65
	Rect (BOUNDARY_X+2),(BOUNDARY_Y+2),(BOUNDARY_WIDTH-4),(BOUNDARY_HEIGHT-4),1
	
	update_user()
	
	update_ball()
	
	draw_level()
	
	Color 0,0,Rand(200,255)
	Rect user_x,user_y,USER_WIDTH,USER_HEIGHT,1
	Color 255,255,255
	Rect user_x,user_y,USER_WIDTH,USER_HEIGHT,0
	Oval ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,1

	Rect BOUNDARY_X,BOUNDARY_Y,BOUNDARY_WIDTH,BOUNDARY_HEIGHT,0
	Color 255,255,255
	Rect (BOUNDARY_X+2),(BOUNDARY_Y+2),(BOUNDARY_WIDTH-4),(BOUNDARY_HEIGHT-4),0
	
	Rect TEXT_X-2,0,SCREEN_WIDTH-(TEXT_X-2),SCREEN_HEIGHT,0

	Text TEXT_X,5,"BALL X:"+ball_x 
	Text TEXT_X,35,"BALL Y:"+ball_y 
	Text TEXT_X,65,"BALL_Y_DIR:"+ball_y_dir
	Text TEXT_X,105,"SCORE:"+user_score
	
	Flip
	
	
Wend
End





Function update_ball()


	If ball_x_dir = 1 Then ball_x = ball_x+ball_x_speed
	If ball_x_dir = 0 Then ball_x = ball_x-ball_x_speed
	If ball_y_dir = 1 Then ball_y = ball_y+ball_y_speed
	If ball_y_dir = 0 Then ball_y = ball_y-ball_y_speed
	
	If ball_x>BOUNDARY_X+(BOUNDARY_WIDTH-BALL_WIDTH) Then ball_x_dir = 1-ball_x_dir
	If ball_x<BOUNDARY_X Then ball_x_dir = 1-ball_x_dir
	If ball_y>(BOUNDARY_HEIGHT-BALL_HEIGHT) Then ball_y_dir = 1-ball_y_dir
	If ball_y<BOUNDARY_Y Then ball_y_dir = 1-ball_y_dir
	
	
	For y = 0 To AREA_HEIGHT-1
		For x = 0 To AREA_WIDTH-1
			If Bricks(x,y)<>0

				X_CHECK = (AREA_X+BRICK_WIDTH)+(x*BRICK_WIDTH)
				WIDTH_CHECK = X_CHECK+BRICK_WIDTH
				Y_CHECK = AREA_Y+(y*BRICK_HEIGHT)
				HEIGHT_CHECK = Y_CHECK+BRICK_HEIGHT
				
				ball_x = ball_x+ball_x_speed
				If RectsOverlap(ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,X_CHECK,Y_CHECK,BRICK_WIDTH,BRICK_HEIGHT) Then
					ball_x_dir = 1-ball_x_dir
					Bricks(x,y) = 0
					user_score = user_score+14
				EndIf
				
				ball_x = ball_x-ball_x_speed
				If RectsOverlap(ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,X_CHECK,Y_CHECK,BRICK_WIDTH,BRICK_HEIGHT) Then
					ball_x_dir = 1-ball_x_dir
					Bricks(x,y) = 0
					user_score = user_score+14
				EndIf

				ball_y = ball_y+ball_y_speed
				If RectsOverlap(ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,X_CHECK,Y_CHECK,BRICK_WIDTH,BRICK_HEIGHT) Then
					ball_y_dir = 1-ball_y_dir
					Bricks(x,y) = 0
					user_score = user_score+14
				EndIf
				
				ball_y = ball_y-ball_y_speed
				If RectsOverlap(ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,X_CHECK,Y_CHECK,BRICK_WIDTH,BRICK_HEIGHT) Then
					ball_y_dir = 1-ball_y_dir
					Bricks(x,y) = 0
					user_score = user_score+14
				EndIf

			EndIf
		Next
	Next

End Function




Function update_user()

	user_x = user_x+MouseXSpeed()
	If user_x>BOUNDARY_X+(BOUNDARY_WIDTH-USER_WIDTH) Then user_x = BOUNDARY_X+(BOUNDARY_WIDTH-USER_WIDTH)
	If user_x<BOUNDARY_X Then user_x = BOUNDARY_X
	
	ball_x = ball_x+ball_x_speed
	If RectsOverlap(ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,user_x,user_y,USER_WIDTH,USER_HEIGHT) Then 
		ball_x_dir = 1-ball_x_dir
	EndIf
	
	ball_x = ball_x-ball_x_speed
	If RectsOverlap(ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,user_x,user_y,USER_WIDTH,USER_HEIGHT) Then 
		ball_x_dir = 1-ball_x_dir
	EndIf
	
	ball_y = ball_y+ball_y_speed
	If RectsOverlap(ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,user_x,user_y,USER_WIDTH,USER_HEIGHT) Then 
		ball_y_dir = 1-ball_y_dir
	EndIf
	
	ball_y = ball_y-ball_y_speed
	If RectsOverlap(ball_x,ball_y,BALL_WIDTH,BALL_HEIGHT,user_x,user_y,USER_WIDTH,USER_HEIGHT) Then 
		ball_y_dir = 1-ball_y_dir
	EndIf

End Function




Function read_level()
	
	Restore level1
	
	For y=0 To AREA_HEIGHT-1
		For x=0 To AREA_WIDTH-1
			Read Bricks(x,y)
		Next
	Next

End Function





Function draw_level()

	For y = 0 To AREA_HEIGHT-1
		For x = 0 To AREA_WIDTH-1
			If Bricks(x,y)=1 Then 
				Color 55,55,Rand(0,135)
				Rect (AREA_X+BRICK_WIDTH)+x*BRICK_WIDTH,AREA_Y+y*BRICK_HEIGHT,BRICK_WIDTH,BRICK_HEIGHT,1
				Color 255,255,255
				Rect (AREA_X+BRICK_WIDTH)+x*BRICK_WIDTH,AREA_Y+y*BRICK_HEIGHT,BRICK_WIDTH,BRICK_HEIGHT,0
			EndIf
		Next
	Next
	
End Function







.level1
Data 1,1,1,1,1,1,1,1,1,1,1
Data 1,1,1,1,1,1,1,1,1,1,1
Data 1,1,1,1,1,1,1,1,1,1,1
Data 1,1,1,1,1,1,1,1,1,1,1
Data 1,1,1,1,1,1,1,1,1,1,1
Data 1,1,1,1,1,1,1,1,1,1,1
Data 1,1,1,1,1,1,1,1,1,1,1
Data 1,1,1,1,1,1,1,1,1,1,1



Thanks Again guys! :o)