Code archives/Graphics/vector point to line deflection

This code has been declared by its author to be Public Domain code.

Download source code

vector point to line deflection by Jesse
(Posted 19 years ago)
I have been trying to learn vector math. and is a little bit complicate but nothing I can't Manage. I googled and found this site
http://tonypa.pri.ee/vectors/start.html
it is a good tutorial source.
it is for flash but the logic/principal is the same. so I did some work around it and managed to figure out a few things. so here is what I got so far. if you like it let me know so I can post a ball to line sample when I figure it out.
SuperStrict
Type point
	Field x#
	Field y#
End Type
Type tgame
	Field stageW%
	Field stageH%
	Field maxV#
	Field gravity#
	Field bounce:vector2d
	Field t#
	Field MyOb:vector2d
	Field v1:vector2d[5]
End Type
Type vector2d
	Field p0:point
	Field p1:point
	Field vx#,vy#
	Field dx#,dy#
	Field rx#,ry#
	Field lx#,ly#
	Field Length#
	Field timeFrame#
	Field lastTime#
	Global airf#
	Global b#
	Global f#
End Type 


Global game:tgame = New tgame
      
game.stageW = 320
game.stageH = 240
game.maxV = 10
game.gravity = 0.0;

' Create Object
' point p0 is its starting point in the coordinates x/y
game.myob = New vector2d
game.myOb.airf = 1.0
game.myOb.b = 1.0
game.myOb.f = 1.0
game.myOb.p0 = New point
game.myOb.p0.x = 150
game.myob.p0.y = 100
' vectors x/y components
game.myOb.vx = 1.0;
game.myOb.vy = 0.0;
game.myOb.lastTime = MilliSecs()
' Create first vector
' point p0 is its starting point in the coordinates x/y
' point p1 is its End point in the coordinates x/y
game.v1[1] = New vector2d
game.v1[2] = New vector2d
game.v1[3] = New vector2d
game.v1[4] = New vector2d
game.v1[1].p0 = New point
game.v1[1].p1 = New point
game.v1[1].p0.x = 5
game.v1[1].p0.y = 10
game.v1[1].p1.x = 250
game.v1[1].p1.y = 50
game.v1[1].b = 1.0
game.v1[1].f = 1.0
game.v1[2].p0 = New point
game.v1[2].p1 = New point 
game.v1[2].p0.x = 250
game.v1[2].p0.y = 50
game.v1[2].p1.x = 280
game.v1[2].p1.y = 130
game.v1[2].b = 1
game.v1[2].f = 1
game.v1[3].p0 = New point
game.v1[3].p1 = New point
game.v1[3].p0.x = 280
game.v1[3].p0.y = 130
game.v1[3].p1.x = 50
game.v1[3].p1.y = 160
game.v1[3].b = 1
game.v1[3].f = 1
game.v1[4].p0 = New point
game.v1[4].p1 = New point
game.v1[4].p0.x = 50
game.v1[4].p0.y = 160
game.v1[4].p1.x = 5
game.v1[4].p1.y = 10
game.v1[4].b = 1
game.v1[4].f = 1

Graphics game.stageW,game.stageH,32

Repeat

	Cls 
	runme()
	Flip()

Until KeyDown(key_escape)



Function runMe ()
	Local i%
	    
	For i = 1 To 4
	    updateVector(game.v1[i]);
    Next

	Local ob:vector2d = game.myOb;
    ' add air resistance
    ob.vx :* ob.airf
    ob.vy :* ob.airf
    ' dont let it go over Max speed
    If (ob.vx>game.maxV)
    	ob.vx = game.maxV
    ElseIf (ob.vx<-game.maxV)
        ob.vx = -game.maxV
    EndIf
    If (ob.vy>game.maxV)
    	ob.vy = game.maxV
    Else If (ob.vy<-game.maxV)
        ob.vy = -game.maxV
    EndIf
    ' update the vector parameters
    updateObject(ob)
    ' time To collide something big
    game.t = 1000000
    ' no collision yet
    game.bounce = Null
    ' find collisions with walls
    For Local i% = 1 To 4
    	Local t% = findIntersection(ob, game.v1[i]);
    	' If this has collision, save it
        If (t<game.t)
		    ' which wall To collide with
        	game.bounce = game.v1[i];
               ' save time
            game.t = t;
        EndIf
	Next
    ' we have collision
    If game.bounce 
    	' set End point To intersection point
    	ob.p1.x = ob.p0.x+ob.vx*game.t;
    	ob.p1.y = ob.p0.y+ob.vy*game.t;
    	' bounce
    	Local newv:vector2d = bounce(ob, game.bounce);
    	' change movement vector
    	ob.vx = newv.vx;
    	ob.vy = newv.vy;
    	' add New direction To End point
    	ob.p1.x :+ ob.vx*(1-game.t);
    	ob.p1.y :+ ob.vy*(1-game.t);
    	' save the time
   		game.t = 1-game.t;
    EndIf
    ' reset Object To other side If gone out of stage
    If (ob.p1.x>game.stageW)
    	ob.p1.x :- game.stageW;
    ElseIf (ob.p1.x<0)
    	ob.p1.x :+ game.stageW;
    EndIf
    If (ob.p1.y>game.stageH)
    	ob.p1.y :- game.stageH;
    ElseIf (ob.p1.y<0)
    	ob.p1.y :+ game.stageH;
    EndIf
	' draw it
	drawAll(ob);
	' make End point equal To starting point For Next cycle
	ob.p0 = ob.p1;
	' save the movement without time
	ob.vx :/ ob.timeFrame;
	ob.vy :/ ob.timeFrame;
End Function

' Function To find all parameters For the vector
Function updateVector (v:vector2d)
	' x And y components
	' End point coordinate - start point coordinate
	v.vx = v.p1.x-v.p0.x;
	v.vy = v.p1.y-v.p0.y;
	' length of vector
	v.Length = Sqr(v.vx*v.vx+v.vy*v.vy);
	' normalized unti-sized components
	If (v.Length>0) 
		v.dx = v.vx/v.Length;
		v.dy = v.vy/v.Length;
	Else
		v.dx = 0;
		v.dy = 0;
	EndIf
	' Right hand normal
	v.rx = -v.vy;
	v.ry = v.vx;
	' Left hand normal
	v.lx = v.vy;
	v.ly = -v.vx;
End Function

Function updateObject (v:vector2d)
	' find time passed from last update
    Local thisTime# = MilliSecs()
    Local time# = (thisTime-v.lastTime)/6.0
    ' we use time, Not frames To move so multiply movement vector with time passed
    v.vx :* time;
    v.vy :* time;
    ' add gravity, also based on time
    v.vy = v.vy+time*game.gravity;
    'v.p1 = {};
	v.p1 = New point
    ' find End point coordinates
    v.p1.x = v.p0.x+v.vx;
    v.p1.y = v.p0.y+v.vy;
    ' length of vector
    v.Length = Sqr(v.vx*v.vx+v.vy*v.vy);
    ' normalized unti-sized components
    v.dx = v.vx/v.Length;
    v.dy = v.vy/v.Length;
    ' Right hand normal
    v.rx = -v.vy;
    v.ry = v.vx;
    ' Left hand normal
    v.lx = v.vy;
    v.ly = -v.vx;
    ' save the current time
    v.lastTime = thisTime;
    ' save time passed
    v.timeFrame = time;
End Function

' find intersection point of 2 vectors

Function findIntersection:Int (v1:vector2d, v2:vector2d)
' vector between starting points
	Local t1#,t2#
	Local v3a:vector2d = New vector2d
	Local v3b:vector2d = New Vector2d
 	v3a.vx = v2.p0.x - v1.p0.x
	v3a.vy = v2.p0.y - v1.p0.y
    v3b.vx = v1.p0.x - v2.p0.x
	v3b.vy = v1.p0.y - v2.p0.y
    ' If they are parallel vectors, Return big number
    If ((v1.dx = v2.dx And v1.dy = v2.dy) Or (v1.dx = -v2.dx And v1.dy = -v2.dy))
    	Return 1000000;
	Else
    	t1 = perP(v3a, v2)/perP(v1, v2)
        t2 = perP(v3b, v1)/perP(v2, v1)
    EndIf
    If (t1>0 And t1<=1 And t2>0 And t2<=1)
    	Return t1;
	Else
    	Return 1000000;
    EndIf
End Function

' calculate perp product of 2 vectors
Function perP# (va:vector2d, vb:vector2d)

	Return va.vx*vb.vy-va.vy*vb.vx;
         
End Function
      
' find New vector bouncing from v2
Function bounce:vector2d (v1:vector2d, v2:vector2d)
	' projection of v1 on v2
    Local proj1:vector2d = projectVector(v1, v2.dx, v2.dy);
    ' projection of v1 on v2 normal
    Local proj2:vector2d = projectVector(v1, v2.lx/v2.Length, v2.ly/v2.Length);
    Local proj:vector2d = New vector2d
    ' reverse projection on v2 normal
    proj2.vx :* -1;
    proj2.vy :* -1;
    ' add the projections
    proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
    proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
    Return proj;
End Function

Function 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 Function

Function drawall(v:vector2d)
	Local vn:vector2d
	For Local i:Int = 1 To 4
		vn = game.v1[i]
		DrawLine vn.p0.x,vn.p0.y,vn.p1.x,vn.p1.y
	Next	
	DrawOval v.p0.x-2,v.p0.y-2,4,4
End Function