Good idea
I have hit a snag with Line intersect <> ball code from the archives though. When a new line is added for the collision test, the ball will deflect regardless of where the line ends
It's as if an imaginary line goes all the way across the screen
The RED line has been added in this screenshot. The ball bounces as shown and cannot 'pass by' where the line ends:

The line only works one way too. Depending which way the line is draw it is possible for the ball to pass straight through. After which it rebounds back as expected
Any other ways to resolve this? Help appreciated
What I have so far ..
MAIN SOURCE
SuperStrict
Framework BRL.GLMax2D
Import BRL.Blitz
Import "LineBallColl.bmx"
' Create gameMyObject
' CreateMyObject
' point p0 is its starting point in the coordinates x/y
game.Create(640,480,80,0.0)
game.myOb.airf = 0.982
game.myOb.b = 0.5
game.myOb.f = 0.995
game.myOb.r = 10
game.MyOb.lastTime = MilliSecs()
game.myOb.p0 = New point
game.myOb.p0.x = 350
game.myOb.p0.y = 120
' vectors x/y components
game.myOb.vx = 0.0;
game.myOb.vy = 0.0;
Local v:vector2d = New vector2d
game.createWall(600,30,50,50,1,1)
game.createWall(250,450,600,30,1,1)
game.createWall(50,380,250,450,1,1)
game.createWall(50,50,50,380,1,1)
Global starttime% , timeout%
Global mx# , my#
Type edit
Global mode%,line%,x%,y%
End Type
Graphics game.stageW,game.stageH
' =======================================================
Repeat
Cls
If MouseHit(2)
edit.mode=~edit.mode ; FlushMouse
If edit.mode=False
edit.line=0 ; game.myob.vx=0 ; game.myob.vy=0
EndIf
EndIf
If edit.mode
Editor
Else
GameUpdate
EndIf
Flip
Until KeyDown(key_escape)
' =======================================================
Function GameUpdate()
game.animate(game.myob)
game.drawall(game.myob)
If game.myob.moving=0
mx=MouseX() ; my=MouseY()
SetColor $77,$77,$77
DrawLine game.myob.p0.x,game.myob.p0.y , mx,my
If MouseHit(1)
Local d#=Dist(mx,my,game.myob.p0.x,game.myob.p0.y)
Local a#=Ang(mx,my,game.myob.p0.x,game.myob.p0.y)
game.myob.vx=Sin(a)*(d/3.5)
game.myob.vy=-Cos(a)*(d/3.5)
EndIf
EndIf
Msg "LMB = Shoot RMB for editor"
End Function
Function Editor()
Cls
Msg "LMB = add line RMB= return to game"
SetColor $aa,$44,$16
For Local v:vector2d = EachIn game.Walllist
DrawLine v.p0.x,v.p0.y,v.p1.x,v.p1.y
Next
If edit.line=1 DrawLine edit.x,edit.y,MouseX(),MouseY()
If MouseHit(1)
Select edit.line
Case 0
edit.x=MouseX() ; edit.y=MouseY()
edit.line=1
Case 1
game.createWall(edit.x,edit.y,MouseX(),MouseY(),1,1)
edit.line=0
End Select
EndIf
End Function
Function Msg(t$)
SetColor $ff,$ff,$ff
DrawText t$,10,5
End Function
Function Dist#(x1#,y1#,x2#,y2#)
Local dx#=Abs(x1-x2)
Local dy#=Abs(y1-y2)
Return Sqr(dx*dx + dy*dy)
End Function
Function Ang#(x1#,y1#,x2#,y2#)
Local dx#=x1-x2
Local dy#=y1-y2
Return 180.0-ATan2(dx,dy)
End Function
####################################
IMPORT code "BallLineColl.bmx"
' Line/Ball collision and deflection - Jesse
SuperStrict
Import BRL.LinkedList
Type point
Field x# , y#
End Type
Type tgame
Field stageW% , stageH%
Field maxV# , gravity#
Field bounce:vector2d
Field MyOb:vector2d
Global walllist:TList
'
Method Create(W%,H%,V#,G#)
walllist = CreateList()
stageW = W ; stageH = H
maxV = V ; gravity = G
myOb = New vector2d
End Method
'
Method CreateWall(x1#,y1#,x2#,y2#,b#,f#)
' Create vector
' point p0 is its starting point in the coordinates x/y
' point p1 is its ending point in the coordinates x/y
Local v:vector2d = New vector2d
walllist.addlast(v)
v.p0 = New point
v.p0.x = x1 ; v.p0.y = y1
v.p1 =New point
v.p1.x = x2 ; v.p1.y = y2
v.b = b ; v.f = f
v.updateVector()
End Method
'
Method Animate(MyOb:vector2d)
Local i%,w:vector2d,vb:vector2d,pen#
' add air resistance
MyOb.vx :* MyOb.airf;
MyOb.vy :* MyOb.airf;
' dont let it go over Max speed
If (Myob.vx>game.maxV)
MyOb.vx = game.maxV;
Else If (MyOb.vx<-game.maxV)
MyOb.vx = -game.maxV;
EndIf
If (MyOb.vy>game.maxV)
MyOb.vy = game.maxV;
Else If (MyOb.vy<-game.maxV)
MyOb.vy = -game.maxV;
EndIf
' update the vector parameters
myob.updateObject();
' check the walls For collisions
For w = EachIn game.Walllist
' If we have hit the wall
pen# = MyOb.r-myOb.findIntersection(w);
If pen>=0
' move MyObject away from the wall
MyOb.p1.x :+ w.lx*pen
MyOb.p1.y :+ w.ly*pen
' change movement
vb = myob.bounce(w)
MyOb.vx = vb.vx
MyOb.vy = vb.vy
EndIf
Next
' reset MyObject To other side If gone out of stage
If (MyOb.p1.x>game.stageW+MyOb.r)
MyOb.p1.x = -Myob.r;
ElseIf (Myob.p1.x<-Myob.r)
MyOb.p1.x = game.stageW+Myob.r;
EndIf
If (Myob.p1.y>game.stageH+Myob.r)
MyOb.p1.y = -Myob.r;
ElseIf (Myob.p1.y<-Myob.r)
MyOb.p1.y = game.stageH+Myob.r;
EndIf
' draw it
drawAll(Myob);
' make End point equal To starting point For Next cycle
MyOb.p0 = MyOb.p1;
' save the movement without time
MyOb.vx :/ MyOb.timeFrame
MyOb.vy :/ MyOb.timeFrame
End Method
'
Method DrawAll(v1:vector2d)
SetColor $77,$ff,$66
For Local v:vector2d = EachIn game.Walllist
DrawLine v.p0.x,v.p0.y,v.p1.x,v.p1.y
Next
SetColor $ff,$ff,$40
DrawOval v1.p0.x-v1.r,v1.p0.y-v1.r,..
v1.r*2,v1.r*2
End Method
'
End Type
Type vector2d
Field p0:point
Field p1:point
Field vx#,vy# , dx#,dy# , rx#,ry# , lx#,ly#
Field Length# , timeFrame# , lastTime#
Field r# , airf# , b# , f# , moving%
'
Method updateObject()
Local ThisTime#,time#
' find time passed from last update
thisTime = MilliSecs();
time = (thisTime - lastTime) /100
' we use time, Not frames To move so multiply movement vector with time passed
vx :* time ; vy :* time;
moving=True
If (vx>-0.04 And vx<0.04) Then vx=0
If (vy>-0.04 And vy<0.04) Then vy=0
If (vx=0 And vy=0) Then moving=False
' add gravity, also based on time
vy = vy+time*game.gravity;
p1 = New point;
' find End point coordinates
p1.x = p0.x+vx ; p1.y = p0.y+vy;
' length of vector
Length = Sqr(vx*vx+vy*vy);
' normalized unti-sized components
dx = vx/Length ; dy = vy/Length
' Right hand normal
rx = -vy ; ry = vx;
' Left hand normal
lx = vy ; ly = -vx;
' save the current time
lastTime = thisTime;
' save time passed
timeFrame = time;
End Method
'
Method updateVector:vector2d()
' x And y components
' End point coordinate - start point coordinate
vx = p1.x-p0.x ; vy = p1.y-p0.y
' length of vector
Length = Sqr(vx*vx+vy*vy);
' normalized unti-sized components
If (Length>0)
dx = vx/Length ; dy = vy/Length;
Else
dx = 0 ; dy = 0;
EndIf
' Right hand normal
rx = -dy ; ry = dx;
' Left hand normal
lx = dy ; ly = -dx;
Return Self
End Method
'
' find New vector bouncing from v2
Method bounce:vector2d(v2:vector2d)
' projection of v1 on v2
Local proj1:vector2d = projectVector(Self, v2.dx, v2.dy);
' projection of v1 on v2 normal
Local proj2:vector2d = projectVector(Self, v2.lx, v2.ly);
Local proj:vector2d = New vector2d
' reverse projection on v2 normal
proj2.Length = Sqr(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
proj2.vx = v2.lx*proj2.Length
proj2.vy = v2.ly*proj2.Length
' add the projections
proj.vx = f*v2.f*proj1.vx+b*v2.b*proj2.vx
proj.vy = f*v2.f*proj1.vy+b*v2.b*proj2.vy
Return proj
End Method
'
' project vector v1 on unit-sized vector dx/dy
Method projectVector:vector2d (v1:vector2d, dx#, dy#)
' find dot product
Local dp# = v1.vx*dx+v1.vy*dy;
Local proj:vector2d = New vector2d
' projection components
proj.vx = dp*dx ; proj.vy = dp*dy;
Return proj;
End Method
'
' find intersection point of 2 vectors
Method findIntersection# (v2:vector2d)
' vector between center of ball And starting point of wall
Local v3:vector2d = New vector2d
v3.vx = p1.x-v2.p0.x;
v3.vy = p1.y-v2.p0.y;
' project this vector on the normal of the wall
Local v:vector2d = projectVector(v3, v2.lx, v2.ly)
' find length of projection
v.Length = Sqr(v.vx*v.vx+v.vy*v.vy)
Return v.Length
End Method
'
End Type
Global game:tgame = New tgame