Help with Physics: Momentum!

BlitzMax Forums/BlitzMax Programming/Help with Physics: Momentum!

Tibit(Posted 2005) [#1]
It is so close, but it just won't work (that last bit). Something is wrong with the reflection. Because somehow I need to apply it to both of the object who collide, but when I do they act crazy. This shouldn't be that hard to solve so I ask anyone, please help me!


I pasted all code into one file, to run this just copy and paste.



Tibit(Posted 2005) [#2]
Can anyone try it?


Diablo(Posted 2005) [#3]
run this vesion and you can REALLY see the problem. And it doesn't look good:

I'll see what I can do for ya

EDIT_____________________________________________________
Not that far now - they just dont move in the right direction tho:


EDIT:________________________________________________
It wont let me have another code box :(


Diablo(Posted 2005) [#4]
Try this then wave - Its a bit rough around the edges but it kida works:



Tibit(Posted 2005) [#5]
When I run it the bounces are reversed, it doesn't seem to work. I tried to tweak it some more. I think there is a problem in that each ball is checked against each other, but when a collision occur both ball's velocities is altered, instead of just one of them. And the amount we change velocity with need to be based on the mass of both objects and on the elasticity of the objects.

Or perhaps the best solution would be to separate the two cases. No bounce vs Perfect Bounce. Anyhow I still can't get it to work..


Diablo(Posted 2005) [#6]
try playing with this version. I made the collision into a method and update in drawall. I think i added a collision field but you can get rid of that:



EDIT: as i said I have no Idea about physics but i'm just trying to get it to a point when it looks right. and also keeping it at the top till someone else with a better idear of what todo repliys :D


Tibit(Posted 2005) [#7]
Thanks, yet the collisions are chaotic ;)

I think my collision idea is flawed. I need to do it another way, though the momentum is easy in theory, so I don't understand why it should be so hard to code.

I'll try some more. I think this problem can be solved, hm..


Tibit(Posted 2005) [#8]
And if you didn't know:

Momentum
Momentum is a measurement of an objects ability to resist change in velocity. The greater the speed and the larger the mass, the greater will the object’s momentum be. Momentum is a vector quantity and always has the same direction as the objects velocity vector.

There will be times where objects of different mass and different speeds collide. Some times you might even have an object that increases or decreases its mass. That could for example be a helicopter landing on a train, where as the trains mass gets a little bigger, and therefore the train’s velocity will decreases slightly.

Momentum = Velocity*Mass

If a collision involving two objects the total momentum all conserved! So the total momentum before and after collision is always the same.

Example:
Our bounce balls, each have different masses and velocities. When a big ball collide with a smaller one, and they both have the same speed, the larger ball will not change it's velocity very much, while the small ball will bounce away with a larger speed.

Example2:
Think about a pool table, if you fire a ball against a not moving ball, the moving ball will transfer its momentum to the stationary ball and that ball will fly off with the same speed the first ball had before collision. Also consider that at the moment of collision we have some energy loss (friction) so in the real world the second ball would have a slightly slower velocity than the first. This is what I call friction in my ApplyResponse( Velocity:Vector2D Var, SurfaceNormal:Vector2D, Friction!, Elasticity! ) method.


Tibit(Posted 2005) [#9]
Still not solved..


Diablo(Posted 2005) [#10]
I think this is the last time I try this :D. The balls don't stick together too much any more and momentum is kida accounted for now. However somtimes the larger balls get effect a bit to much by the smaller ones. Also acounts for friction between the balls now:


I mate of mine was vgood at physics at school (A* at a level) and hes also good at coding, I'll see if I can get him to help - He is extreamly lazy tho :D


Tibit(Posted 2005) [#11]
Thanks, I really appriciate your effort, however when the balls collide they sometimes switch direction and bounce away in a reversed direction. Also I don't think the momentum works.

On the other hand, I think the solution is very easy. If someone knows how to apply momentum. Because without momentum the collisions are perfect.
In the collide method, rem everything except the loop and this:
If Reflection <> Null Then
ApplyResponse( _otherBall.Velocity, Reflection, 0.2, 1.998 )
Endif

Momentum and speed needs to be applied on both colliding objects. But not 50-50.. I don't know..

I mate of mine was vgood at physics at school (A* at a level) and hes also good at coding, I'll see if I can get him to help - He is extreamly lazy tho :D
I will wish for the best :)


Will(Posted 2005) [#12]
Here is how to do this, afaik (haven't done it before, just looked it up online)

You need to know the line between the balls centers, lets call it the Line of Sight (LOS)

Each ball has a different velocity and mass, and so a different momentum. Ignore the x and y components and instead calculate the magnitude of the momentum vectors, and then resolve that relative to the line of sight - so that for each ball you have the momentum parallel to the LOS, and the momentum perpendicular to the LOS. Then do 1D collision involving the LOS.

You then solve a system of equations, the conservation of LOS parallel momentum equation and a LOS parallel kinetic energy equation to find the LOS parallel new velocities. Perpendicular to the LOS, no change will have been made. This is hard to understand as I have written it, here is the page that I am using as a reference:

http://www.mcasco.com/p1lmc.html


Tibit(Posted 2005) [#13]
Will! Fantastic! Just what I needed. I have written down the formulas and the theory, tomorrow I'll test if it works.

What I'm going to do is project both objects velocities on the reflecting vector and then apply the change in velocity acording to the equation give on that page.

Ignore the x and y components and instead calculate the magnitude of the momentum vectors
That is a paradox, because the vector consists of x and y values, and if I ignore them I can't calculate the magnitude. Na, just kidding, I know what you mean.

Thanks again! I think this solves it!


Will(Posted 2005) [#14]
Great! Post your code again when it works plz - BTW: is it ok to copy your code?


Tibit(Posted 2005) [#15]
It works, but something is still worng. I don't know what. At least this should be sufficient, but where does the extra energy come from, and elasticity doesn't work.


Global Gravity:Vector2D = CreateVector( 0, 0.05 )

Type TBall

	Global list:TList = New TList

	Field Color
	Field Position:Vector2D
	Field Velocity:Vector2D = CreateVector()
	Field Circle:Circle2D
	Field LastCollide:TBall '
	
	Method New()
		List.Addlast( Self )
		color = Rand(1,5)
	EndMethod

	Function Create:TBall( Circle:Circle2D )
		Local Ball:TBall = New TBall
		Ball.Circle = Circle
		Ball.Position = Circle.Position
		Return Ball
	EndFunction
	
	Method Draw()
		Circle.Draw()
	EndMethod
	Method SetBallColor()
		Select Color
			Case 1
				SetColor 255,0,0
			Case 2
				SetColor 0,255,0
			Case 3
				SetColor 0,0,255
			Case 4
				SetColor 0,255,255
			Case 5
				SetColor 255,255,0								
		EndSelect
	EndMethod
	
	Function DrawAll()
		For Local Ball:TBall = EachIn List
			Ball.SetBallColor()
			Ball.Draw()
			Ball.Velocity.Add( Gravity )
			Ball.Position.Add( Ball.Velocity )
			
			If Ball.Position.Y > GraphicsHeight() And Ball.Velocity.Y > 0 Then Ball.Velocity.Y:*-1
			If Ball.Position.X < 0 And Ball.Velocity.X < 0 Then Ball.Velocity.X:*-1
			If Ball.Position.X > GraphicsWidth() And Ball.Velocity.X > 0 Then Ball.Velocity.X:*-1						
			
		Next
	EndFunction

	Function Collision()
		For Local BallA:TBall = EachIn List
			For Local BallB:TBall = EachIn List
				If BallA <> BallB
				
					Local Reflection:Vector2D = BallA.Circle.CollideCircleReflect( BallB.Circle )
					'If BallA and BallB does not collide Reflection = null
					'If they do collide then Reflection is a vector From BallA to BallB
					'The Length of Reflection is the amount BallA has passed into/over BallB
					
					If Reflection
											
						' A Dynamic object against another Dynamic object
						DrawText "COLLISION DETECTED!!! ",150,150
									
						'Get us out of collision (Hopefully)
						BallA.Position.Subtract( Reflection )				
																																	
						'Add Elasticy
						'ApplyResponse( BallA.Velocity, Reflection, 0.0, 0.5 )'Bounce or Slide	
						'ApplyResponse( BallB.Velocity, Reflection, 0.0, 0.5 )'Bounce or Slide
						' With the setting 0,1 the above should do Nothin'		
														
																																	
						' Initial Velocity
						Local iVelocityA:Vector2D = CreateProjection( BallA.Velocity, Reflection )
						Local iVelocityB:Vector2D = CreateProjection( BallB.Velocity, Reflection )
						
				'		SetColor 255,255,255
				'		DrawText "iVel Vector A ",20,50 
				'		iVelocityA.DrawModify( BallA.Position, 20 ,0)
				'		Flip
				'		WaitKey()
				'		SetColor 255,55,255
				'		DrawText "iVel Vector B ",20,50 
				'		iVelocityB.DrawModify( BallB.Position, 20 ,0)
				'		Flip
				'		WaitKey()
												
						' Make it a one dimentional problem, simpler N easier to solve
						Local InitialA! = iVelocityA.Magnitude() 
						Local InitialB! = iVelocityB.Magnitude()
						
				'		Print "InitialA : "+InitialA
				'		Print "InitialB : "+InitialB
												
						Local MassA! = BallA.Circle.Radius*0.01
						Local MassB! = BallB.Circle.Radius*0.01
						
						If MassA = 0 And MassB = 0 Then Exit'Exit Current loop
						
						' The Velocity we seek; the Velocity after the collision
						Local AfterVelocityA!,AfterVelocityB!
						
						' This is carfully calculated math
						' It is the momentum equation combined with the energy equations
						' No Energy is lost. *cough*
						AfterVelocityA! = ( InitialA*(MassA - MassB)/(MassA + MassB) ) + ( InitialB*(2*MassB) / (MassA + MassB) )
						AfterVelocityB! = ( InitialA*(2*MassA)/(MassA + MassB) ) + ( InitialB*( MassB - MassA ) / (MassB + MassA) )						
			
				'		Print "AfterVelocityA : "+AfterVelocityA 'Should be B's inital if both have same Mass
				'		Print "AfterVelocityB : "+AfterVelocityB 'Should be A's inital if both have same Mass
							
						' Now we create the Vector which represents the change in Velocity
						Local VelChangeB:Vector2D = Vector2D.CreateField( AfterVelocityB, Reflection.Angle() )
						Reflection.Reverse()' Now Reflection is Vector From B to A (Reversed)
						Local VelChangeA:Vector2D = Vector2D.CreateField( AfterVelocityA, Reflection.Angle() )
						
				'		Print "ChangeVelocityA : "+VelChangeA.Length()
				'		Print "ChangeVelocityB : "+VelChangeB.Length()
						
						' Add change in Velocity to Current Velocity
						BallA.Velocity.Add( VelChangeA )	
						BallB.Velocity.Add( VelChangeB )	
				
					EndIf							
					
				EndIf					
			Next	
		Next
	EndFunction

EndType


Local A:TBall = TBall.Create( Circle2D.Create( 20 , 90, 100 ) )
Local B:TBall = TBall.Create( Circle2D.Create( 300, 70, 10 ) )

A.Velocity.Set(  2 , 0 )
B.Velocity.Set(  0 , 0 )

Graphics 640 , 480 , 0

While Not KeyDown(Key_Escape)
DrawText "Use the Mouse, Left-Click to Create Balls",10,10

	If MouseHit(1) TBall.Create( Circle2D.Create( MouseX(), MouseY(), Rand(2,20)  ) )

	TBall.DrawAll()
	TBall.Collision()	
								
	Flip;Cls
Wend'REST of THIS FILE IS VECTOR2D.bmx and CIRCLE2D.bmx





Rem
	File: "Vector2D.bmx"

	2D Vector Module
	The Vector Module which is a part of the Public MaxPhysics PROJECT
	
	VERSION HISTORY:
	
		ADDITIONS:
			Added Mirror Method!
			Added Reflection and Projection methods!	
			Added some more function commands (these should be in a aseparate file..)
			Added a DrawPoint Function
			Added methods for converting and creating perpendicular vectors (normals)
			'    \__ Commands see: CreateLeftNormal()
			
			Added a method: Plus( value!) - increases a vectors leangth with a scalar 
					
		FIXES:
		    Fixed: CreateField, it was using ints and not doubles - choppy movement as result
			Fixed: Now using the real cartesian coordinate system
			Fixed: Replaced floats with doubles.
		
		TO DO:
			Add methods and functions from the PollyCode Vector
			Each method should have a equivalent function
			only 3-4 are done.
EndRem




' /  /  /  /  /  /  /  /  /  /  /  /  /  /  /  /

'		T V E C T O R

'------------------------------------------------------------------------
Type Vector2D

	Field X!,Y!
			
	'===============
	' BASIC COMMANDS
	'===============
	
	'		 C R E A T E  V E C T O R
	'-----------------------------------------------
	Function Create:Vector2D( X!, Y! )
	
		Local Vector:Vector2D
		Vector = New Vector2D
		
		Vector.X!  = X!
		Vector.Y!  = Y!
		Return Vector 
		
	End Function
	
	'		C R E A T E   V E C T O R   F R O M
	'----------------------------------------------
	Function CreateFrom:Vector2D( Position1:Vector2D , Position2:Vector2D )
	
		Local Vector:Vector2D = Create(0,0)
		Vector.VectorFrom( Position1, Position2 )
		Return Vector
		
	EndFunction
	
	'		C R E A T E   /w  D I E C T I O N
	'----------------------------------------------	
	' I don't know any good name for this method
	Function CreateField:Vector2D( Length! , Direction! )

		Local Vector:Vector2D = Create(1,0)
		Vector.SetLength( Length )
		Vector.SetDirection( Direction )		
		Return Vector
				
	EndFunction
	
	'		 C O P Y   V E C T O R
	'----------------------------------------------
	Method Copy:Vector2D()'

		Return Create( X , Y )
		
	End Method

	'		 S E T  V E C T O R
	'----------------------------------------------
	Method Set( newX! , newY! )'
		X! = newX!
		Y! = newY!
	End Method

	'		 S E T  D I R E C T I O N
	'----------------------------------------------
	Method SetDirection( Angle! )'
		Local Length!  = Length()
		X = Cos( Angle! )*Length
		Y = -Sin( Angle! )*Length		    
	End Method
	Method SetDir( Angle! )
		SetDirection( Angle )
	EndMethod

	'		 S E T  L E N G T H
	'----------------------------------------------	
	Method SetLength( Length! )
		'If we want to set vector to zero 
		If Length = 0 Set(0,0);Return

		'If the new length is negative assume we want to
		If Length < 0 Turn180() 'Reverse

		Local Angle! = Angle()'Of this Vector
		X =  Cos(Angle) * Length
		Y = -Sin(Angle) * Length			
					
	EndMethod
	Method SetMagnitude( Length! )
		SetLength( Length )
	EndMethod


	'		G E T   L E N G T H
	'----------------------------------------------
	Method Length!()
		Return Sqr( X*X + Y*Y )'
	EndMethod
	'Alternative Names - Use whatever you like
	Method Magnitude!()    Return Length() EndMethod
	Method GetLength!()    Return Length() EndMethod
	Method GetMagnitude!() Return Length() EndMethod
		
	'		G E T   L E N G T H   S Q U A R E D
	'----------------------------------------------	
	Method LengthSquared()
		Return ( X*X + Y*Y )'
	EndMethod	
		

	'		G E T  D I R E C T I O N
	'----------------------------------------------
	Method Direction!()
		Return ATan2(-y , x)
	End Method
	'Also Alternative Names - Use whatever you like	
	Method GetDirection!() Return Direction() EndMethod
	Method Dir!()          Return Direction() EndMethod	
	Method GetAngle!()     Return Direction() EndMethod
	Method Angle!()        Return Direction() EndMethod
	'And alternative to get 0<= Angle <360
	Method Dir360!()
		Local Angle! = Direction!()
		If Angle < 0 Then Angle:+360
		Return Angle
	End Method

	'		G E T  A N G L E   B E T W E E N
	'----------------------------------------------
	Method AngleBetween( Vector:Vector2D )	
		Local DT! = Self.Dot( Vector )
		Local DB! = Length()*Vector.Length()
		If DB = 0 Return
		Return ACos( DT / DB )
	EndMethod
	'	 C R E A T E   L E F T   N O R M A L
	'----------------------------------------------	
	' This is a a Perpendicular Vector!
	'As if you would rotate it 90 degrees 
	Method CreateLeftNormal:Vector2D( )
		Return Create( Y, -X )
	EndMethod

		
	'	 C R E A T E   R I G H T   N O R M A L
	'----------------------------------------------	
	' This is a a Perpendicular Vector!
	Method CreateRightNormal:Vector2D( )
		Return Create( -Y, X )
	EndMethod
	
	
	'	 M A K E   L E F T   N O R M A L
	'----------------------------------------------	
	Method MakeLeftNormal( )
		Return Set( Y, -X )
	EndMethod

		
	'	 M A K E   R I G H T   N O R M A L
	'----------------------------------------------	
	Method MakeRightNormal()
		Return Set( -Y, X )
	EndMethod
	
	' M A K E   L E F T   N O R M A L   F R O M
	'----------------------------------------------	
	Method MakeLeftNormalFrom( Vector:Vector2D )
		Return Set( Vector.Y, -Vector.X )
	EndMethod

		
	' M A K E   R I G H T   N O R M A L   F R O M
	'----------------------------------------------	
	Method MakeRightNormalFrom( Vector:Vector2D )
		Return Set( -Vector.Y, Vector.X )
	EndMethod	
	
	'		R E V E R S E    V E C T O R 
	'----------------------------------------------
	Method Reverse() 'or Turn 180 Degrees
		X = -X
		Y = -Y
	End Method
	Method Turn180()
		Reverse()
	EndMethod
	
	
	'		V E C T O R   F R O M
	'----------------------------------------------
	Method VectorFrom( Position1:Vector2D , Position2:Vector2D)
		X = ( Position2.X - Position1.X ) 	
		Y = ( Position2.Y - Position1.Y )
		'Change the vector into a vector from Position1 to Position2		
	EndMethod

		



	'===============
	' MATH COMMANDS
	'===============

	'		A D D
	'----------------------------------------------	
	Method Add( Vector:Vector2D ) 
		X:+ Vector.X 
		Y:+ Vector.Y 
	EndMethod

		
	'		A D D  C O P Y
	'----------------------------------------------	
	' Add two Vectors and return the result as a 
	' third vector.
	Method AddCopy:Vector2D( Vector:Vector2D ) 
		Local NewVector:Vector2D
		NewVector = Self.Copy()
		NewVector.Add( Vector ) 
		Return NewVector 
	EndMethod
	
	'		I N C R E A S E
	'----------------------------------------------	
	Method Increase( Value! )'Add a value to the vectors length
		Local Angle# = GetAngle()
		X:+ Cos( Angle ) * Value
		Y:- Sin( Angle ) * Value
	End Method
	Method Plus( Value! )
		Increase( Value )
	EndMethod
	
	'		P R O J E C T I O N
	'----------------------------------------------
	'	
	' Returns: Self vector projected on the Input Vector
	'
	Method ProjectOn( Vector:Vector2D )
	'Self = A
	'Vector = B
		Local DotAB! = Dot( Vector)'A*B
		Local DotBB! = Vector.Dot( Vector)'B*B
		
		X = ( DotAB / DotBB )*Vector.X 'Ab.x = ( A*B / B*B ) B.x
		Y = ( DotAB / DotBB )*Vector.Y 'Ab = A projected on B
	EndMethod

	Method ProjectionOf( VectorA:Vector2D, VectorB:Vector2D )
		X = VectorA.X 'Copy
		Y = VectorA.Y
		Self.ProjectOn( VectorB )
	EndMethod
	
	Function CreateProjection:Vector2D( VectorA:Vector2D, VectorB:Vector2D )
		Local ProjectVector:Vector2D = VectorA.Copy()
		ProjectVector.ProjectOn( VectorB )
		Return ProjectVector
	EndFunction
		
	
	 
	'  R E F L E C T I O N   - AGAINST SURFACE
	'----------------------------------------------------------
	' 
	' Mainly used for Velocity vectors that collide against surfaces 
	' Self = Incoming Vector to be reflected (or vector you want to reflect at surface)
	' Surface = Surface normal ( any vector perpendicular to the surface )
	' 
	' This would be the same as reversing and then mirroring the vector in the
	' surface normal!	
	Method Reflect:Vector2D( SurfaceNormal:Vector2D )
		Local Reflect:Vector2D = Create(0,0)
		SurfaceNormal.Normalize()'Make its length = 1
		Reflect.Mirror( SurfaceNormal )
		Return Reflect
	EndMethod
	
	' M I R R O R
	'Surface must be a unit vector!
	Method Mirror( Normal:Vector2D )
		Local Dotprod# = -X * Normal.X - Y * Normal.Y
		X=X+2 * Normal.X * dotprod
		Y=Y+2 * Normal.Y * dotprod
	
	
'		Self.Reverse()
'		Local Angle! = AngleBetween( Surface )
'		Self.SetDirection( Angle*2 )

		'X = Surface.X* Surface.DOT( Self ) - X
		'Y = Surface.Y* Surface.DOT( Self ) - Y		
	EndMethod
	

		'		R O T A T E 
	'----------------------------------------------	
	Method Rotate( Angle! )
		Local CurrentAngle! = Direction()
		Local Length! = Length()
		
		X =  Cos( CurrentAngle + Angle ) * Length
		Y = -Sin( CurrentAngle + Angle ) * Length
	EndMethod
	Method AddAngle( Angle! ) 
		Rotate( Angle )
	EndMethod
		

			
	'		S U B T R A C T
	'----------------------------------------------		
	Method Subtract( Vector:Vector2D )
		X:- Vector.X 
		Y:- Vector.Y
		
		'This would also work
		'Self.Add( Vector.Copy().Reverse() )
	EndMethod	
		
	'		 D O T  P R O D U C T 
	'----------------------------------------------
	Method DOT!( Vector:Vector2D )
		Return ( X * Vector.X + Y * Vector.Y)
	EndMethod
	'Alternative Name
	Method DotProduct!( Vector:Vector2D )
		Return Self.DOT( Vector )
	EndMethod	
	
	'		M U L T I P L Y   V E C T O R 
	'----------------------------------------------
	Method Multiply( Value! )
		X:*Value
		Y:*Value	
	EndMethod
	
	
	'		N O R M A L I Z E 
	'----------------------------------------------	
	Method Normalize()
		Local Length! = Length()
		If Length = 0 Return'Don't divide by zero
		Set( (X / Length), ( Y / Length)  ) 'Make length = 1
	End Method	
		
	'		 U N I T   V E C T O R 
	'----------------------------------------------
	Method Unit:Vector2D()
		Local Vector:Vector2D
		Vector = Self.Copy()
		Vector.Normalize()		
		Return Vector'Returns a New vector with length = 1
	End Method

	'  		D I S T A N C E
	'----------------------------------------------	
	'The Distance between the end points of two vectors
	Method DistanceTo!( Other:Vector2D )
		Local dx! = Other.X - X 
		Local dy! = Other.Y - Y 
		Return Sqr( dx*dx + dy*dy ) 	
	EndMethod
	

	'Calculates the perpendicular distance from a point to a line (or vector)
	'If the vector returned is smaller than the radius of your round object (circle)
	'then you have collided and if you then add this vector to your position you
	'will move out of collision, then you are free to change velocity: (bounce or slide)
	Method ToLine:Vector2D( LineStart:Vector2D, LineEnd:Vector2D )
		Return PointToLineVector( X, Y, LineStart.X, LineStart.Y, LineEnd.X, LineEnd.Y )
	EndMethod
	
	Function PointToLineVector: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

	
	
	
	
	'===============
	' DEBUG COMMANDS
	'===============
	
	'	 	D R A W   V E C T O R 
	'--------------------------------------------------
	Method DrawModify( From:Vector2D , Multiply! , Xtra )
	
		'DrawLine From.X + Xtra, From.Y, From.X + Xtra + X* Multiply , From.Y + Y* Multiply 
		DrawArrow From.X + Xtra, From.Y, From.X + Xtra + X* Multiply , From.Y + Y* Multiply
		
	EndMethod
	Method DrawXY( FromX, FromY, Multiply! , Xtra )
		DrawModify( Point(FromX, FromY) , Multiply! , Xtra )
	End Method	
	
	'	 	D R A W   R E A L   V E C T O R 
	'--------------------------------------------------
	Method Draw( Origin:Vector2D =Null )
		If Origin = Null Origin = Create( 0, 0 )
		DrawModify( Origin , 1 , 0 )		
	EndMethod

	'		 D R A W   V E C T O R    D A T A
	'-----------------------------------------------
	Method DrawData( sLen, sDir, X, Y )
		Local Row = 0
		If sLen DrawText "Length : "+Length(),X,Y	+Row*15; Row:+1
		If sDir DrawText "Dir : "   +Dir360(),X,Y	+Row*15; Row:+1
	End Method

	Function DrawArrow(x1%, y1%, x2%, y2%, _arrowHeadLength% = 10, _arrowHeadWidth% = 5)
		Local dx = x1 - x2
		Local dy = y1 - y2
		If Sqr( dX*dX + dY*dY ) = 0 Then Return 
		
		DrawLine x1, y1, x2, y2
		
		Local lineAngle% = ATan2( dx , dy )
		
		lineAngle:+ 180
		DrawLine x2, y2, (x2 + (Sin(lineAngle * -1) * _arrowHeadLength%)) + (Cos(lineAngle) * _arrowHeadWidth%), (y2 - (Cos(lineAngle * -1) * _arrowHeadLength%)) - (Sin(lineAngle) * _arrowHeadWidth%)
		DrawLine x2, y2, (x2 + (Sin(lineAngle * -1) * _arrowHeadLength%)) - (Cos(lineAngle) * _arrowHeadWidth%), (y2 - (Cos(lineAngle * -1) * _arrowHeadLength%)) + (Sin(lineAngle) * _arrowHeadWidth%)
		
	End Function

	
EndType	' /  /  /  /  /  /  /  /  /  /  /  /  /  /  /  /
'------------------------------------------------------------------------







' 			C R E A T E  V E C T O R
'-----------------------------------------------
'Purpose: Creates a New Vector 			
'Parameters: X = Vectors X value ' Same For Y	
'Returns: New Vector Type						
'-----------------------------------------------
Function CreateVector:Vector2D( X!=0, Y!=0 )
	Return Vector2D.Create( X, Y )
EndFunction




'		 C O P Y   V E C T O R
'----------------------------------------------
'Purpose: Copies a Vector into a New vector	
'Parameters: VECTOR
'Returns: a VECTOR, exact copy of first VECTOR
'-----------------------------------------------	
Function CopyVector:Vector2D( Vector:Vector2D )
	Return Vector.Copy()
EndFunction	
	
		
'		 V E C T O R   D I R E C T I O N
'----------------------------------------------------
'Purpose: Calculates the direction of a vector		
'Parameters: VECTOR
'Returns: Degrees
'Note on Angel: 0 is Left, 90 is down (BlitzStyle)
'Note LastDir: If Length = 0 this Function returns LastDir
'---------------------------------------------------------
Function VectorDirection!( Vector:Vector2D )
	If Vector = Null Return
	Return Vector.Direction()
EndFunction

'		 S E T  V E C T O R
'----------------------------------------------
Function SetVector( Vector:Vector2D,  X!=0, Y!=0 )
	If Vector = Null Return
	Vector.Set( X, Y )	
EndFunction		


'	 M A K E   L E F T   N O R M A L
'----------------------------------------------		
' Creates Vector that is perpendicular to the first
' Fast way to rotate it 90 degrees.
'	
Function CreateLeftNormal:Vector2D( Vector:Vector2D )
	Return Vector.CreateLeftNormal()
EndFunction	
	
	

'		P R O J E C T I O N
'----------------------------------------------
' Project A-Vector on the B-Vector and return the
' resulting Vector
Function CreateProjection:Vector2D( VectorA:Vector2D, VectorB:Vector2D )
	Return Vector2D.CreateProjection( VectorA, VectorB )
EndFunction
	
	'		 D O T  P R O D U C T 
'---------------------------------------------------
'Purpose: Calculated the Dot-Product of Two Vectors			
'Parameters: Two vectors you want to "Dot"
'Returns: The result   				
'---------------------------------------------------
Function Dot!(Vector:Vector2D,Vector2:Vector2D)
	If Vector = Null Return
	Return Vector.DOT( Vector2 )	
	
End Function
'Alternative Naming (Both these works the same)
Function DotProduct!(Vector:Vector2D,Vector2:Vector2D)
	If Vector = Null Return
	Return Vector.DOT( Vector2 )
End Function


'		N O R M A L I Z E 
'----------------------------------------------	
'Purpose: Sets Vector length To ONE but keeps 
' it's direction		
'Parameters: VECTOR to normalize
'-----------------------------------------------
Function NormalizeVector( Vector:Vector2D )
	If Vector = Null Return
	Vector.Normalize()
EndFunction


'		R O T A T E 
'----------------------------------------------	
' Rotates the Vector by this much. 
' Possitive numbers for clockwise movement
' Negative for Anit-Clockwise =)
' 
'Note: Don't confuse this command with SetVectorDirection()
Function RotateVector( Vector:Vector2D, Angle! )
	If Vector = Null Return
	Vector.Rotate( Angle! )
EndFunction

'		 U N I T   V E C T O R 
'----------------------------------------------
'Note: This is same as Normalizing a vector
' except that this function does not alter the
' original vector. Instead it return a new vector
Function CreateUnitVector:Vector2D( Vector:Vector2D )
	If Vector
		Return Vector.Unit()
	EndIf
EndFunction



' 			D R A W  V E C T O R
'__________________________________________________
'Purpose: Draws the vector from the specifed point
'Parameters: X,Y location		
'--------------------------------------------------
Function DrawVector( Vector:Vector2D, From:Vector2D , Multiply!=1 , Xtra=0 )
	Vector.DrawModify( From , Multiply! , Xtra )
EndFunction




	
'		 D R A W   V E C T O R    D A T A
'-----------------------------------------------
'Purpose: Prints the data of a vector		
'Parameters: sLen=ShowLength, SDir=ShowDirection
' X and Y = Where to start draw the data (text)
'-----------------------------------------------
Function DrawVectorData( Vector:Vector2D, X=10, Y=20, sLen=True, sDir=False )
	Vector.DrawData( sLen, sDir, X, Y )
EndFunction
Function DrawVectorInfo( Vector:Vector2D, X=10, Y=20, sLen=True, sDir=False)
	Vector.DrawData( sLen, sDir, X, Y )
EndFunction


Rem
	If you ever need a function to check something of a point you can
	use the vector to check against (position vector for example)
	Ex drawline( Point(50,100), ShipPosition:Vector )
EndRem
Function Point:Vector2D( X! , Y! )
	Local Vector:Vector2D= New Vector2D
	Vector.X = X
	Vector.Y = Y
	Return Vector
EndFunction	

Function DrawPoint( Point:Vector2D, Radius)
	DrawOval Point.X-Radius, Point.Y-Radius, Radius*2, Radius*2' Center Point!
EndFunction

Function DrawLineToPointFromOrigin( Start:Vector2D, Origin:Vector2D )
	DrawLine Start.X, Start.Y, Start.X + Origin.X , Start.Y + Origin.Y 		
EndFunction


'Import "vector2D.bmx"
Type Shape2D Abstract

	Field Position:Vector2D = Point(0,0)'Center position!
	
	Method ShapesOverlap( Shape:Shape2D )
	EndMethod
	
	Method ShapesCollide:Vector2D( Shape:Shape2D )
		'A Shape Collides Against another Shape
	EndMethod
	
EndType


Type Circle2D Extends Shape2D

	Field Radius! = 1

	Function Create:Circle2D( X, Y, Radius! ) 
		Local Circle:Circle2D = New Circle2D
		Circle.Position.Set(X,Y)
		Circle.Radius = Radius
		Return Circle
	End Function
	
	'Circle vs another Shape
	'Returns the projected vector required to push us out of collision
	Method ShapesCollide:Vector2D( Shape:Shape2D )
		Select Shape
			Case Circle2D( Shape )
				Return CollideCircleReflect( Circle2D( Shape) )
			'Case Line2D( Shape )
			'	Return CollideLineReflect( Line2D( Shape ) )			
			'Case Polygon2D( Shape )
			'	Return CollidePolygonReflect( Polygon2D( Shape ) )						
		EndSelect
	EndMethod
	
	'Circle vs another Shape
	Method ShapesOverlap( Shape:Shape2D )
		Select Shape
			Case Circle2D( Shape )
				Return CollideCircle( Circle2D( Shape) )
			'Case Line2D( Shape )
			'	Return CollideLine( Line2D( Shape ) )			
			'Case Polygon2D( Shape )
			'	Return CollidePolygon( Polygon2D( Shape ) )						
		EndSelect
	EndMethod
	
	'Just check collision - Quick version
	Method CollideCircle( Circle:Circle2D)
		Local Distance! = Distance( Position, Circle.Position )	
		Local Amount! =  ( Radius + Circle.Radius ) - Distance
		If Amount > 0 Then Return Amount Else Return False
	EndMethod
	
	Method GetAngleToCircle!( Circle:Circle2D )
		Local Reflect:Vector2D = Vector2D.CreateFrom( Position, Circle.Position )
		Return Reflect.Dir360() 'Or Angle() - depends on the form you want
	EndMethod
	
	'------------------------------------------------------------------------
	'Check for collisions, if collision detecte it return a reflection vector 
	'The reflection vector has the same length and direction required to push
	'the circle out-of collision with the other circle
	'------------------------------------------------------------------------
	Method CollideCircleReflect:Vector2D( Circle:Circle2D )
	
		Local Magnitude! = CollideCircle( Circle )
		If Magnitude = False Then Return Null
		Local ReflectAngle = GetAngleToCircle!( Circle )
		Return Vector2D.CreateField( Magnitude!, ReflectAngle )
	
	EndMethod
	
	Rem UNDER CONTRUCTION
	Method CollideLineReflect:Vector2D( Circle:Circle2D )
		Local FromPointToLine:Vector2D = 
		
		See solution in File: "CircleTesting5.bmx"
		
		VectorToLine.Reverse()		
		Local Dist = VectorToLine.Length()		
		VectorToLine.Normalize()
		VectorToLine.Multiply( Ball.Radius - Dist )
		Ball.Position.Add( VectorToLine )	
	EndRem
	
	Method Draw()
		DrawOval Position.X - Radius, Position.Y - Radius, Radius*2, Radius*2
	EndMethod
					
EndType

Function Distance!( Position1:Vector2D, Position2:Vector2D )	
	Local DX! = Position2.X - Position1.X
	Local DY! = Position2.Y - Position1.Y
	Return Sqr(DX*DX + DY*DY)
EndFunction

Rem
Local CircleA:Circle2D = Circle2D.Create(100 , 100 , 100)
Local CircleB:Circle2D = Circle2D.Create(320 , 240 , 50)
Local CircleB_Mobile = False 'Can we move B?

Graphics 640 , 480 , 0

While Not KeyDown(Key_Escape)
DrawText "Move around, Press SPACE to make the RED circle MOBILE.",10,10

	SetColor 0 , 200 , 0 'Green
	CircleA.Draw	
	SetColor 200 , 0 , 0' Red
	CircleB.Draw
	
	If KeyHit( Key_Space )
		If CircleB_Mobile = True Then CircleB_Mobile = False Else CircleB_Mobile = True
	EndIf
	
	SetColor 0 , 0 , 255' Blue
	'Local OverlapDist = CircleA.CollideCircle( CircleB )
	'Local OverlapAng  = CircleA.GetAngleToCircle( CircleB )
	'If OverlapDist 
		'DrawText "COLLIDING!   by : "+OverlapDist+", Angle: "+OverlapAng ,50,50
		
		Local Reflection:Vector2D = CircleA.CollideCircleReflect( CircleB )
		If Reflection Reflection.Draw( CircleA.Position )
		
		If CircleB_Mobile = True
			CircleB.Position.Add( Reflection )
		EndIf
		
		ApplyResponse( BallVelocity, SurfaceNormal, 0.00, 0.2 )
		
	'EndIf
																								
																																																																	
	CircleA.Position.Set( MouseX(), MouseY() )
	Flip;Cls
Wend
EndRem



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



The code is open source, see the MaxPhysics Community Project Page. You can take it and do whatever you want with it, though I would appriciate, if you manage to improve this, that you share your advancements :)