Code archives/Graphics/vectors part 2
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| this is the continuation from my point to line collition and deflection. this is a ball to line collition and deflection with gravity. now I have encapsulated it into objects. Maybe Easier to understand and use. I Hope. :) note: collition is not constrained to the length of the line Which makes it only usefull for encapsulating. next I will figure out vector segment and corner collition. comming soon. maybe :) | |||||
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
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 End 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()
Local i%,w:vector2d,vb:vector2d,pen#
Local MyOb:vector2d = game.myOb;
' 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)
For Local v:vector2d = EachIn game.Walllist
DrawLine v.p0.x,v.p0.y,v.p1.x,v.p1.y
Next
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#
Field dx#,dy#
Field rx#,ry#
Field lx#,ly#
Field Length#
Field timeFrame#
Field lastTime#
Field r#
Global airf#
Global b#
Global f#
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;
' 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
' Create gameMyObject
' CreateMyObject
' point p0 is its starting point in the coordinates x/y
game.Create(640,480,20,0.6)
game.myOb.airf = 1.0
game.myOb.b = 0.5
game.myOb.f = 0.9
game.myOb.r = 20
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;
game.myOb.vy = -25;
Local v:vector2d = New vector2d
game.createWall(600,50,50,50,1,1)
game.createWall(250,450,600,50,1,1)
game.createWall(50,450,250,450,1,1)
game.createWall(50,50,50,450,1,1)
Graphics game.stageW,game.stageH
Repeat
Cls
game.animate()
game.drawall(game.myob)
Flip()
Until KeyDown(key_escape) |
Comments
None.
Code Archives Forum