Code archives/Graphics/vectors part 3
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| the sample below is code based on the tutorials from the flash tutorials in this page link: http://tonypa.pri.ee/vectors/start.html next: ball to wall collition. | |||||
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#)
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(True)
End Method
Method animate ()
' start To calculate movement
' 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;
ElseIf (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 Local w:vector2d = EachIn game.walllist
Local v:vector2d = MyOb.findIntersection(w);
v = v.updateVector(False);
Local pen# = MyOb.r-v.Length;
' If we have hit the wall
If (pen>=0)
' move Object away from the wall
MyOb.p1.x :+ v.dx*pen;
MyOb.p1.y :+ v.dy*pen;
' change movement, bounce off from the normal of v
Local vbounce:vector2d = New vector2d
vbounce.dx = v.lx
vbounce.dy = v.ly
vbounce.lx = v.dx
vbounce.ly = v.dy
vbounce.b = 1
vbounce.f = 1
Local vb:vector2d = MyOb.bounced(vbounce);
MyOb.vx = vb.vx;
MyOb.vy = vb.vy;
EndIf
Next
' reset Object To other side If gone out of stage
If (MyOb.p1.x>game.stageW+MyOb.r)
MyOb.p1.x = -MyOb.r;
Else If (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;
Else If (MyOb.p1.y<-MyOb.r)
MyOb.p1.y = game.stageH+MyOb.r;
EndIf
' draw it
'drawAll();
' 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;
EndMethod
Method drawall()
Local i%
For Local v:vector2d = EachIn game.walllist
DrawLine v.p0.x,v.p0.y,v.p1.x,v.p1.y
Next
DrawOval myOb.p0.x - myOb.r, myOb.p0.y - myOb.r,..
MyOb.r * 2,myOb.r * 2
End Method ' main Function
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 updateVector:vector2d (frompoints:Int)
' x And y components
If (frompoints)
vx = p1.x-p0.x;
vy = p1.y-p0.y;
Else
p0 = New point
p1 = New point
p1.x = p0.x+vx;
p1.y = p0.y+vy;
EndIf
' 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
Method updateObject ()
' find time passed from last update
Local thisTime# = MilliSecs();
Local 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 findIntersection:vector2d (v2:vector2d)
' vector between center of ball And starting point of wall
Local v3:vector2d = New vector2d
Local v:vector2d
v3.vx = p1.x-v2.p0.x;
v3.vy = p1.y-v2.p0.y;
' check If we have hit starting point
Local dp# = v3.vx*v2.dx+v3.vy*v2.dy;
If (dp<0)
' hits starting point
v = v3;
Else
Local v4:vector2d = New vector2d
v4.vx = p1.x-v2.p1.x;
v4.vy = p1.y-v2.p1.y;
' check If we have hit side Or endpoint
dp = v4.vx*v2.dx+v4.vy*v2.dy;
If (dp>0)
' hits ending point
v = v4;
Else
' it hits the wall
' project this vector on the normal of the wall
v = v3.projectVector(v2.lx, v2.ly);
EndIf
EndIf
Return v;
EndMethod
Method bounced:vector2d (v2:vector2d)
' projection of v1 on v2
Local proj1:vector2d = projectVector(v2.dx, v2.dy);
' projection of v1 on v2 normal
Local proj2:vector2d = projectVector(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 (dx#, dy#)
' find dot product
Local dp# = vx*dx+vy*dy;
Local proj:vector2d = New vector2d
' projection components
proj.vx = dp*dx;
proj.vy = dp*dy;
Return proj;
End Method
End Type
Global game:tgame = New tgame
game.Create(640,480,10,0.5)
game.myOb.vx = 5;
game.myOb.vy = -5;
game.myOb.airf = .99
game.myOb.b = 1
game.myOb.f = 1
game.myOb.r = 20
game.MyOb.lastTime = MilliSecs()
game.myOb.p0 = New point
game.myOb.p0.x = 200
game.myOb.p0.y = 30
' vectors x/y components
game.myOb.vx = 5
game.myOb.vy = -5
Local v:vector2d = New vector2d
game.createWall(250,110,50,100,1,1)
game.createwall(250,150,250,110,1,1)
game.createWall(50,150,250,150,1,1)
game.createWall(50,100,50,150, 1,1)
game.createWall(250,300,400,280,1,1)
game.createWall(250,300,250,350,1,1)
game.createWall(400,280,400,330,1,1)
game.createWall(250,350,400,330,1,1)
Graphics game.stageW,game.stageH
Repeat
Cls
game.animate()
game.drawall()
Flip()
Until KeyDown(key_escape) |
Comments
None.
Code Archives Forum