I'm not sure that using angles is the best way to do it - use a vector instead. That way, when you bounce off a horizontal surface all you need to do is reverse the y component of the vector, and if bouncing off a vertical surface, reverse the x component.
Also, if you don't mind doing the conversion, there was some code I posted in my plug-ins thread in the DLL forum for bouncing a circle off a box that handled it in exactly this way - here it is:
sync on
sync rate 0
sync sleep 1
x as float
y as float
radius as float
xspeed as float
yspeed as float
x = screen width() / 2
y = screen height() / 2
radius = 20.0
repeat
xspeed = rnd(20) / 5.0
yspeed = rnd(20) / 5.0
until xspeed <> 0.0 and yspeed <> 0.0
do
cls
set cursor 0, 0
circle x, y, radius
box 100, 100, 200, 150
Result = CircleBoxCollision_Side( x, y, radius, 100, 100, 200, 150 )
if Result = 0 and xspeed > 0.0 then xspeed = 0.0 - xspeed
if Result = 1 and xspeed < 0.0 then xspeed = 0.0 - xspeed
if Result = 2 and yspeed > 0.0 then yspeed = 0.0 - yspeed
if Result = 3 and yspeed < 0.0 then yspeed = 0.0 - yspeed
inc x, xspeed
inc y, yspeed
if x < radius then xspeed = 0.0 - xspeed
if x > screen width() - radius then xspeed = 0.0 - xspeed
if y < radius then yspeed = 0.0 - yspeed
if y > screen height() - radius then yspeed = 0.0 - yspeed
sync
loop
function CircleBoxCollision(cx as integer, cy as integer, cr as integer, bx1 as integer, by1 as integer, bx2 as integer, by2 as integer)
local Collision as integer = 0
local nx as integer
local ny as integer
` Find nearest point from centre of circle to the rectangle (works even if within rectangle)
nx = min(max(cx, bx1), bx2)
ny = min(max(cy, by1), by2)
` Check if within circle radius (pythagoras, except square roots cancel each other)
if ( (cx - nx) ^ 2 + (cy - ny) ^ 2) <= cr ^ 2 then Collision = 1
endfunction Collision
function CircleBoxCollision_Side(cx as integer, cy as integer, cr as integer, bx1 as integer, by1 as integer, bx2 as integer, by2 as integer)
local Collision as integer = -1
` Nearest point
local nx as integer
local ny as integer
` Distance to edges
local dx as integer
local dy as integer
` Which edges
local XSide as integer
local YSide as integer
` Find nearest point from centre of circle to the rectangle (works even if within rectangle)
nx = min(max(cx, bx1), bx2)
ny = min(max(cy, by1), by2)
` Check if within circle radius (pythagoras, except square roots cancel, so avoids divide-by-zero error)
if ( (cx - nx) ^ 2 + (cy - ny) ^ 2) <= cr ^ 2
` Find nearest edge for x
if cx < (bx1 + bx2) / 2
dx = cx - bx1
XSide = 0
else
dx = bx2 - cx
XSide = 1
endif
` Find nearest edge for y
if cy < (by1 + by2) / 2
dy = cy - by1
YSide = 2
else
dy = by2 - cy
YSide = 3
endif
` Is X closer than Y
if dx < dy
Collision = XSide
else
Collision = YSide
endif
endif
endfunction Collision
It should be trivial to convert it.