Bouncing a ball off moving bricks

BlitzMax Forums/BlitzMax Beginners Area/Bouncing a ball off moving bricks

I'm in the middle of creating a breakout-style game. The ball is bouncing fine at the moment, but only when the bricks are not moving. When the ball collides with a moving brick, sometimes it will calculate the collision wrong and the ball will end up passing through the brick instead of reflecting off it. Here's some code to see what I mean:


superstrict

type Tball
	field x: float
	field y: float
	field w: float
	field h: float
	field dx: float
	field dy: float
	field hit: int
	field temp_x: float
	field temp_y: float
end type

type Tbrick
	field x: float
	field y: float
	field w: float
	field h: float
	field dx: float
	field dy: float
end type

graphics(800,600,0)

local ball: Tball = new Tball
ball.x = 374
ball.y = 100
ball.w = 16
ball.h = 16
ball.dx = 0
ball.dy = 5

local brick: Tbrick = new Tbrick
brick.x = 350
brick.y = 200
brick.w = 64
brick.h = 32
brick.dx = 0
brick.dy = 1

repeat	
		
	' Move Ball X
	ball.temp_x = ball.x + ball.dx
	if ball.hit = false
		if (overlap(ball.temp_x,ball.temp_y,ball.w,ball.h,brick.x,brick.y,brick.w,brick.h))
			ball.dx = -ball.dx
			ball.hit = true
			notify("Horizontal Collision")
			ball.temp_x = ball.x
		endif
	endif
	ball.x = ball.temp_x
	
	' Move Ball Y
	ball.temp_y = ball.y + ball.dy
	if ball.hit = false
		if (overlap(ball.temp_x,ball.temp_y,ball.w,ball.h,brick.x,brick.y,brick.w,brick.h))
			ball.dy = -ball.dy
			ball.hit = true
			notify("Vertical Collision")
			ball.temp_y = ball.y
		endif
	endif
	ball.y = ball.temp_y
	
	' Bounce ball off walls
	if (ball.x > 800 - ball.w or ball.x < 0) ball.dx = -ball.dx ; ball.hit = false
	if (ball.y > 600 - ball.h or ball.y < 0) ball.dy = -ball.dy ; ball.hit = false
	
	
	' Move Brick
	brick.x :+ brick.dx
	brick.y :+ brick.dy
	
	' Bounce brick off walls
	if (brick.x > 800 - (brick.w * 2) or brick.x < brick.w) brick.dx = -brick.dx
	if (brick.y > 600 - (brick.h * 2) or brick.y < brick.h) brick.dy = -brick.dy
			
	
	' Draw
	cls
	if (ball.hit) drawtext("Hit",0,0)
	
	' Ball
	setcolor(255,255,255)
	draw_unfilled_rect(ball.x,ball.y,ball.w,ball.h)
	
	' Brick
	setcolor(0,255,0)
	draw_unfilled_rect(brick.x,brick.y,brick.w,brick.h)
	flip
until keydown(KEY_ESCAPE)
end

function draw_unfilled_rect(x: float, y: float, w: float, h: float)
	w = (w + x) 
	h = (h + y)
	drawline(x, y, w, y)
	drawline(x, h, w, h)
	drawline(x, y, x, h)
	drawline(w, y, w, h)
end function

function overlap: int(x1: float,y1: float,w1: float,h1: float, x2: float,y2: float,w2: float, h2: float)
	if ((x1 + w1) > x2) and ((x1 + w1) < (x2 + (w2 + w1))) and ((y1 + h1) > y2) and ((y1 + h1) < (y2 + (h2 + h1))) return true
end function



How would I fix this code so the ball would bounce off the brick correctly? Thanks in advance.

here you go:
SuperStrict

Type Tball
	Field x: Float
	Field y: Float
	Field w: Float
	Field h: Float
	Field dx: Float
	Field dy: Float
	Field hit: Int
	Field temp_x: Float
	Field temp_y: Float
End Type

Type Tbrick
	Field x: Float
	Field y: Float
	Field w: Float
	Field h: Float
	Field dx: Float
	Field dy: Float
End Type

Graphics(800,600,32,60)

Local ball: Tball = New Tball
ball.x = 374
ball.y = 100
ball.w = 16
ball.h = 16
ball.dx = 0
ball.dy = 5

Local brick: Tbrick = New Tbrick
brick.x = 350
brick.y = 200
brick.w = 64
brick.h = 32
brick.dx = 0
brick.dy = 1

Repeat	
	Cls	
	' Move Ball X
	If ball.hit = False
		If (overlap(ball.temp_x+ball.dx,ball.temp_y,ball.w,ball.h,brick.x,brick.y,brick.w,brick.h))
			ball.dx = -ball.dx
			ball.hit = True
			DrawText "Horizontal Collision", 300,10
			ball.temp_x = ball.x
		EndIf
	EndIf
	ball.temp_x = ball.x + ball.dx
	ball.x = ball.temp_x
	
	' Move Ball Y
	If ball.hit = False
		If (overlap(ball.temp_x,ball.temp_y+ball.dy,ball.w,ball.h,brick.x,brick.y,brick.w,brick.h))
			ball.dy = -ball.dy
			ball.hit = True
			DrawText "Vertical Collision",300,40
			ball.temp_y = ball.y
		EndIf
	EndIf
	ball.temp_y = ball.y + ball.dy
	ball.y = ball.temp_y
	
	' Bounce ball off walls
	If (ball.x > 800 - ball.w Or ball.x < 0) ball.dx = -ball.dx ; ball.hit = False
	If (ball.y > 600 - ball.h Or ball.y < 0) ball.dy = -ball.dy ; ball.hit = False
	
	
	' Move Brick
	brick.x :+ brick.dx
	brick.y :+ brick.dy
	
	' Bounce brick off walls
	If (brick.x > 800 - (brick.w * 2) Or brick.x < brick.w) brick.dx = -brick.dx
	If (brick.y > 600 - (brick.h * 2) Or brick.y < brick.h) brick.dy = -brick.dy
			
	
	' Draw
	
	If (ball.hit) DrawText("Hit",0,0)
	
	' Ball
	SetColor(255,255,255)
	draw_unfilled_rect(ball.x,ball.y,ball.w,ball.h)
	
	' Brick
	SetColor(0,255,0)
	draw_unfilled_rect(brick.x,brick.y,brick.w,brick.h)
	Flip
Until KeyDown(KEY_ESCAPE)
End

Function draw_unfilled_rect(x: Float, y: Float, w: Float, h: Float)
	w = (w + x) 
	h = (h + y)
	DrawLine(x, y, w, y)
	DrawLine(x, h, w, h)
	DrawLine(x, y, x, h)
	DrawLine(w, y, w, h)
End Function

Function overlap: Int(x1: Float,y1: Float,w1: Float,h1: Float, x2: Float,y2: Float,w2: Float, h2: Float)
	If ((x1 + w1) > x2) And ((x1 + w1) < (x2 + (w2 + w1))) And ((y1 + h1) > y2) And ((y1 + h1) < (y2 + (h2 + h1))) Return True
End Function

the way you have it, you are doing two tests inside the brick. the first test was done when the ball was 4 pixels inside the brick the second was when you were 1 pixels inside the brick the 1 pixel is the brick movement. and that is why it was going through.

Many thanks for the quick reply! It's working fine now.