Diablo, THANKS!!
It all works now!
YES!
Check this out!
Requires: Vector2D.bmx (See my first post above)
Strict
Include "Vector2D.bmx"
Include "Circle2D.bmx"
'''''''''' seting Lines
Global Vector:Vector2D[10]
Vector[0] = Vector2d.create(4.0000000000000000 , 1.0000000000000000)
Vector[1] = Vector2d.create(204.00000000000000 , 369.00000000000000)
Vector[2] = Vector2d.create(197.00000000000000 , 238.00000000000000)
Vector[3] = Vector2d.create(634.00000000000000 , 0.0000000000000000)
Vector[4] = Vector2d.create(122.00000000000000 , 448.00000000000000)
Vector[5] = Vector2d.create(499.00000000000000 , 448.00000000000000)
Vector[6] = Vector2d.create(499.00000000000000 , 448.00000000000000)
Vector[7] = Vector2d.create(499.00000000000000 , 225.00000000000000)
Vector[8] = Vector2d.create(122.00000000000000 , 448.00000000000000)
Vector[9] = Vector2d.create(122.00000000000000 , 221.00000000000000)
'''''''''''''''''' Ball stuff and gravity
Global Grav:Vector2d = Vector2d.create(0, 0.000098)
Global Ball:Circle2d = Circle2d.create(400 , 20 , 10)
Global BallVelocity:Vector2d = Vector2d.create(0,0)
'''''''''''''''''''''''''''''''''''''''''Graphics and main Loop
Graphics 640 , 480, 0, 60
While Not KeyHit(KEY_ESCAPE)
Cls
'''''''''' Drawing
SetScale 1.0 , 1.0
DrawText MouseX() + " " + MouseY() , 10 , 10
For Local i = 0 To Vector.Length - 1 Step 2
SetColor 0 , 255 , 0
DrawLine Vector[i].x , Vector[i].y , Vector[i+1].x , Vector[i+1].y
SetColor 200 , 150 , 100
DrawText i , Vector[i].x , Vector[i].y
DrawText i + 1 , Vector[i + 1].x , Vector[i + 1].y
Next
SetColor 0 , 0 , 255
Ball.Draw()
'''''' Forces
BallVelocity.add( Grav )
CheckCollision()
SetColor 255,255,255
'BallVelocity.DrawModify( Ball.Position, 1000, 0 )
'''''' Update Positions and store data for the old ones
Local PreBall:Vector2D = Ball.position.copy()
Ball.position.add(BallVelocity)
''''''' Positionning Lines
''''''''''''''''''Line[0]
If KeyDown(Key_0)
Vector[0].x = MouseX()
Vector[0].y = MouseY()
End If
If KeyDown(Key_1)
Vector[1].x = MouseX()
Vector[1].y = MouseY()
End If
''''''''''''''''''Line[1]
If KeyDown(Key_2)
Vector[2].x = MouseX()
Vector[2].y = MouseY()
End If
If KeyDown(Key_3)
Vector[3].x = MouseX()
Vector[3].y = MouseY()
End If
''''''''''''''''''Line[1]
If KeyDown(Key_4)
Vector[4].x = MouseX()
Vector[4].y = MouseY()
End If
If KeyDown(Key_5)
Vector[5].x = MouseX()
Vector[5].y = MouseY()
End If
''''''''''''''''''Line[3]
If KeyDown(Key_6)
Vector[6].x = MouseX()
Vector[6].y = MouseY()
End If
If KeyDown(Key_7)
Vector[7].x = MouseX()
Vector[7].y = MouseY()
End If
''''''''''''''''''Line[4]
If KeyDown(Key_8)
Vector[8].x = MouseX()
Vector[8].y = MouseY()
End If
If KeyDown(Key_9)
Vector[9].x = MouseX()
Vector[9].y = MouseY()
End If
''''''''''''''''''''''' Psitionning Ball
If MouseDown(1)
Ball.Position.set( MouseX() , MouseY() )
BallVelocity.set(0,0)
End If
Flip 1
Wend
'''''''''''' To copy paste this to the setting Line section on the top and have the costom MAP
Print ""
Print "copy paste the below"
Print "''''''''''''''''''''''''''''''''''''''''''''"
Print "Local Vector:Vector2d[10]"
For Local i:Byte = 0 To Vector.Length - 1
Local printout$ = ""
Printout:+ "Vector[" + i +"] = Vector2d.create(" + Vector[i].x + " , " + Vector[i].y + ")"
Print printout
' Vector[0] = Vector2d.create(100 , 300)
' Vector[1] = Vector2d.create(300 , 300)
Next
End
Function CheckCollision()
For Local i = 0 To Vector.Length - 1 Step 2
'
' 1. Detect collision
' Makes sure that with our current velocity and shape ( this time we are a circle )
' we do not pass through any lines
' This function does not check that, but this works if our velocity is not larger than or cirles radius
' The check for collision rutine need improvement!
'
'Local OverlapDist! = MinDistPointLine(Ball.position.x , Ball.position.y , Vector[i].x , Vector[i].y , Vector[i +1].x , Vector[i +1].y)
Local VectorToLine:Vector2D = VectorToLine(Ball.position.x , Ball.position.y , Vector[i].x , Vector[i].y , Vector[i +1].x , Vector[i +1].y)
If VectorToLine.Length() < Ball.Radius
SetColor 255 , 0 , 0 'Just for fun
SetScale 1.0 , 1.0
DrawText "\__ COLLIDE" , Ball.position.x , Ball.position.y ' Just for fun
' 2. Project out of collision
'Move backwards along the velocity vector until we are out of collision.
''''''''''''''''''''''''Local DistIntoWall = Ball.Radius - OverlapDist
'Make velocity unit vector
'''''''Local ProjectVector:Vector2D = CreateUnitVector( BallVelocity )
'''''''ProjectVector.Reverse()
Ball.Position.subtract( VectorToLine ) 'We are now right where we are supposed to be. (right before the wall)
VectorToLine.Normalize()
VectorToLine.Multiply( Ball.Radius - VectorToLine.Length() )
Ball.Position.add( VectorToLine )
' 3. Get the line's surface normal
Local Surface:Vector2D = Vector2D.CreateFrom( Vector[i] , Vector[i +1] )
Local SurfaceNormal:Vector2D = Surface.CreateRightNormal()
'BallVelocity = BallVelocity.Reflect( SurfaceNormal )
' 4. Apply response on velocity ( reflect )
ApplyResponse( BallVelocity, SurfaceNormal, 0.00, 0.2 )' 0,0 would be Perfect Slide
'Now before we move we should check that this new Velocity does not collide in something else.
Ball.Position.add( BallVelocity )' It is safe to move ( Not really!)
' Right now we only check against the remaining lines - which could be none or all
'
End If
Next
EndFunction
Function DistanceCircleLine( Circle:Circle2D, LineStart:Vector2D, LineEnd:Vector2D )
'In progress
EndFunction
'-----------------------------------------------------------------
''''Collision Handling
'Calculated the distance from a point to a line
Function MinDistPointLine!(px!,py!,x1!,y1!,x2!,y2!) ''This function found in Blitz's forum Code Archive
If x1 = x2 And y1 = y2 Then Return PointToPointDist(px,py,x1,y1)
Local sx! = x2-x1
Local sy! = y2-y1
Local q! = ((px-x1) * (x2-x1) + (py - y1) * (y2-y1)) / (sx*sx + sy*sy)
If q < 0.0 Then q = 0.0
If q > 1.0 Then q = 1.0
Return PointToPointDist(px,py,(1-q)*x1+q*x2,(1-q)*y1 + q*y2)
End Function
'-----------------------------------------------------------------
Function pointToPointDist!(x1! , y1! , x2! , y2!)
Return Sqr( (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1) )
End Function
Function VectorToLine:Vector2D(px!,py!,x1!,y1!,x2!,y2!)
If x1 = x2 And y1 = y2 Then Return Vector2D.Create( x1-px, y1-py )
Local sx! = x2-x1
Local sy! = y2-y1
If sx = 0 And sy = 0 Then Return
Local q! = ((px-x1) * (x2-x1) + (py - y1) * (y2-y1)) / (sx*sx + sy*sy)
If q < 0.0 Then q = 0.0
If q > 1.0 Then q = 1.0
Local Xx! = (1-q)*x1 + q*x2
Local Xy! = (1-q)*y1 + q*y2
Return Vector2D.Create(Xx - Px, Xy - Py )
End Function
Rem
Friction! from 0 to 1 ; 1 = Total Friction (get stuck), 0 = No Friction
Elasticy! from 0 to 1 ; 1 = Perfect Bounce, 0 = No Bounce
USE:
If CollideSurface( SurfaceNormal,....)
ApplyResponse( Tank.Velocity, SurfaceNormal, 0, 0.5 )
Endif
EndRem
Function ApplyResponse( Velocity:Vector2D Var, SurfaceNormal:Vector2D, Friction!, Elasticity! )
SurfaceNormal.Normalize()
Velocity.Mirror( SurfaceNormal )
If Elasticity < 0 Then Elasticity = 0'Slide
If Elasticity > 1 Then Elasticity = 1'Perfect Bounce
Local Bounce:Vector2D = CreateVector(0,0)
Bounce.ProjectionOf( Velocity, SurfaceNormal )
Bounce.Multiply( Elasticity ) ' Apply Elasticy, to the perpendicular part of velocity
If Friction < 0 Then Friction = 0
If Friction > 1 Then Friction = 1
Friction = 1 - Friction'' Case 1, now: 0, Case 0, now: 1
Local Slide:Vector2D = CreateVector()
SurfaceNormal.MakeLeftNormal()'Convert the normal to the surface!
Slide.ProjectionOf( Velocity, SurfaceNormal )' Project to surface
Slide.Multiply( Friction ) ' Apply Friction, to the parallel part of velocity
Velocity.Set(0,0)
Velocity.Add( Slide )
Velocity.Add( Bounce )
'FOR DEBUGGING ONLY
' SetColor 0,0,255'GREEN
' Slide.Draw ( Ball.Position )
' SetColor 255,255,0'YELLOW
' Bounce.Draw ( Ball.Position )
EndFunction