2D Physics: Ideas for a Community Project

BlitzMax Forums/BlitzMax Programming/2D Physics: Ideas for a Community Project

The MaxPhysics Project

The vision is to create a solid expandable and flexible 2D physics module for Blitzmax, which will easily be expandable into a 3D version in the future. It is going to be public and open source. Anyone can add their improvements and suggest ideas and tips.

Here is a first topic to focus on the project plan and overall ideas about the project. Here I want everyone who is interested to discuss what they would want from the Physics Module. - Or perhaps we should split it up into more than one module?

--- Points to Decide upon ---

[ ] Find a Name for the Project. Key words: Physics, Vectors. Right now it's "MaxPhysics"

[ ] How is code management going to work? How can we avoid the problem that more than two may be working on the same part? I suggest one file for each type (not always though).

[ ] What about coding styles? Guidelines to make the code similar (as much as possible) for everyone in the project, includes how and where to add comments and formation of the code. - Right now you should try to follow my style in the vector library (see some post below), comments are welcome.

[ ] Referense List
Some about Collisions /f Visual Basic
Flipcode - Collison detection in 3D
N collision, Vector collision /w source in Flash
Hugo - Physics, Effects and Collisons
[a ] no link [/a]

TO DO:
[100%] Finnish the project plan and start the actual project in another topic

Here is my first overview of the project plan, I will update this according to suggestions.

Project Plan - MaxPhysics
[ ] Based upon a solid vector library
[ ] Types: Vectors,Lines,Polygons?,Rects,Cricles
[ ] Collision Checks (above types)
[ ] Collision Response (above types)
Requires we know the point of impact and the speed of impact. With that we could choose anything from perfect slide to perfect bounce, depending on settings.
[ ] Collision Response :Physics Object
When two "lose" objects collide, take momentum into account. These physics objects have a Mass,Position,Velocity,Acceleration. Any object in your game that you want to use with collisions can be derivied from this "physicsObject" and using one (or more?) of the collision types. For example:
Ship extends MaxPhysicsObject
New()
CollisionShape = new Circle( ShipSize )

Perhaps we can also include torque here so that rotation is affected by collisions to.

[ ] Examples and Documentation!
This is very important so that everyone can use this module with ease!

End Notes:
The Physics Library is supposed to be very simple to implement and use, while being as general purpose as possible.




--------- WORK DONE SO FAR ---------
The Second version of the new improved vector library is done. I haven't added anything with physics or collision or lines yet. Here is the start:

Thanks to Haramanai for conversion to real cartesian coordinates.

Anyone may add and improve to this. Make sure that you, in the comments at the top of the file, write what have changed and what adition you have done or bugs you have discovered, perhaps even fixed.
Strict
Rem
	File: "Vector2D.bmx"

	2D Vector Module
	The Vector Module which is a part of the Public MaxPhysics PROJECT
	
	VERSION HISTORY:
	
		ADDITIONS:
			Added a method: Plus( value!) - increases a vectors leangth with a scalar 
		
		FIXES:
			Fixed: Now using the real cartesian coordinate system
		
		TO DO:
			Each method should have a equivalent function
			only 3-4 are done.
EndRem


Type TShape Abstract 
EndType



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

'		T V E C T O R

'------------------------------------------------------------------------
Type Vector2D Extends TShape'

	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 GetLenght!()    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

	
	'		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  /w  D E L T A  T I M E
	'----------------------------------------------	
	Method AddDelta( Vector:Vector2D ) 
		Add( Vector )
		MultiplyDeltaTime()
	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
	
	'		A D D  N E W  /w  D E L T A  T I M E
	'----------------------------------------------	
	Method AddDeltaCopy:Vector2D( Vector:Vector2D ) 
		Local NewVector:Vector2D
		NewVector = AddCopy( Vector )
		NewVector.MultiplyDeltaTime()
		Return NewVector 
	EndMethod

	Method Plus( Value:Float )'Add a value to the vectors length
		Local Angle:Float = GetAngle()
		X:+ Cos( Angle ) * Value
		Y:- Sin( Angle ) * Value
	End Method
	
	'		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
	
	'		M U L T I P L Y   /w  Delta Time
	'----------------------------------------------	'
	Method MultiplyDeltaTime()
		Self.Multiply( Delta.Time() )
	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


	
	
	
	
	'===============
	' 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 
	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


	
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()
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 )
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)

	Return Vector.DOT( Vector2 )	
	
End Function
'Alternative Naming (Both these works the same)
Function DotProduct!(Vector:Vector2D,Vector2:Vector2D)

	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 Normalize()
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 Unit()
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!=20 , 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, sLen=True, sDir=False, X=10, Y=20 )
	Vector.DrawData( sLen, sDir, X, Y )
EndFunction
Function DrawVectorInfo( Vector:Vector2D, sLen=True, sDir=False, X=10, Y=20 )
	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 DrawLineToPointFromOrigin( Start:Vector2D, Origin:Vector2D )
	DrawLine Start.X, Start.Y, Start.X + Origin.X , Start.Y + Origin.Y 		
EndFunction




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

'		 D E L T A  T I M E

'------------------------------------------------------------------------
	Type Delta 
	'		
	'-----------------------------------------------------
	' This type is Fully global. Which means you'll always 
	' refere to it as Delta.Start() , Delta.Time(),
	' Delta.Update() 
	'
	' You shouldn't create instances of this type!
	' DeltaTime is same for all your objects!
	'
	Global DeltaTime!
	Global TimeDelay%
	
	'Run this once before your main loop
	'If you don't there will be a jump in deltatime
	Function Start()
		TimeDelay = MilliSecs()
	End Function
	
	'Everytime where you want to get the deltatime
	'call this: Delta.Time
	'You should multiply this to every place which 
	'adds to you position/speed/acceleration
	'
	' The basic rule is to add deltatime to all
	' things which gets added to every frame
	' Like Speed:+ 10*Delta.Time
	'
	' If you use the Vector Library simply use 
	' AddDelta() instead of Add()
	' And
	' AddDeltaNew() Instead of AddNew()
	
	Function Time!()
	
		Return DeltaTime!
	
	End Function
	
	'Put this once in your main loop
	'it calculates the current deltatime
	'depeding on your framerate or more exact
	'the time between each/the last frame.
	Function Update()
	'_____________________________________________________ 
	'Purpose: Calculates DeltaTime , put it in mainloop			
	'-----------------------------------------------------	
			DeltaTime = ( MilliSecs()- TimeDelay )*0.001
			TimeDelay  = MilliSecs()			
		
	EndFunction
		
End Type	' /  /  /  /  /  /  /  /  /  /  /  /  /  /  /  /
'----------------------------------------------------------------------------------------	


A simple demo with only very simple vector math. Don't look to much at the code, I was lazy when I did this, see this only as a first demo.

Tech Demo
' Have a ball that is affected by grafity and bounces against the sides of the screen
' Make the ball apply an acceleration towards your mouse
' Bigger the further away, but only if the ball is below the mouse!
Strict 

Type Vector
	Field X#,Y#
		
	Function Create:Vector( X#=0, Y#=0 )
		Local NewVector:Vector = New Vector
		NewVector.X = X
		NewVector.Y = Y
		Return NewVector
	EndFunction
	
	Method Add( OtherVector:Vector ) X:+ OtherVector.X ; Y:+ OtherVector.Y EndMethod
	
	Method Multiply( Value# ) X:*Value; Y:*Value	EndMethod

	Method Visulize( Start:Vector , Multiply# = 20 , Xtra = 0)
		DrawLine Start.X + Xtra, Start.Y, Start.X + Xtra + X* Multiply , Start.Y + Y* Multiply 
	EndMethod
	
'	Method Draw( Start:Vector )
'		DrawLine Start.X, Start.Y, Start.X + X , Start.Y + Y 		
'	EndMethod

	Method ReverseX() 	X = -X EndMethod
	
	Method ReverseY() 	Y = -Y EndMethod
	
	Method Set( X#=0, Y#=0) Self.X = X;Self.Y = Y	EndMethod

	Method Length#() 
		Return Sqr( X*X + Y*Y )'Pythagoras
	EndMethod
	
	Method VectorFrom( Position1:Vector , Position2:Vector)
		X = ( Position2.X - Position1.X ) 	
		Y = ( Position2.Y - Position1.Y )		
	EndMethod
	
	'Decrease a vector until it is zero
	Method Break( Amount# )
		If Amount = 0 Return'We don't brake..
		If Amount >= Length(); Self.Set(0,0) Return'No matter how much you brake you'll never go backwards
						
		Local Break:vector = Vector.Create( X / Length() , Y / Length() )
		Break.Multiply( -Amount# )
		Self.Add( Break )	
	EndMethod
End Type


Type TBounceBall

	Field TopLeft:Vector	'Not in use, I think
	Field Position:Vector 		
	Field Velocity:Vector 		'I hope these are self-explainatory
	Field Acceleration:Vector
	Field Force:Vector
	Field Mass#			
	Field Radius 'Size of ball
	
	Method New()
		TopLeft		= Vector.Create( 0 , 0)
		Position 		= Vector.Create( 50, 250)
		Velocity 		= Vector.Create( 0 , 0)
		Acceleration 	= Vector.Create()
		Force		= Vector.Create()
		Radius		= 30
		Mass 		= 1
	EndMethod
	
	Method Draw( )
		DrawOval( Position.X - Radius/2, Position.Y - Radius/2, Radius, Radius )
		'Draws a oval around the ball's position
		'If I wouldn't take X - radius/2 the oval would be draw from the middle.. Try it
	EndMethod
	
	Method Update()
		Force.Multiply( Float(1.0/Mass) )
		Acceleration.Add( Force )' a = F/m  ; F =  m*a ; m = F/a
		Velocity.Add( Acceleration )
		Position.Add( Velocity )		
									
		' D I S P L A Y    V E C T O R S	
		'-----------------------------------------------------					
		'Draw and magnify the vectors so we can see them		
		'_____________________________________________________
		SetColor 0,255,0
		DrawText "GREEN Vector is the Velocity Vector"+Velocity.Length(),10,80
		Velocity.Visulize( Position ,4 )
							
		SetColor 255,0,0
		DrawText "RED Line is the Acceleration Vector. Lenght: "+Acceleration.Length(),10,50
		Acceleration.Visulize( Position  ,50, -1)
		'_____________________________________________________
		
		SetColor 255,255,255
		
		Force.Set
		Acceleration.Set			
		'Velocity.Set
		
	EndMethod	
	
	Method CollideWalls()
		If Position.X < 0' And Velocity.X > 0'Left
			CollideVerticalWall( 0 )		
		Else If Position.X > GraphicsWidth()' And Velocity.X < 0'Right
			CollideVerticalWall( GraphicsWidth() )	
		Else If Position.Y < 0' And Velocity.Y > 0'Top
			CollideHorisontalWall( 0 )		
		Else If Position.Y > GraphicsHeight() 'And Velocity.Y < 0'Bottom
			CollideHorisontalWall( GraphicsHeight() )	
		EndIf		

	EndMethod
	
	Method CollideVerticalWall( WallX )
			Velocity.ReverseX()
			Velocity.Multiply(0.8)' Fotball bounce - 1 for super bounce, 0 for no bounce
			Acceleration.ReverseX()			
			Local DistanceIntoWall = (Position.X - WallX) 
			Position.X:- 2*DistanceIntoWall		
	EndMethod
	
	Method CollideHorisontalWall( WallY )
			Velocity.ReverseY()
			Velocity.Multiply(0.8)' Fotball bounce 0.5 - 1 for super bounce, 0 for no bounce
			Acceleration.ReverseY()			
			Position.Y:- 2*(Position.Y - WallY) ' (Position.Y - WallY) = DistanceIntoWall		
	EndMethod
	
EndType




Local Ball:TBounceBall = New TBounceBall
Local MousePosition:Vector = Vector.Create( MouseX(), MouseY() )
Local MouseForce:Vector    = Vector.Create()
Local GravityAcc:Vector    = Vector.Create( 0 , 0.2 ) 'Constant Acceleration Downwards

Local Gravity = False 'Activate with [ G ] key
Local Friction = False 'Toggle Friction [ F ] Key

Graphics 500,500,0 'Window debug Mode

While Not KeyDown(Key_Escape)
	
	MousePosition.Set MouseX() , MouseY()
	MouseForce.VectorFrom( Ball.Position, MousePosition )
	MouseForce.Multiply( 0.01 )'0.1%

	If KeyDown( Key_MouseLeft ) Ball.Force.Add( MouseForce )
	If KeyDown( Key_X ) Ball.Force.X = 2
	If KeyDown( Key_A ) Ball.Velocity.X = 2
	If KeyDown( Key_Z ) Ball.Acceleration.X = 2
	


	If KeyHit( Key_G )
		If Gravity = False Then Gravity = True Else Gravity = False
	EndIf
			
	If Gravity
		Ball.Acceleration.Add( GravityAcc )
		'We only have one object
		'In a normal case you would loop this for every object affected by gravity
		'NOTE: Gravity is an accleration; independant of Mass - it is not a force!
	EndIf
	
	If KeyHit( Key_F ) 	
		If Friction = False Then Friction= True Else Friction = False
	EndIf
	
	If Friction'Apply Friction unless SPACE is hold down
		Ball.Velocity.Break( 0.1 )'FRICTION
		'This is not very good air friction, but should work
		'good for pool balls or rolling minigolf balls.
	EndIf

	
	Ball.Draw		' Draw Ball
	
	SetColor 0,0,255
	DrawText "All BLUE Lines is Force Vectors",10,20
	SetColor 0,100,255
	MouseForce.Visulize( Ball.Position, 10 )		
	SetColor 25,25,155
	Ball.Force.Visulize( Ball.Position, 10 )	

	Ball.Update	' Update the balls velocity, acceleration and position
	Ball.CollideWalls

	DrawText "Press G to Toggle Gravity ON/OFF",10,150
	DrawText "Press F to Toggle Friction ON/OFF",10,180
	DrawText "Press LeftMouse to draw the ball toward the cursor",10,210
		
	DrawText "MEM: "+MemAlloced(),10,GraphicsHeight()-20
	
	Flip;Cls;FlushMem
Wend


May i draw your attention to this thread started a while ago, theres some intresting stuff located within!. Might be of use to this.

Good demo.:) Looks like you are a good organizer of thinks! I also liked your tutorials. currently I am creating something like that based on line segments. I will help if I can. Just tell me how I can be involved.

Looks good,

I was trying to make something like that but based on polygons for a game but I can’t work out collision responses with rotation (and heaps of other stuff)

It is poorly made (it is was only meant for me), but it might help?



Strict


' --------------------------------------------------------------------
' ---------------------------     Test    -------------------------------
' --------------------------------------------------------------------


Type Grounds
	Field Body:p2D_Body
	Global List:TList
	Field Link:TLink
	
	Method New()
		If List=Null Then List=CreateList()
		Link=ListAddLast(List,Self)
		
		Body=New p2D_Body
		
		Body._BodyType=2 'Static Body
		Body.InvMass#=0
		Body.CollisionType=Ground_Collision
		Body.AddShape( p2D_Shape.CreateConvex(Rnd(10,40), Rand(3,6) ) )
	End Method
	
	Method Draw()
		SetColor 255,0,0
		Body.Shapes[0].Draw(Body.Position.X#,Body.Position.Y#) 'Tmp only
	End Method
	

End Type

Type Blocks
	
	Field Body:p2D_Body
	
	Global List:TList
	Field Link:TLink
	Field MouseMove=False
	
	
	Method New()
		If List=Null Then List=CreateList()
		Link=ListAddLast(List,Self)
		
		Body=New p2D_Body
		
		Body._BodyType=1 'Rigid Body
		Body.InvMass#=1
		Body.AddShape( p2D_Shape.CreateConvex(Rnd(10,40), Rand(3,6) ) )
		Body.CollisionType=Block_Collision
		
	End Method
	
	Method Draw()
		SetColor 0, 255,0
		Body.Shapes[0].Draw(Body.Position.X#,Body.Position.Y#) 'Tmp only
	End Method
	
End Type


'Setup...

Graphics 640,480,0

p2D_Simulator.CreateSimulator(0,0.5)


Const Block_Collision=2

Const Ground_Collision=3

p2D_Simulator.SetCollisionResponse(Block_Collision, Ground_Collision, 1)
p2D_Simulator.SetCollisionResponse(Block_Collision, Block_Collision, 1)

'Create Blocks...


For Local n=0 To 40
		Local Block:Blocks=New Blocks
		Block.Body.Position.X#=Rnd(10,630)
		Block.Body.Position.Y#=Rnd(10,300)
		Block.Body.AngRotation#=Rand(0,360)
		
		If n=0 Then Block.MouseMove=True
		
Next


'Create Ground...

For Local n=0 To 30
	
	Local Ground:Grounds=New Grounds
	
	Ground.Body.Position.X#=Rnd(10,630)
	Ground.Body.Position.Y#=Rnd(200,450)
	
	Ground.Body.AngRotation#=Rand(0,360)
	
Next

'Main loop...


Local Delta_OldTime#=MilliSecs()

While Not KeyDown(KEY_ESCAPE)
	
	Cls
	
	
	
	Local Time#=MilliSecs()
	Local Speed#=(Time#-Delta_OldTime#)/30
	If (Time#-Delta_OldTime#)<10 Then Delay 10-(Time#-Delta_OldTime#)
	Delta_OldTime#=Time#
	If Speed#<0 Then Speed#=0
	If Speed#>5 Then Speed#=5
	
	
	
	p2D_Simulator.Advance(Speed#)
	
	For Local Block:Blocks = EachIn Blocks.List
		
		If KeyDown(KEY_LEFT)  Block.Body.AngRotation#:+Speed#
		If KeyDown(KEY_RIGHT)  Block.Body.AngRotation#:-Speed#
		
		If Block.MouseMove=True
			Block.Body.Position.X#=MouseX()
			Block.Body.Position.Y#=MouseY()
		End If
		
		Block.Draw()
		
	Next
	
	For Local Ground:Grounds = EachIn Grounds.List
		Ground.Draw()
	Next
	
	SetColor 255,255,255
	DrawText "Press Left and right | Move Mouse",20,20
	
	FlushMem()
	Flip
	
Wend






' --------------------------------------------------------------------
' -------------------------     Physics    ------------------------------
' --------------------------------------------------------------------

Rem
bbdoc: BlitzMax 2D Polygon based Rigid body Collision and Physics
about:
Baa Baa Baa
End Rem


Rem
Module Pub.PolygonPhysics'?
ModuleInfo "Version: 0.0"
ModuleInfo "Author: Luke Hoschke, and other people's code from blitz basic, and the web"
End Rem'


	
Rem
bbdoc: 2D Physics Engine
about:
#p2D_Simulator wrapper holds the main Functions for the Physics Engine<br>
You need to call CreateSimulator before calling anything else<br>
End Rem
Type p2D_Simulator
	
	Global _Created:Byte=False
	Global _BodyList:TList
	Global Gravity:p2D_Vector
	
	Rem
	bbdoc: Create the Simulater
	Returns: True if started
	about:
	Starts the Physics Engine, and sets the Gravity <br>
	<br>
	<b>Note:</b> No new type of p2D is ever made, it is only used as a namespace
	End Rem
	Function CreateSimulator(GravityX#=0,GravityY#=1)
		
		_BodyList=CreateList()
		_Collision_Response_List=New Byte[255*255]
		
		
		Gravity=New p2D_Vector
		Gravity.Set(GravityX#,GravityY#)
		
		
		
		
		
		
		_Created=True
		
		Return True
	End Function
	
	
	Rem
	bbdoc: Advances all bodys in the Physics Engine
	about:
	Advances all bodys by the timestep (GameSpeed) and responds to collions
	End Rem
	Function Advance(GameSpeed#=1)
		If _Created=False Then RuntimeError "Simulator not created"
		
		Local Body:p2D_Body
		
		
		For Body:p2D_Body = EachIn _BodyList
			For Local Shape:p2D_Shape=EachIn Body.Shapes
				Shape.Rotate(Body.AngRotation#)
			Next
		Next
		
		Local Found=0
		
		For Body:p2D_Body = EachIn _BodyList
			If Body._BodyType<>2 Then
			
			
			
			
			'A bad spot for check... Please Fix
			For Local OtherBody:p2D_Body = EachIn _BodyList
				If OtherBody<>Body Then
					
					If Body.Collide(OtherBody)=True Then
						
						
						
						
						
						'Body.Velocity.X#=-Body.Velocity.X#
						'Body.Velocity.Y#=-Body.Velocity.Y#
						
						'OtherBody.Velocity.X#=-OtherBody.Velocity.X#
						'OtherBody.Velocity.Y#=-OtherBody.Velocity.Y#
						
					End If
					
				End If
			Next
			
			
			'---Gravity---'
			
			
				
				Body.Velocity.Add(Gravity,GameSpeed#)
				
				
				
				
				
				
				
				Num_Lower(Body.AngVelocity#,0.1*GameSpeed#)
				
				Num_Lower(Body.Velocity.X,0.1*GameSpeed#)
				Num_Lower(Body.Velocity.Y,0.1*GameSpeed#)
				
				
				Body.Velocity.X#=Body.Velocity.X#*0.9^GameSpeed#'Fix
				Body.Velocity.Y#=Body.Velocity.Y#*0.9^GameSpeed#
			

			
			'---Move---'
			
				
				Body.Position.Add(Body.Velocity,GameSpeed#)
				
				Body.AngRotation#:+Body.AngVelocity#*GameSpeed#
				
				
				
				
				
			End If
		Next
		
	End Function
	
	Rem
	bbdoc: Frees the Simulator
	about:
	You might want to do this each level
	End Rem
	Function DestroySimulator()
		
		
		'Clear
		
		
		_Created=False
		
	End Function
	
	
	
	
	Global _Collision_Response_List:Byte[]
	
	Rem
	bbdoc: Set the Collision Response of a Type colliding with another type
	about:
		<i>
		source_type% = The collision ID For the source body <br>
		target_type% = The collision ID For the target body <br>
		Response% = The collision Response mode. <br>
			0 = No impulse Or feedback<br>
			1 = Impulse only <br>
			2 = Feedback only <br>
			3 = Impulse & Feedback <br>
		</i>
		
		<b>Description:</b>
		
		The collosion in one way if the target type does not <br>
		collide with the source type as well
		
		
	End Rem
	Function SetCollisionResponse(source_type%, target_type%, Response%)
		If _Created=False Then RuntimeError "Simulator not created"
		
		If source_type%>255 Or source_type%<0 Then RuntimeError "type must be 1-255"
		If target_type%>255 Or target_type%<0 Then RuntimeError "type must be 1-255"
		
		'_Collision_Response_List[source_type-1]=target_type
		
		_Collision_Response_List[ (source_type-1)*255+ (target_type-1) ]=1
		
		
		
	End Function
	
	Rem
	bbdoc: Resets all Responses
	End Rem
	Function ResetCollisionResponses()
		If _Created=False Then RuntimeError "Simulator not created"
		
		For Local target:Int = EachIn _Collision_Response_List
			target=0
		Next
		
	End Function
	
	
	Rem
	bbdoc: Collision Type Collides
	End Rem
	Function CollisionTypeCollides(source_type%, target_type%)
		Return _Collision_Response_List[ (source_type-1)*255+ (target_type-1) ]		
	End Function
	
	
	
	
	
	Method New() Final
		RuntimeError "p2D cannot be made"
	End Method
	
End Type

	


Rem
ClearCollisions



src_type - entity Type To be checked For collisions. 
dest_type - entity Type To be collided with. 

Method - collision detection method. 
1: ellipsoid-To-ellipsoid collisions 
2: ellipsoid-To-polygon collisions 
3: ellipsoid-To-box collisions 

response - what the source entity does when a collision occurs. 
1: stop 
2: slide1 - full sliding collision 
3: slide2 - prevent entities from sliding down slopes

End Rem



Rem
bbdoc: Physics Body
about:
The main type used for objects in to the physic engine
End Rem
Type p2D_Body
	
	Field Position:p2D_Vector=New p2D_Vector
	Field Velocity:p2D_Vector=New p2D_Vector
	
	Field AngRotation#	=0
	Field AngVelocity#	=0
	
	
	Rem
	bbdoc: 0: Unpickable (default), 1: Polygon
	End Rem
	Field PickMode:Byte=1'0
	
	
	Rem
	bbdoc: (0-255) A collision type value of 0 indicates that no collision checking will occur with that entity. 1-255 indicates that collision checking will occur
	End Rem
	Field CollisionType:Byte=0
	
	Rem
	bbdoc: None
	End Rem
	Field InvMass#		=1	'Inverse mass
	Rem
	bbdoc: None
	End Rem
	Field InvInertia#	=1	'Inverse Inertia, Mass for Rotations
	
	Rem
	bbdoc: None
	End Rem
	Field Friction#		=0.5	'{0-1}, 
	Rem
	bbdoc: None
	End Rem
	Field Elasticity		=0.5	'{0-1}, Bounce
	
	
	Field _Dead:Byte=False
	Field _Link:TLink
	Field _Size#=-1
	Field _BodyType:Byte=1 '{0-None, 1-Rigid Body, 2-Static Body
	
	Field _Active:Byte=True 
	Field _Active_Timer:Float=0
	
	Field CountCollisions
	Field CollisionBody[Max_Collisions]
	
	
	Field Shapes:p2D_Shape[]
	
	
	
	Method Kill()
		RemoveLink(_Link)
		_Dead=True
		
	End Method
	
	Method New()
		If p2D_Simulator._Created=False Then RuntimeError "Simulator not created"
		_Link=ListAddLast(p2D_Simulator._BodyList,Self)
		
		
	End Method
	
	Method Delete()
		
	End Method
	
	
	Rem
	bbdoc: AddShape
	about:
	Add a shape to the Rigid Body (convex only)
	End Rem
	Method AddShape(Shape:p2D_Shape)
		
		'I bet there is an easier way?
		
		Local Tmp:p2D_Shape[Shapes.Length]
		Tmp=Shapes[..]
		Shapes=New p2D_Shape[Shapes.Length+1]
		For Local n=0 To Tmp.Length-1
			Shapes[n]=Tmp[n]
		Next
		Shapes[Shapes.Length-1]=Shape
		
		'Fix Bounding Info
		UpdateBoundingInfo()
		
	End Method
	
	
	Rem
	bbdoc: Updates to Bounding Info of the Rigid Body
	End Rem
	Method UpdateBoundingInfo()
		'-Find Size-
		For Local Shape:p2D_Shape=EachIn Shapes
			Shape.UpdateBoundingInfo()
			If Shape._Size>_Size Then _Size=Shape._Size
		Next
		
	End Method
	
	Rem
	bbdoc: SetForce
	End Rem
	Method SetForce(_X#,_Y#)
		Velocity.Set(_X#*InvMass#,_Y#*InvMass#)
	End Method
	
	Rem
	bbdoc: SetForce2
	End Rem
	Method SetForce2(_X#,_Y#)
		'Doto... non-center point force, Twists
	End Method
	
	Rem
	bbdoc: SetTwist
	End Rem
	Method SetTwist(_Rotation#)
		AngVelocity#:+_Rotation#*InvMass#
	End Method
	
	Method BodyDistance#(Other:p2D_Body)
		Return Distance#(Position.X#,Position.Y#,Other.Position.X#,Other.Position.Y#)
	End Method
	
	Method BodyDistance_Squared#(Other:p2D_Body)
		Return Distance_Squared#(Position.X#,Position.Y#,Other.Position.X#,Other.Position.Y#)
	End Method
	
	
	Function LinePick:p2D_Body(_x#,_y#,_x2#,_y2#)
		
		Local vOffset:p2D_Vector = New p2D_Vector
		Local vAxis:p2D_Vector = New p2D_Vector
		
		For Local Body:p2D_Body = EachIn p2D_Simulator._BodyList 'Sort based on Distance!!
			If Body.Pickmode=1 Then
				If Body.Shapes.Length<>0 Then
					
					'### Get closest point on the line, (from "SSwift",  I think) ###'
						Local U# = (Body.Position.X# - _X#) * (_X2# - _X#) + (Body.Position.Y# - _Y#) * (_Y2# - _Y#)
						U# = U# / ((_X2# - _X#)*(_X2# - _X#) + (_Y2# - _Y#)*(_Y2# - _Y#))
						'Stop it coming of the ends
						If U#<0 Then U#=0; If U#>1 Then U#=1
						'Calculate coordinates of said point.
						Local Px# = _X# + (U# * (_X2# - _X#))
						Local Py# = _Y# + (U# * (_Y2# - _Y#))
					
					If Distance_Squared#(Body.Position.X#,Body.Position.Y#,Px#,Py#) < (Body._size#*Body._size#) Then
						
						vOffset.Set( _X# - Body.Position.X# , _Y# - Body.Position.Y#)
						Local Found_seperating=False
						
						For Local Polygon:p2D_Shape=EachIn Body.Shapes
							For Local i= 0 To (Polygon.Vertices.Length-1)+1
								
								Local n
								If i=0 Then
									vAxis.Set(_X-_X2,_Y-_Y2)
									vAxis.Normalize()
									n=-1
								Else
									n=i-1
									If n=Polygon.Vertices.Length - 1
										vAxis.Set(Polygon.Vertices[0].X-Polygon.Vertices[n].X,Polygon.Vertices[0].Y-Polygon.Vertices[n].Y)
									Else
										vAxis.Set(Polygon.Vertices[n+1].X-Polygon.Vertices[n].X,Polygon.Vertices[n+1].Y-Polygon.Vertices[n].Y)
									End If
									vAxis.Normalize()
								End If
								
								vAxis.Set(-vAxis.y,vAxis.x)'Make perpendicular
								
								'- Get Projected Interval -'
								Local Min0#,Max0#
								Local Min1#,Max1#
								
								'Projected Polygon
								Polygon.CalculateInterval(vAxis,min0,max0)
								
								'Projected Line (0 - 'End of line') it is in local space
								CalculateIntervalPlot(vAxis, _X-_X2 , _Y-_Y2 ,min1,max1)
								If min1 > 0 Then min1=0
								If max1 < 0 Then max1=0
								
								'Turn it in to global space (relative)
								Local sOffset# = vAxis.DotProduct(vOffset)
								min0 = min0 + sOffset;max0 = max0 + sOffset
								
								'- Get intersections -'
								Local d0# = min0 - max1	'\ Test for intersections
				  				Local d1# = min1 - max0 	'/
								
								If (d0# > 0) Or (d1# > 0) Then'seperating axis found
									
									Found_seperating=True
									Exit
									
								End If
								
							Next
						Next
						
						If Found_seperating=False
							Return Body
						End If
						
					End If
				End If
			End If
		Next
		
		Return Null
	End Function
	
	Rem
	bbdoc: Uses #Pickmode to cheak if any body is overlap a point
	return: The overlaping body or NULL
	End Rem
	Function PlotPick:p2D_Body(_X#,_Y#)
	
		Local vOffset:p2D_Vector = New p2D_Vector
		Local vAxis:p2D_Vector = New p2D_Vector
		
		For Local Body:p2D_Body = EachIn p2D_Simulator._BodyList
			If Body.Pickmode=1 Then
				If Body.Shapes.Length<>0 Then
					If Distance_Squared#(Body.Position.X#,Body.Position.Y#,_X#,_Y#)<(Body._size#*Body._size#) Then
						
						vOffset.Set( _X# - Body.Position.X# , _Y# - Body.Position.Y#)
						
						Local Found_seperating=False
						
						For Local Polygon:p2D_Shape=EachIn Body.Shapes
							For Local n= 0 To (Polygon.Vertices.Length-1)
								
								If n=Polygon.Vertices.Length - 1
									vAxis.Set(Polygon.Vertices[0].X-Polygon.Vertices[n].X,Polygon.Vertices[0].Y-Polygon.Vertices[n].Y)
								Else
									vAxis.Set(Polygon.Vertices[n+1].X-Polygon.Vertices[n].X,Polygon.Vertices[n+1].Y-Polygon.Vertices[n].Y)
								End If
								vAxis.Normalize()
								
								vAxis.Set(-vAxis.y,vAxis.x)'Make perpendicular
								
								'- Get Projected Interval -'
								Local Min0#,Max0#
								
								Polygon.CalculateInterval(vAxis,min0,max0)
								
								'- Get intersections -'
								Local sOffset# = vAxis.DotProduct(vOffset)
								
								min0 = min0 + sOffset
								max0 = max0 + sOffset
								
								If (min0 > 0) Or (-max0 > 0) Then'seperating axis found
									
									Found_seperating=True
									Exit
									
								End If
								
							Next
						Next
						
						If Found_seperating=False
							Return Body
						End If
						
					End If
				End If
			End If
		Next
		
		Return Null
	End Function
	
	Method Collide(Other:p2D_Body)
		
		'Do the body types collide...
		If (CollisionType=0 Or Other.CollisionType=0) Then Return False
		If p2D_Simulator.CollisionTypeCollides(CollisionType, Other.CollisionType)=0..
				And p2D_Simulator.CollisionTypeCollides(Other.CollisionType,CollisionType)=0 Then Return False
		
		'Do the bodys have shapes...
		If Shapes.Length=0 Or Other.Shapes.Length=0 Then Return False
		
		'Can the bodys possibly collide at there distance...
		Local Min_Distance#=_size#+Other._size#
		If BodyDistance_Squared#(Other)>(Min_Distance#*Min_Distance#) Then Return False
		
		
		
		
		Local vOffset:p2D_Vector = New p2D_Vector
		vOffset.Set(Position.X - Other.Position.X, Position.Y - Other.Position.Y)
		
		
		Local vAxis:p2D_Vector = New p2D_Vector
		
		Local MTD:p2D_Vector
		Local MTD_Intersect#
		Local MTD_min0#
		Local MTD_max0#
		Local MTD_min1#
		Local MTD_max1#
		
		Local MTD_PolygonA:p2D_Shape
		Local MTD_PolygonB:p2D_Shape
		
		For Local PolygonA:p2D_Shape=EachIn Shapes
			For Local PolygonB:p2D_Shape=EachIn Other.Shapes
				
				
				For Local i = 0 To (PolygonA.Vertices.Length-1)+(PolygonB.Vertices.Length-1)
					
					'--- Get vAxis ---'
					
					
					Local n
					If i=<(PolygonA.Vertices.Length-1) Then
						n=i
						
						
						If n=PolygonA.Vertices.Length - 1
							vAxis.Set(PolygonA.Vertices[0].X-PolygonA.Vertices[n].X,PolygonA.Vertices[0].Y-PolygonA.Vertices[n].Y)
						Else
							vAxis.Set(PolygonA.Vertices[n+1].X-PolygonA.Vertices[n].X,PolygonA.Vertices[n+1].Y-PolygonA.Vertices[n].Y)
						End If
						
						vAxis.Normalize()
					Else
						n=(i-(PolygonA.Vertices.Length))
						
						
						If n=(PolygonA.Vertices.Length-1)+(PolygonB.Vertices.Length-1)+1
							vAxis.Set(PolygonB.Vertices[0].X-PolygonB.Vertices[n].X,PolygonB.Vertices[0].Y-PolygonB.Vertices[n].Y)
						Else
							vAxis.Set(PolygonB.Vertices[n+1].X-PolygonB.Vertices[n].X,PolygonB.Vertices[n+1].Y-PolygonB.Vertices[n].Y)
						End If
						
						vAxis.Normalize()
					End If
					
					vAxis.Set(-vAxis.y,vAxis.x)'Make perpendicular
					
					'- Get Projected Interval -'
					Local min0#,max0#
					Local min1#,max1#
					
					PolygonA.CalculateInterval(vAxis,min0,max0)
					PolygonB.CalculateInterval(vAxis,min1,max1)
					
					'- Get intersections -'
					
					Local sOffset# = vAxis.DotProduct(vOffset)
					
					min0 = min0 + sOffset
					max0 = max0 + sOffset
					
					Local d0# = min0 - max1	'\ Test for intersections
					Local d1# = min1 - max0 	'/
					
					If (d0 > 0) Or (d1 > 0) Then'seperating axis found
					
						Return False 'Found a seperating axis, they can't possibly be touching
					
					Else
						
						Local push#=0
						If d0<d1 Then
							push=d0
						Else
							push=d1
						End If
							
						If MTD=Null Then
							MTD=New p2D_Vector
							
							
							'Use...
							'MTD.Set(vAxis.x,vAxis.y)
							
							
							'Local axis_lengh_squared=MTD.DotProduct(MTD)
							
							'MTD.X:*(Push/axis_lengh_squared)
							'MTD.Y:*(Push/axis_lengh_squared)
							
							
							
							MTD.Set(Cos(vAxis.GetAngle()) ,Sin(vAxis.GetAngle()) )
							
							MTD_Intersect=push
							
							
							MTD_PolygonA=PolygonA
							MTD_PolygonB=PolygonB
							
							MTD_min0#=min0#
							MTD_max0#=max0#
							MTD_min1#=min1#
							MTD_max1#=max1#
							
						Else
							
							

							If MTD_Intersect>push Then
								
								MTD.Set(vAxis.x,vAxis.y)
								
								
								
								Local axis_lengh_squared#=MTD.DotProduct(MTD)
								
								'MTD.X:*(Push/axis_lengh_squared)
								'MTD.Y:*(Push/axis_lengh_squared)
								
								
								MTD.Set(Cos(vAxis.GetAngle())  ,Sin(vAxis.GetAngle()) )
								
								MTD_Intersect=push
								
								MTD_PolygonA=PolygonA
								MTD_PolygonB=PolygonB
								
								MTD_min0#=min0#
								MTD_max0#=max0#
								MTD_min1#=min1#
								MTD_max1#=max1#
							
							End If
										
							

						End If
						
					End If
					
					
					
					
				Next
						
					
			Next
		Next
		
		'Local PolygonA:p2D_Shape=ShapeA
		'Local PolygonB:p2D_Shape=ShapeB
		
		
		
		
		Local Temp:p2D_Vector=New p2D_Vector
		
		
		Temp.Set(Position.X,Position.Y)
		
		Temp.Subtract(Other.Position)
		
		
		If Temp.DotProduct(MTD)<0 Then
			MTD.X=-MTD.X
			MTD.Y=-MTD.Y
		End If
		
		'DebugLog "min0:"+MTD_min0#+" min1:"+MTD_min1#+" max0:"+MTD_max0#+" max1:"+MTD_max1#
		
		
		'- Get Projected Interval -'
		Local min0#,max0#
		Local min1#,max1#
		
		MTD.Normalize()
		
		MTD_PolygonA.CalculateInterval(MTD,min0,max0)
		MTD_PolygonB.CalculateInterval(MTD,min1,max1)
		
		
		Local sOffset# = MTD.DotProduct(vOffset)
		
		
		'min0=Sqr( (min0*MTD.x)+(min0*MTD.y) )
		'min1=Sqr( (min1*MTD.x)+(min1*MTD.y) )
		
		'max0=Sqr( (max0*MTD.x)+(max0*MTD.y) )
		'max1=Sqr( (max1*MTD.x)+(max1*MTD.y) )
		
		min0 = min0 + sOffset
		max0 = max0 + sOffset
		
		
		
		Local d0# = max1# - min0# '\ Test for intersections
		Local d1# = max0# - min1# '/
		
		Local push#
		If Abs(d0#)>Abs(d1#) Then
			push=d1#
		Else
			push=d0#
		End If
		
		MTD.X#:*Sqr(Abs(push))
		MTD.Y#:*Sqr(Abs(push))
		
		
		
		Local TotalMass#=InvMass#+Other.InvMass#
		If TotalMass=0 Then TotalMass=1
		
		
		Local OtherCollide=0
		Local SelfCollide=0
		
		
		
		SelfCollide=p2D_Simulator.CollisionTypeCollides(CollisionType, Other.CollisionType)
		OtherCollide=p2D_Simulator.CollisionTypeCollides( Other.CollisionType,  CollisionType)
		SelfCollide= (SelfCollide=1) Or (SelfCollide=3)
		OtherCollide= (OtherCollide=1) Or (OtherCollide=3)
		
		
		
		
		Local ForceVector:p2D_Vector = New p2D_Vector
		ForceVector.Add(Velocity)
		ForceVector.Subtract(Other.Velocity)
		
		
		
		Local Collision_Normal:p2D_Vector = MTD.Copy()
		Collision_Normal.Normalize()
		Local num= (ForceVector.X*Collision_Normal.X) + (ForceVector.Y*Collision_Normal.Y)
		Collision_Normal.X:*num
		Collision_Normal.Y:*num
		Collision_Normal.X:*2
		Collision_Normal.Y:*2
		
		ForceVector.X= (ForceVector.X-Collision_Normal.X)
		ForceVector.Y= (ForceVector.Y-Collision_Normal.Y)
		
		
		
		
		If SelfCollide Then
			If _BodyType<>2 Then Position.Add(MTD, (InvMass#/TotalMass) )
			If _BodyType<>2 Then
				'Velocity.Set(0,0)
				'Velocity.Add(ForceVector, (InvMass#/TotalMass) )
			End If
		Else
			If Other._BodyType<>2 Then Other.Position.Subtract(MTD, (InvMass#/TotalMass))
			If Other._BodyType<>2 Then
				'Other.Velocity.Set(0,0)
				'Other.Velocity.Subtract(ForceVector, (InvMass#/TotalMass))
			End If
		End If
		
		If OtherCollide  Then
			If Other._BodyType<>2 Then Other.Position.Subtract(MTD, (Other.InvMass#/TotalMass) )
			If Other._BodyType<>2 Then
				'Other.Velocity.Set(0,0)
				'Other.Velocity.Subtract(ForceVector, (Other.InvMass#/TotalMass) )
			End If
		Else
			If _BodyType<>2 Then Position.Add(MTD, (Other.InvMass#/TotalMass) )
			If _BodyType<>2 Then
				'Velocity.Set(0,0)
				'Velocity.Add(ForceVector, (Other.InvMass#/TotalMass) )
			End If
		End If
		
		
		
		
		If SelfCollide Then Velocity.Add(MTD,0.4)
		If OtherCollide Then Other.Velocity.Subtract(MTD,0.4)
		
		
		If SelfCollide Then
			Num_Lower(Velocity.X,0.03)
			Num_Lower(Velocity.Y,0.03)
		End If
		
		If OtherCollide Then
			Num_Lower(Other.Velocity.X,0.03)
			Num_Lower(Other.Velocity.Y,0.03)
		End If
		
		




		
		Return True
		
	End Method
	
End Type



Type p2D_Joint
	
	Field BodyA:p2D_Body
	Field BodyB:p2D_Body
	
	Field Typ:Byte
	
	
	Method Create()
	
	End Method
	
	
	
	
	
	
End Type


Type p2D_Vector
	Field X#,Y#
	Method Set(_X#,_Y#)
		X#=_X#
		Y#=_Y#
	End Method
	
	Method Rotate(angle#)
		'local tx=x'?
		'x =  x * Cos(angle) - y * Sin(angle);
		'y = tx * Sin(angle) + y * Cos(angle);
		'Dis#=GetDistance#()
		'x= Cos(angle)*X#
		'y= Sin(angle)*Y#
		
		x= Cos(GetAngle#()+angle#)*GetDistance#()
		y= Sin(GetAngle#()+angle#)*GetDistance#()
		
	End Method
	
	Method Add(Other:p2D_Vector,Scalar#=1)
		X#:+(Other.X#*Scalar)
		Y#:+(Other.Y#*Scalar)
	End Method
	Method Subtract(Other:p2D_Vector,Scalar#=1)
		X#:-(Other.X#*Scalar)
		Y#:-(Other.Y#*Scalar)
	End Method
	
	Method DotProduct#(Other:p2D_Vector)
		Return (X * Other.X)+(Y * Other.Y)
	End Method
	
	
	
	Method GetAngle#()
		Return ATan2(Y#,X#)
	End Method
	
	Method GetDistance#()
		Return Sqr(X# * X# + Y# * Y#)
	End Method
	
	Method GetDistance_Squared#()
		Return X# * X# + Y# * Y#
	End Method 
	
	Method Normalize()
		Local Tmp_L#=GetDistance()
		If Tmp_L#=0 Then Return
		X#:* (1/Tmp_L#)
		Y#:* (1/Tmp_L#)
	End Method
	
	Method NormalizeVar(_X# Var, _Y# Var)
		Local Tmp_L#=GetDistance()
		If Tmp_L#=0 Then Return
		_X#=X#/ Tmp_L#
		_Y#=Y#/ Tmp_L#
	End Method
	
	
	Method MultiScalar(Scalar#)
		X#:* Scalar
		Y#:* Scalar
	End Method
	
	
	Method Slope#()
		Return Y#/X#
	End Method
	
	
	Method Copy:p2D_Vector()
		Local Vector:p2D_Vector=New p2D_Vector
		Vector.X=X
		Vector.Y=Y
		Return Vector
	End Method
	
End Type


Type p2D_Shape
	
	Field Vertices:p2D_Vector[]
	Field _Vertices:p2D_Vector[]
	Field _size#
	
	
	
	Function CreateBox:p2D_Shape(Width:Float, Height:Float)
		Local Shape:p2D_Shape=New p2D_Shape
		
		Shape._Vertices=New p2D_Vector[4]
		
		Shape._Vertices[0]=New p2D_Vector
		Shape._Vertices[0].Set(-Width/2,-Height/2)
		
		Shape._Vertices[1]=New p2D_Vector
		Shape._Vertices[1].Set(Width/2,-Height/2)
		
		Shape._Vertices[2]=New p2D_Vector
		Shape._Vertices[2].Set(Width/2,Height/2)
		
		Shape._Vertices[3]=New p2D_Vector
		Shape._Vertices[3].Set(-Width/2,Height/2)
		
		Shape.SetVertices()
		
		Return Shape
	End Function
	
	
	Function CreateConvex:p2D_Shape(Radius:Float, NumPoints:Int)
		If NumPoints<2 Then Return Null
		
		Local Shape:p2D_Shape=New p2D_Shape
		Shape._Vertices=New p2D_Vector[NumPoints]
		For Local n=0 To NumPoints-1
			
			Shape._Vertices[n]=New p2D_Vector
			Local Dir#=(Float(n)/Float(NumPoints))*360
			Shape._Vertices[n].Set(Cos(Dir#)*Radius,Sin(Dir#)*Radius)
			
		Next
		Shape.SetVertices()
		
		Return Shape
	End Function

	
	
	Rem
	bbdoc: Recalculate the shape's size for collisions (you should not need this)
	End Rem
	Method UpdateBoundingInfo()
		
		'---Get size (Squared)---'
		Local tmp#=0
		Local tmp2#=0
		For Local Vertice:p2D_Vector=EachIn _Vertices
			tmp2=Vertice.GetDistance()
			If tmp<tmp2 Then tmp=tmp2
		Next
		_size=tmp
		
	End Method
	
	
	Rem
	private doc: Sets Vertices to _Vertices
	End Rem
	Method SetVertices()
		Local n
		If Vertices.Length<>_Vertices.Length Then
			For n=0 To Vertices.Length - 1
				Vertices[n]=Null
			Next
			Vertices=New p2D_Vector[_Vertices.Length]
			For n=0 To Vertices.Length - 1
				Vertices[n]=New p2D_Vector
			Next
		End If
		For n=0 To _Vertices.Length - 1
			Vertices[n].Set(_Vertices[n].x,_Vertices[n].y)
		Next
	End Method
	
	Rem
	bbdoc: Rotates all the Vertices of the Shape an absolute angle
	End Rem
	Method Rotate(_Dir#)
		SetVertices()
		For Local Vertice:p2D_Vector=EachIn Vertices
			Local Dir#=Vertice.GetAngle()
			Local Dis#=Vertice.GetDistance()
			Dir#=Dir#+_Dir#
			Vertice.X=Cos(Dir#)*Dis#
			Vertice.Y=Sin(Dir#)*Dis#
		Next
	End Method
	
	Rem
	bbdoc: Move to shape to an average point
	End Rem
	Method Center()
		Local TotalX#=0
		Local TotalY#=0
		For Local Vertice:p2D_Vector=EachIn Vertices
			TotalX:+Vertice.X; TotalY:+Vertice.Y
		Next
		Move(TotalX/Vertices.length,TotalY/Vertices.length)
	End Method
	
	Rem
	bbdoc: Move all the vertices in the shape
	End Rem
	Method Move(_X#,_Y#)
		For Local Vertice:p2D_Vector=EachIn Vertices
			Vertice.X:+_X#; Vertice.Y:+_Y#
		Next
	End Method
	
	
	Rem
	bbdoc: Draws to the Vertices (for debug only)
	End Rem
	Method Draw(_X#,_Y#)
		SetBlend ALPHABLEND
		'SetColor 255,255,255
		SetTransform 0,1,1
		SetAlpha 0.5
		
		Local Poly#[Vertices.Length *2]
		
		
		For Local i=0 To Vertices.Length - 1
			Poly[ (i*2) ]=Vertices[i].X+_X#
			Poly[ (i*2) +1 ]=Vertices[i].Y+_Y#
		Next
		
		DrawPoly( Poly )
		
		
		SetAlpha 1
		
		'SetViewport 0,0,graphics_width,graphics_height
		For Local i=0 To Vertices.Length - 1
			If i=Vertices.Length - 1
				DrawLine Vertices[i].X+_X#, Vertices[i].Y+_Y#, Vertices[0].X+_X#, Vertices[0].Y+_Y#
			Else
				DrawLine Vertices[i].X+_X#, Vertices[i].Y+_Y#, Vertices[i+1].X+_X#, Vertices[i+1].Y+_Y#
			End If
		Next
		
	End Method
	
	Method CalculateInterval(_Axis:p2D_Vector, _Min# Var, _Max# Var )
		'Project polygon
		_min = _Axis.DotProduct(Vertices[0])
		_max = _min
		Local d#
		For Local i = 0 To (Vertices.Length - 1)
			d = _Axis.DotProduct(Vertices[i])
			If d < _Min Then _Min = d
			If d > _Max Then _Max = d
		Next
	End Method
	
	
End Type


Private

Const Max_Collisions=100
		
		
Function CalculateIntervalPlot(_Axis:p2D_Vector, _X#, _Y# , _Min# Var, _Max# Var ); 
	'Project polygon
	_min = (_Axis.X# * _X#) + (_Axis.Y# * _Y#)
	_max = _min
End Function

Function Num_Lower(_Num# Var, _By#=1,_To#=0)
	If _Num#>_To# Then _Num#:-_By#
	If _Num#<_To# Then _Num#:+_By#
	If Abs(_Num#-_To#)<_By# Then _Num#=_To#
End Function

Function Distance#(X1#,Y1#,X2#,Y2#)
	Local X#=X2#-X1#, Y#=Y2#-Y1#
	Return Sqr(X#*X#+Y#*Y#)
End Function
	
Function Distance_Squared#(X1#,Y1#,X2#,Y2#)
	Local X#=X2#-X1#, Y#=Y2#-Y1#
	Return X#*X#+Y#*Y#
End Function

Function GetLength_Squared#(_X#,_Y#)
	Return (_X# * _X#) + (_Y# * _Y#)
End Function



Function GetBit(_Byte:Byte, _BitN:Byte) 'Fix speed...
	Local _tmp:Byte=_Byte
	For Local n=0 To 7
		If 0>_tmp-2^n Then
		If n<>_BitN Then _tmp:-2^n
		End If
		
	Next
	If _tmp=2^_BitN Then Return True
	Return False
End Function

Function SetBitArray(_Bit:Byte[])
	Return _Bit[0]*2^0  + _Bit[1]*2^1 + _Bit[2]*2^2 + _Bit[3]*2^3 + _Bit[4]*2^4 + _Bit[5]*2^5 + _Bit[6]*2^6 + _Bit[7]*2^7
End Function

Function SetBit(_Bit0,_Bit1,_Bit2,_Bit3,_Bit4,_Bit5,_Bit6,_Bit7)
	Return _Bit0*2^0  + _Bit1*2^1 + _Bit2*2^2 + _Bit3*2^3 + _Bit4*2^4 + _Bit5*2^5 + _Bit6*2^6 + _Bit7*2^7
End Function

Function SetBitByByte(_Byte:Byte, _BitN:Byte, _value:Byte)
	Local _tmp:Byte=_Byte
	For Local n=0 To 7
		If _BitN<>n Then _tmp:+GetBit(_Byte, n)*2^n
	Next
	 _tmp:+ _value*2^ _BitN
	
	Return _tmp
End Function



Public



'End Rem










I would like to help too, if I can

Yes as I stated in that post (link above) this is a great idea, I just wish I had some time to try.

IMHO I think we need a simple to access, powerful toolset, which can be used by simply passing the name of an entity to a function. What happens underneath should happen totally automatically.

I have been working hard with Flash and Director this year, and one of the books I have managed to get hold of is excellent for this kinda thing.

I've yet to understand most of it, but when I do...

;)

IPete2.

Luke, that is a very good start! Perfect base to build upon.

Pete, I agree with you. Tell me more how you would like it to work, simple example (skip the underlying magic for now).

I'll try to put these things together into the very base.

Move to Top of Topic

The coordinate system you are using it's not good(no ofense of course). the reason I say that it's because it's not based on the Cartesian coordinate system. To do that you have to have the 0 angles at the right and 90 angles at the up. To do that you have to get angles this way atan2(-y , x). And then
x = cos(angle) * Length (the same with yours. but..)
y = - sin(angle) * Length

I am not saing that you are wrong but it's better to work with Cartesian coordinate system as it ise more clasic and we will find solution for problems more easily.
The system that way works good with the negativy values that you are getting when you overcome the 180 angles or when you are giving over 180 angle e.g. 270. that equals to -90

If you wand to get always positive value you just have to put inside the method
if angle< 0 then angle:+360

Here my HAVector2d that I have done this morning


Type HAVector2d
	Field x# , y#
	
	Function create:HAVector2d(_x# = 0 , _y# = 0)
		Local _V:HAVector2d = New HAVector2d
		_V.x = _x
		_V.y = _y
		Return _V
	End Function
	
	Function createFromAngleAndLength:HAVector2d(_angle# = 0 , _Length# = 0)
		Local _V:HAVector2d = New HAVector2d
		_V.x = Cos(_angle) * _Length
		_V.y = - Sin(_angle) * _Length
		Return _V
	End Function
	
	Method draw()
		DrawLine GraphicsWidth() / 2 , GraphicsHeight()/2 , GraphicsWidth() / 2 + x , GraphicsHeight() / 2 + y
	End Method
	
	Method set(_x:Float , _y:Float)
		x = _x
		y = _y
	End Method
	
	Method getLength:Float()
		Return Sqr(x*x + y*y)
	End Method
	
	Method getAngle:Float()
		Return ATan2(-y , x)
	End Method
	
	Method Multiply(_Multiplier:Float)
		x:* _Multiplier
		y:* _Multiplier
	End Method
	
	Method plusValue(_Plus:Float)
		Local an:Float = getAngle()
		x = x + Cos( an) * _plus
		y = y - Sin( an ) * _plus
	End Method
	
	Method reverse()
		x = -x
		y = -y
	End Method
	
	Method setAngle(_angle:Float)
		Local _length:Float = self.getLength()
		x = Cos(_angle) * _length
		y = - Sin(_angle) * _length
	End Method
	
	Method setLength(_length:Float)
		Local an:Float = self.getAngle()
		x =  + (Cos(an) * _length)
		y =  - (Sin(an) * _length)
	End Method
	
	Method addVector(_HAVector2d:HAVector2d)
		x = x + Cos( _HAVector2d.getAngle() ) * _HAVector2d.getLength()
		y = y - Sin( _HAVector2d.getAngle() ) * _HAVector2d.getLength()	
	End Method
	
	
	Method subtractVector(_HAVector2d:HAVector2d)
		'addVector(_HAVector2d)
		x = x - Cos( _HAVector2d.getAngle() ) * _HAVector2d.getLength()
		y = y + Sin( _HAVector2d.getAngle() ) * _HAVector2d.getLength()	
	End Method
	
	Method getVector(_V:HAVector2d)
		x = _V.x
		y = _V.y
	End Method
	
End Type


EDIT: And here are the changes in TVector (I don't know if I forgeted somethink)
	'		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:TVector( Length , Direction )
	
		Local Vector:TVector = Create(1,0)
		Vector.x = Cos(Direction) * Length
		Vector.y = -Sin(Direction) * Length		
		Return Vector
		
	EndFunction

	'		 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
		
		Local Angle# = GetDirection()
		x = Cos(Angle) * Length
		y = -Sin(Angle) * Length
	EndMethod
	Method SetMagnitude( Length# )
		SetLength( Length )
	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# = ATan2(-y , x)
		If Angle < 0 Then Angle:+360
		Return Angle
	End Method

	'		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


EDIT2: And from wikipedia fro Cartesian Coordinate System : http://en.wikipedia.org/wiki/Cartesian_coordinate_system

Good work, I agree with you on this. I never thought about it. It's just that (I think) the graphics are drawn with inversed Y-axis. Anyhow using the normal system feels more at home for me too.

Any suggestions for the formation of TVector? I mean will you use the new TVector?

I like where this is going, also checkout this: soldiers.250free.com/BlitZMax/Polycolly.zip
Download and run the exe's for some impressive physics and collide demos. Includes source in C++.

Of course I am going to use the new TVector. I don't have any sugestion so far (time will tell).
And yes I am looking in PollyColly rigth now and it looks really good but I don't have c++ background so... it will be hard for me.

Let me make this thread a sticky for you!. But if I see lack of intrest (ie dead!) I will un-sticky it, unless its complete!!. Good luck :).

And yes I am looking in PollyColly rigth now and it looks really good but I don't have c++ background so... it will be hard for me.
Same here. Don't miss the excellent tutorial (in html) that comes along.

@Shagwana, Thanks. Note that I intend to create a new thread as we progress (with links to old ones). This is so the discussion can be focused on the most recent updates, questions and problems.

I'll work on a base for the Line Type now, which will be based upon your Haline2D and TVector.

(I'll update the full TVector with Cartesian system in a moment)

@Shagwana, Thanks. Note that I intend to create a new thread as we progress (with links to old ones). This is so the discussion can be focused on the most recent updates, questions and problems.
No problem will sort as you go along.

I had maded some progress in HALine2d
here is the type with an example in reflection
Strict

Framework BRL.Max2d
Import BRL.GLMax2d
Import BRL.Math


Type HaLine2d
	Field x1# , y1# , x2# , y2#
	
	Function create:HALine2d(_x1# = 0 , _y1 = 0 , _x2# = 10 , _y2# = 0)
		Local FLine:HALine2d = New HALine2d
		FLine.x1 = _x1
		FLine.y1 = _y1
		FLine.x2 = _X2
		FLine.y2 = _y2
		Return FLine
	End Function
	
	Function createParallel:HALine2d(Line1:HALine2d , _x , _y , _Length)
		Local Line2:HALine2d = New HALine2d
		Line2.x1 = _x
		Line2.y1 = _y
		Line2.x2 = Line2.x1 + ( Cos(Line1.getAngle() ) * _Length)
		Line2.y2 = Line2.y1 - ( Sin(Line1.getAngle() ) * _Length)
		Return Line2
	End Function
	
	Function createVertical:HALine2d(Line1:HALine2d , _x , _y , _Length)
		Local Line2:HALine2d = New HALine2d
		Line2.x1 = _x
		Line2.y1 = _y
		Line2.x2 = Line2.x1 + ( Cos(Line1.getAngle() + 90) * _Length)
		Line2.y2 = Line2.y1 - ( Sin(Line1.getAngle() + 90) * _Length)
		Return Line2
	End Function
	
	Method Draw()
		DrawLine x1 , y1 , x2 , y2
	End Method
	
	Method GetLength:Float()
		Return Sqr( (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) )
	End Method
	
	Method getAngle:Float()
		Return ATan2(y1 - y2 , x2 - x1)
	End Method
	
	Method extendLine(Ex:Float , dir:Byte = 1)
		Local an:Float = self.getAngle()
		If Dir = True
			x2 = x2 + (Cos(an) * Ex)
			y2 =   y2 - (Sin(an) * Ex)
		End If
		If Dir = False
			x1 = x1 - (Cos(an) * Ex)
			y1 =   y1 + (Sin(an) * Ex)
		End If
	End Method
	
	Method reverse()
		Local xr# = x1
		Local yr# = y1
		x1 = x2
		y1 = y2
		x2 = xr
		y2 = yr
	End Method
	
	Method setLength(L:Float , dir:Byte = 1)
		Local an:Float = self.getAngle()
		If dir = True
			x2 = x1 + (Cos(an) * L)
			y2 = y1 - (Sin(an) * L)
		End If
		If dir = False
			x1 = x2 - (Cos(an) * L)
			y1 = y2 + (Sin(an) * L)
		End If
	End Method
	
	Method setAngle(an:Float , tr:Byte = 1)
		Local L:Float = self.getLength()
		If tr = True
			x2 = x1 + ( Cos(an) * L)
			y2 = y1 - ( Sin(an) * L)
		End If
		If tr = False
			x1 = x2 + ( Cos(an) * L)
			y1 = y2 - ( Sin(an) * L)
		End If
	End Method
	
	Method MoveTo(_x , _y , tr:Byte = 1)
		Local an# = getAngle()
		Local L# = getLength()
		If tr = True
			x1 = _x
			y1 = _y
			x2 = x1 + (Cos(an) * L)
			y2 = y1 - (Sin(an) * L)
		End If
		If tr = False
			x2 = _x
			y2 = _y
			x1 = x2 - (Cos(an) * L)
			y1 = y2 + (Sin(an) * L)
		End If
	End Method
	
	Method addLine(L:HALine2d)
		x2 = x2 + Cos( L.getAngle() ) * L.getLength()
		y2 = y2 - Sin( L.getAngle() ) * L.getLength()
	End Method
	
	Method CollideLine(_Line:HALine2d)

		Local L1d:Float			 
		Local L2d:Float			
		Local L1x#,L1y#,L2x#,L2y#
	
		L1x = x2-x1
		L1y = y2-y1
		L2x = _Line.x2-_Line.x1
		L2y = _Line.y2-_Line.y1
		
		L1d = ( _Line.y1 - y1 + (L2y/L2x)*( x1 - _Line.x1 )) / ( L1y - L2y*L1x/L2x )
	
		If L1d >=0 And L1d <=1 
			L2d  = ( x1 + L1x*L1d - _Line.x1 ) / L2x 
			If L2d >=0 And L2d <=1 
				Return True
			EndIf
		EndIf
		Return False			
	
	End Method
	
	Method GetCollideLinePoint(xi# Var , yi# Var , _Line:HALine2d)

		Local L1d:Float			 
		Local L2d:Float			
		Local L1x#,L1y#,L2x#,L2y#
	
		L1x = x2-x1
		L1y = y2-y1
		L2x = _Line.x2-_Line.x1
		L2y = _Line.y2-_Line.y1
		
		L1d = ( _Line.y1 - y1 + (L2y/L2x)*( x1 - _Line.x1 )) / ( L1y - L2y*L1x/L2x )
	
		If L1d >=0 And L1d <=1 
			L2d  = ( x1 + L1x*L1d - _Line.x1 ) / L2x 
			If L2d >=0 And L2d <=1 
				xi = x1 + L1d*L1x
				yi = y1 + L1d*L1y
				Return True
			EndIf
		EndIf
		Return False			
	
	End Method
	

End Type

Function reflectedLine:HALine2d(L1:HALine2d , L2:HALine2d , tr:Byte = 1)
	Local xi# , yi#
		If L1.GetCollideLinePoint(xi , yi , L2)		
			Local L3:HALine2d = HALine2d.createVertical(L2 , xi , yi , -100)
			Local an# =  L3.getAngle() - L1.getAngle() 
			L3 = HALine2d.create(xi , yi , xi-100 , yi)
			an = L1.getAngle() + an*2
			If tr = True Then an:-180
			L3.setAngle(an)
			If tr = True Then L3.setLength(Sqr( (L1.x2 - xi)*(L1.x2 - xi) + (L1.y2 - yi) * (L1.y2 - yi) ))
			If tr = False Then L3.setLength(Sqr( (L1.x1 - xi)*(L1.x1 - xi) + (L1.y1 - yi) * (L1.y1 - yi) ))
			Return L3
		End If
		Return Null
End Function

Function getPointsDistance:Float(_x1# , _y1# , _x2# , _y2#)
	Return Sqr( ( _x1 - _x2)*(_x1 - _x2) + (_y1 - _y2) * (_y1 - _y2) )
End Function





''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''   Test

Local L1:HALine2d = HALine2d.create(100 , 180 , 400 , 180)
Local L2:HALine2d = HALine2d.create(300 , 180 ,200 , 300)


SetGraphicsDriver GLMax2DDriver()
Graphics 640 , 480 , 0
SetClsColor 40 , 40 , 40


While Not KeyDown(Key_Escape)
	Local timer:Int = MilliSecs()    '''''for frames per seconds
	Cls
	test(L1 , L2)
	DrawText ( (MilliSecs() - timer)) , 400 , 10
	Flip
	FlushMem
Wend
End


Function Test(L1:HALine2d , L2:HALine2d)
	SetColor(255 , 40 , 40)
	L1.draw()
	
	SetColor(40 , 255 , 40)
	L2.Draw()
	
	SetColor(200 , 40 , 40)
	DrawText "xy1" , L1.x1 , L1.y1
	DrawText "xy2" , L1.x2 , L1.y2
	
	SetColor(40 , 200 , 40)
	DrawText "xy3" , L2.x1 , L2.y1
	DrawText "xy4" , L2.x2 , L2.y2
	
	SetColor(200 , 200 , 200)
	DrawText "x1 : " + L1.x1 , 10 , 10
	DrawText "y1 : " + L1.y1 , 10 , 20
	DrawText "x2 : " + L1.x2 , 10 , 30
	DrawText "y2 : " + L1.y2 , 10 , 40
	DrawText "x3 : " + L2.x1 , 10 , 50
	DrawText "y3 : " + L2.y1 , 10 , 60
	DrawText "x4 : " + L2.x2 , 10 , 70
	DrawText "y4 : " + L2.y2 , 10 , 80
	


	DrawText "Line 1 Length : " + L1.getLength() , 10 , 90
	DrawText "Line 2 Length : " + L2.getLength() , 10 , 100
	DrawText "Line 1 Angle : " + L1.getAngle() , 10 , 110
	DrawText "Line 2 Angle : " + L2.getAngle() , 10 , 120
	
	If KeyDown(Key_1)
		L1.x1 = MouseX()
		L1.y1 = MouseY()
	End If
	If KeyDown(Key_2)
		L1.x2 = MouseX()
		L1.y2 = MouseY()
	End If
	If KeyDown(Key_3)
		L2.x1 = MouseX()
		L2.y1 = MouseY()
	End If
	If KeyDown(Key_4)
		L2.x2 = MouseX()
		L2.y2 = MouseY()
	End If
	
	If KeyHit(Key_D)
		L1.addLine(L2)
	End If
	
	Local r:HALine2d = reflectedLine(L1 , L2 , True)
	If r<>Null 
		r.draw()
	End If
		
	
End Function


I will try to find out a good way for pollygons (from PollyColly and from Luke's p2d code and mathworld)

I'll take a look at it right away.

Updated:
Example and Debugger for the VectorLib
Strict 

Import "Vector2D.bmx"
'==============================================================

'==============================================================


'==============================================================
'						TEST CODE

'Code below is To test these functions
'Feel free To Try (warning it's boring)
'Uncomment the stuff you want To test

Local A:Vector2D 
Local B:Vector2D
Local Dir#
Local VL# = 30
Local VectorList:TList = CreateList()

A = Vector2D.CreateField(40,180)'x,y
VectorList.AddLast( A )


'B = Vector2D.CreateField( 2,50 )'lenght, Direction
'VectorList.AddLast( B )

'B.Multiply( 10 )'Scalar

'Print "BEFORE"
'Print "A M : "+A.Length()
'Print "B M : "+B.Length()
'Print "A Dir : "+A.Direction()
'Print "B Dir : "+B.Dir()'Same

'B.Add( A )
'B.Add( A )
'B.Add( A )

'B.SetDir( -180 )'Set dir 

'Print "AFTER"

'Print "A M : "+A.Length()
'Print "B M : "+B.Length()
'
'Print "A Dir : "+A.Direction()
'Print "B Dir : "+B.Angle()'Same as Direction()

dir = A.Dir360()

Graphics 350,300,0,50
While Not KeyDown(Key_Escape)
Cls


dir:+1
If dir > 360 Then dir = 0
For Local T:Vector2D = EachIn VectorList
	
	DrawText "A and Z to change the vector's length",20,20
	DrawText "0 Degrees is Left, 90 Degrees is up",20,250
		
	If KeyDown(Key_Space) Delay(1200)
	
	T.SetDir(Dir)
	DrawVectorInfo T, True, True, 50, 50
		
	SetColor 255,0,0'; DrawLine 150,150,T.X+150, T.Y+150
	DrawVector( T, Point(150,150) ,40,0)
	SetColor 255,255,255
	Plot 150,150
	
	If KeyDown( Key_A ) VL:+1
	If KeyDown( Key_Z ) 
		VL:-1 
		If VL < 1 Then VL = 1
	EndIf
	
	
	'If KeyHit( Key_U ) 
	If KeyDown( Key_U ) T.Normalize ;VL = 1
	 
	If VL > 2 T.SetMagnitude( VL )
		
Next

Flip
Wend
'EndRem

'==============================================================


'==============================================================

'==============================================================



Also note that I change Tvector to Vector2D. I feel that would be the best as there is a big chance someone will make a Vector3D one day.

Wave I think it will beter If you put the latest vertions of the Mod and the examples on your First (or the second) post so the newcomers can get them without traveling over the topic.

I agree, will do that.

I have been starting to work out how the full library architecture might look like. The idea I'm following right now is that our Line2d (as I call the Line-Type) will inherit Vector2D and Vector2D will inherit TShape.

Our TPhysicsObject will have a field called CollisionForm:TShape

Because All our shapes will inherit Tshape this would mean that Box,Line,Circle,Vector and Polygon all can be put in there. Also to take it one step further Polygon will be based upon Line2D and Box and Triangle will simple be special cases of the Polygon- not types of their own.

The final implementation (for the onces using the library) may be something like this:


Type TTank Extends MaxPhysicsObject
 .. All other stuff ..

	Method New()
		Tank.AddCollisionShape( Box( width, height, rotation ) )
		'Or perhaps a polygon:
		Tank.AddCollisionShape( Polygon(x1,y1,x2,y2.... ) )
	EndMethod
EndType

' We know how the collision will look like 
' now we also need to set the collision response

' My idea is to add collision planes (liek those for images but easier)
' Each plane contains some MaxPhysicsObjects 
' You decide the collision response parameters
' for each plane against each other plane. That is 
' for every object in those planes.

' EXAMPLE:
' All shots is added to the Shot_plane:
' Shots Extends MaxPhysicsObject
'
' Adding a shot might look something like this:
' Shot_Plane.Add( Shot )   
' 
' Then we decide how and IF everything in the Shot_Plane 
' should collide against other things in another plane

' Enter what will happen if something from Shot_Plane collides with Shot_Plane.
' Shot_plane.ResponseAgainst( Shot_Plane, Friction, Bounce, RandomRotation, SomethingElse? )
'
' We only have ONE plane so let's check our shots against 
' all other shots. In other words: the plan against itself.

 If Shot_plane.Collide( Shot_Plane )
'	
'	'At ResponseAgainst() above, we decided what would happen automatically	
'	'when two shots collide. IF they will bounce or slide.
'	'Here we can set other properties as damage dealt
'   
'	For Shot:TShot = Eachin ShotPlane.ObjectsCollided() 'A list or array  	
'		Shot.Life:-1
'		If Shot.Life <= 0 then CreateExplosion( Shot.X, Shot.Y )
'	Next
 EndIf
'
' After a collision has been detected we will also have other data availible to use
' ImpactXY and Deepth or impact - Speed of impact - ImpactForce or Momentum (depeding on Mass)
'


A more final plan that this needs to be worked out before we proceed much further.

And Haramanai, your line vs line example's reflected line seems to not display or display backwards if you move the lines around (try having the green line vertical for example). Perhaps a bug there?

Strict

Type CollisionForm

	Field Shape:TShape 'Rect, Line, Circle, Polygon, Could even be a vector
	'Used for collision detection and collision response!
	
	Field Force:Vector2D
	Field Position:Vector2D ' The Center of the object in relation to the screen
	Field Velocity:Vector2D
	Field Acceleration:Vector2D
	
EndType

Type Line2D Extends Vector2D

	Global List:TList

	Field StartPoint:Vector2D
	Field EndPoint:Vector2D
	Field Normal:Vector2D
	
	'Create a Line from XY coordinates
	Function CreateXY:Line2D( StartX, StartY, EndX, EndY )
		Return Create( Point(StartX, StartY), Point(EndX, EndY) )
	EndFunction
	
	'Create a line from points or position vectors
	Function Create:Line2D( StartPoint:TVector, EndPoint:TVector )
		Local Line:Line2D = New Line2D
		Line.X = EndPoint.X - StartPoint.X
		Line.Y = EndPoint.Y - StartPoint.Y
		Line.StartPoint = StartPoint
		Line.StartPoint = EndPoint
		Return Line 	
	EndFunction
	
	Method New()
		If Not List Then List = CreateList()
		List.AddLast(Self)
	EndMethod

	Method Draw()
		DrawLine StartPoint.X , StartPoint.Y , EndPoint.X , EndPoint.Y
	End Method
	
EndType

Type Box2D Extends TPolygon

	Field WallA:Line2D
	Field WallB:Line2D
	Field WallC:Line2D
	Field WallD:Line2D

	'Create with X, Y  and Width and Height
	Function CreateRect:Box2D( X, Y, Width, Height )
		Return Create( X1, Y2, X1 + Width, Y1 + Width, X3 + Height, Y3 + Height, X4 + Width + Height, Y4 + Width + Height)
	EndFunction

	'Box from Lines
	Function Create:Box2D( X1, Y2, X2, Y2, X3, Y3, X4, Y4 )
		Local Box:Box2D = New Box2D
		'This is a polygon!
		WallA = Line2D.Create( X1, Y1, X2, Y2 )
		WallB = Line2D.Create( X2, Y2, X3, Y3 )
		WallC = Line2D.Create( X3, Y3, X4, Y4 )				
		WallD = Line2D.Create( X4, Y4, X1, Y1 )		
		Return Box 	
	EndFunction
				
EndType


Here is polygon code for everyone to play around with.

Run the demo to see some boxes from polygons collide. Nothing fancy. We can probably use parts of it.
Strict

'TO TEST RUN
Graphics 800,600,0',300'16,500

Global Poly1:TPolygon = TPolygon.Create()
'This creates a box with size 100x100
Poly1.Add(-50,-50)
Poly1.Add(50,-50)
Poly1.Add(50,50)
Poly1.Add(-50,50)
Poly1.Add(-50,-50)
Global Poly2:TPolygon = Poly1.Copy()
Global Rect:TPolygon  = Poly1.Copy()

Global X,Y 'This is for the test ball
Global GW = GraphicsWidth()/2 , GH = GraphicsHeight()/2 'Center everything so that we look from the coordinates 0,0 in the middle

Local Fps:FpsCounter = New FPSCounter
While Not KeyDown(Key_Escape)

	If Poly1 And Poly2
	
		If KeyHit(1) Poly1.Add( MouseX()-GW,MouseY()-GH )	'LeftMouse
		
		If KeyHit(2) Poly1.Add( Poly1.ix[0],Poly1.iy[0] )'Join back to start 'Right Mouse
		
		If KeyHit(Key_Space) Poly1 = TPolygon.Create() 'Start on a new Polygon
		
		Plot MouseX(),MouseY()	 'Mark Mouse

		Poly1.Draw( GW,GH )
		
		Poly2.Remove()
		Poly2 = Poly1.Copy() 'Make a copy of the polygon
		Poly2.Scale( 0.1 , 0.1 )'10% smaller
		Poly2.Draw( MouseX(), MouseY() )
		
		If PolygonOverlap(Poly1,GW,GH,Poly2,MouseX(), MouseY() ,False )
			DrawText "< <   C O L L I S I O N   D E T E C T E D   > >" , 0,0
		EndIf
		
		If PolygonOverlap(Poly1,GW,GH,Rect,X,Y,False )
			DrawText "< <   C O L L I S I O N   D E T E C T E D   > >" , 2,0
		EndIf	
			
		If PolygonOverlap(Poly2,MouseX(),MouseY(),Rect,X,Y,False )
			DrawText "< <   C O L L I S I O N   D E T E C T E D   > >" , 0,2
		EndIf		

	EndIf

		Rect.Draw(X,Y) ; X:+Rand(-2,2) ;Y:+Rand(-1,1)'Draw and shake the ball		
		
		DrawText( "X: "+MouseX()+"  Y: "+MouseY(),20,20 ) 
		FPS.CalculateFPS() ;FPS.DrawFPS(20,40)
		
		If KeyDown(Key_D) Poly1 = Null ;Poly2 = Null
		DrawText( " Polygon Count : "+Tpolygon.Count,20,60 )
			
Flip;Cls	
Wend


Type FPSCounter
	Field FPS%,Count%,Time%
	
	Method CalculateFPS()
			Count:+1			
			If Time+1000 < MilliSecs() 'FPS last sec
				
				FPS=Count' <- Frames/Sec
				Count=0
				Time=MilliSecs()			
			EndIf	
	End Method
	
	Method DrawFPS(X=0,Y=0)
		DrawText "Current FPS: "+FPS,X,Y
	End Method
	
	Method New() Time = MilliSecs() EndMethod
End Type
'---------------------------------------------------------------------------------------




Rem
Here starts the actuall module 

Module indiepath.poly

ModuleInfo "Name: 2d Polygon Lib"
ModuleInfo "License: Public Domain"
ModuleInfo "Author: Tim Fisher & Gosse Corrupted , Edited by Wave~"

Import BRL.LinkedList
Import BRL.GLMax2D
End Rem


Global gSin#[360]
Global gCos#[360]

Local a%

For a = 0 To 359
	gSin#[a] = Sin(a)
	gCos#[a] = Cos(a)
Next

Type TPolygon
	
	Global List:TList
	Global Count
		
	Field iX#[64]	
	Field iY#[64]	
	Field fX#[64]	
	Field fY#[64]	
	Field iVertexCount		
	Field fScaleX#			
	Field fScaleY#			
	Field fAngle#			
	Field iMinX#				
	Field iMinY#				
	Field iMaxX#				
	Field iMaxY#
				
		'Used internally only
		Method New ()
            	If List = Null Then List = CreateList()
            	List.AddLast Self
			Count:+1
    		End Method		
		
		Method Remove()            	
			List.Remove Self
			Count:-1	
		EndMethod
		'Remove this Poly
		'MyPoly.Remove
		
		'Create a New Polygon Instance		
		'MyPoly:Polygon = Polygon.Create()
		Function Create:Tpolygon()
			Local Poly:TPolygon
			Poly = New TPolygon
			Poly.fScaleX=1;Poly.fScaleY=1
			Return Poly
		End Function		
		
		' The use:
		' MyPoly.AddVertex(x,y)
		Method AddVertex( X#,Y#, Update=True)
			iX#[iVertexCount] = x#
			iY#[iVertexCount] = y#		
			iVertexCount:+ 1
			If Update Then Self.Update()
		End Method
		'This is a even shorter version =)
		Method Add(X#,Y#,Update=True)
			AddVertex(X,Y,Update=True)		
		EndMethod
				
				
		'Scale alters the size
		'Ex to scale to double size
		'MyPoly.Scale(2,2)' 2 = 200%
		'Ex to scale to half size
		'MyPoly.Scale(0.5,0.5)' 0.5 = 50%
		Method Scale(sx#,sy#,Update=True)
			fScaleX#:* sx#
			fScaleY#:* sy#	
			If Update Then Self.Update()
		EndMethod

		
		'Resize the Poly by a stated amount
		'Set the polygon size		
		'MyPoly.ReSize(1,1)'set to original size
		Method Resize(sx#,sy#,update=True)
			fScaleX# = sx#
			fScaleY# = sy#	
			If update Then Self.Update()
		EndMethod
		
		
		'Turn the Poly By the stated amount
		'Ex MyPoly.Turn(15) 
		'Adds to the current direction
		Method Turn(rot#,update=True)
			fAngle# = wrap_angle(fAngle# + rot#)
			If update Then Self.Update()
		EndMethod
		
		
		'Rotate the Poly by the stated amount
		'Set the direction to this angle
		Method SetDir(Angle#,update=True)
			fAngle# = wrap_angle(angle#)
			If update Then Self.Update()
		EndMethod
		
		

		
		'Copy one poly to another
		'Returns a Polygon equal to the one you copied
		'Ex:
		'ACopyofMyPoly:Polygon = MyPoly.Copy()
		Method Copy:TPolygon()
			Local NewPoly:TPolygon
			NewPoly = New TPolygon
				
			For Local i = 0 To iVertexCount - 1
				NewPoly.iX#[i] = iX#[i]
				NewPoly.iY#[i] = iY#[i]
				NewPoly.fX#[i] = fX#[i]
				NewPoly.fY#[i] = fY#[i]
			Next
			
			NewPoly.iVertexCount = iVertexCount
			NewPoly.fScaleX#	= fScaleX#
			NewPoly.fScaleY#	= fScaleY#
			NewPoly.fAngle# 	= fAngle#
			NewPoly.iMinX# 	= iMinX#
			NewPoly.iMinY#	= iMinY#
			NewPoly.iMaxX# 	= iMaxX#
			NewPoly.iMaxY# 	= iMaxY#
			
			Return NewPoly
		EndMethod
		
		
		
		'Update the Poly
		Method Update()
			Local f1X#, f1Y#, f1#, f2#, angle#,i 
			
			iMinX = 9999999.00
			iMinY = 9999999.00
			iMaxX = -9999999.00
			iMaxY = -9999999.00
			
			For i = 0 To iVertexCount - 1
				f1X# = iX#[i] * fScaleX#
				f1y# = iY#[i] * fScaleY#
				
				angle# = fAngle#
				
				If angle# <> 0 Then
					f1# = gCos#[Angle#] * f1X# - gSin#[Angle#] * f1Y#
					f2# = gSin#[Angle#] * f1X# + gCos#[Angle#] * f1Y#
					f1X# = f1#
					f1y# = f2#
				EndIf
		
				fX#[i] = f1X#
				fY#[i] = f1Y#
					
				If f1X# < iMinX# Then iMinX = f1X#
				If f1Y# < iMinY# Then iMinY = f1Y#
				If f1X# > iMaxX# Then iMaxX = f1X#
				If f1Y# > iMaxY# Then iMaxY = f1Y#
			Next
		End Method			

		'Draw the Specified Poly to Screen
		'Uses the current drawing color
		'Dunno what happens with rotations and line-scales?
		Method Draw(x#,y#)
			Local lx#, ly#, i
			lx# = fX#[0] + x#
			ly# = fY#[0] + y#
			
			For i = 1 To iVertexCount -1
				DrawLine (lx#,ly#,fX#[i]+x,fY#[i]+y)
				lx# = fX#[i] + x#
				ly# = fY#[i] + y#
			Next
		EndMethod 
		
		'Make sure all angles are within 0 to 360 degrees
		Function Wrap_Angle#(angle#)
			While angle# >= 360 ; angle#:- 360 ; Wend
			While angle# <  0   ; angle#:+ 360 ; Wend
			Return angle#
		End Function
End Type
	
'Return TRUE if circles overlap
'This is faster than poly overlap and could be used 
'until we get into a "critical" range.
Function CircleOverlap(x1#,y1#,rad1#,x2#,y2#,rad2#)
	Local dx#, dy#, rsqr#
	dx# = x2# - x1#
	dy# = y2# - y1#
	rsqr# = (rad1# + rad2#) * (rad1# + rad2#)
	Return (dx#*dx#+dy#*dy# < rsqr#)
End Function
		
'Checks 2 polygons and sees if they overlap			
Function PolygonOverlap(poly1:TPolygon,x1#,y1#,poly2:TPolygon,x2#,y2#,bounding = True)

	Local tx1#, ty1#, tx2#, ty2#, tx3#, ty3#, tx4#, ty4#
	Local dSqr#, d1#, d2#, dx#, dy#
	Local lx1#, ly1#, lx2#, ly2#
	Local i,j
	
		If bounding Then
			tx1 = X1 + poly1.iMinX
			ty1 = Y1 + poly1.iMinY
			tx2 = X1 + poly1.iMaxX
			ty2 = Y1 + poly1.iMaxY
			tx3 = X2 + poly2.iMinX
			ty3 = Y2 + poly2.iMinY
			tx4 = X2 + poly2.iMaxX
			ty4 = Y2 + poly2.iMaxX
	

			If Not (tx3 > tx1 And ty3 > ty1 And tx3 < tx2 And ty3 < ty2) Then
				If Not (tx4 > tx1 And ty4 > ty1 And tx4 < tx2 And ty4 < ty2) Then
					If Not (tx3 > tx1 And ty4 > ty1 And tx3 < tx2 And ty4 < ty2) Then
						If Not (tx4 > tx1 And ty3 > ty1 And tx4 < tx2 And ty3 < ty2) Then
							Return False
						End If
					End If
				End If
			End If
		End If
		

		lx1 = poly1.fX#[0] + X1
		ly1 = poly1.fY#[0] + Y1
		lx2 = poly2.fX#[0] + X2
		ly2 = poly2.fY#[0] + Y2

		For i = 1 To poly1.iVertexCount - 1
			For j = 1 To poly2.iVertexCount - 1

			tx1 = poly1.fX#[i] + X1
			ty1 = poly1.fY#[i] + Y1
			tx3 = poly2.fX#[j] + X2
			ty3 = poly2.fY#[j] + Y2
			tx2 = lX1
			ty2 = lY1
			tx4 = lX2
			ty4 = lY2

			dSqr = (ty4-ty3)*(tx2-tx1)-(tx4-tx3)*(ty2-ty1)
			d1 = (ty1-ty3)
			d2 = (tx1-tx3)
			dX = ((tx2-tx1)*d1-(ty2-ty1)*d2)
			dY = ((tx4-tx3)*d1-(ty4-ty3)*d2)
	
			If dSqr = 0 Then
	
				If dX = 0 And dY = 0 Then
					Return True
				End If
			Else
	
				d1 = dX / dSqr
				d2 = dY / dSqr
				If (d1 >= 0 And d1 <= 1) And (d2 >= 0 And d2 <= 1) Then
					Return True
				End If
			End If

			lX2 = tx3
			lY2 = ty3
		Next

		lX1 = tx1
		lY1 = ty1
	Next
	Return False
End Function


Just a suggestion might be that you can have a vector type of Doubles in addition to normal Floats...
(there might be someone with the need for high value calculations)

Haramanai here is my implentation of the Line2D (mostly) following the overall plan (2 posts above). If you like it and think it will work together with everthing else please expand the type with your methods from haline2d. Try to use Vectors as much as possible instead of X,Y fields (I think that gives it more flexibility and readability).

I must say we have come a good way so far.
Strict

Type CollisionForm

	Field Shape:TShape 'Rect, Line, Circle, Polygon, Could even be a vector
	'Used for collision detection and collision response!
	
	Field Force:Vector2D
	Field Position:Vector2D ' The Center of the object in relation to the screen
	Field Velocity:Vector2D
	Field Acceleration:Vector2D
	
EndType

Type Line2D Extends Vector2D

	Global List:TList

	Field StartPoint:Vector2D
	Field EndPoint:Vector2D
	Field Normal:Vector2D
	
	'Create a Line from XY coordinates
	Function CreateXY:Line2D( StartX, StartY, EndX, EndY )
		Return Create( Point(StartX, StartY), Point(EndX, EndY) )
	EndFunction
	
	'Create a line from points or position vectors
	Function Create:Line2D( StartPoint:TVector, EndPoint:TVector )
		Local Line:Line2D = New Line2D
		Line.X = EndPoint.X - StartPoint.X
		Line.Y = EndPoint.Y - StartPoint.Y
		Line.StartPoint = StartPoint
		Line.StartPoint = EndPoint
		Return Line 	
	EndFunction
	
	Method New()
		If Not List Then List = CreateList()
		List.AddLast(Self)
	EndMethod

	Method Draw()
		DrawLine StartPoint.X , StartPoint.Y , EndPoint.X , EndPoint.Y
	End Method
	
EndType

Type Box2D Extends TPolygon

	Field WallA:Line2D
	Field WallB:Line2D
	Field WallC:Line2D
	Field WallD:Line2D

	'Create with X, Y  and Width and Height
	Function CreateRect:Box2D( X, Y, Width, Height )
		Return Create( X1, Y2, X1 + Width, Y1 + Width, X3 + Height, Y3 + Height, X4 + Width + Height, Y4 + Width + Height)
	EndFunction

	'Box from Lines
	Function Create:Box2D( X1, Y2, X2, Y2, X3, Y3, X4, Y4 )
		Local Box:Box2D = New Box2D
		'This is a polygon!
		WallA = Line2D.Create( X1, Y1, X2, Y2 )
		WallB = Line2D.Create( X2, Y2, X3, Y3 )
		WallC = Line2D.Create( X3, Y3, X4, Y4 )				
		WallD = Line2D.Create( X4, Y4, X1, Y1 )		
		Return Box 	
	EndFunction
				
EndType


Also Updated to Vector Library to use doubles instead of floats - Thanks LarsG

Ok I puted the methods in the Line2d

Here it is the New Line2d
Type Line2D 

	Global List:TList
	Field X# , Y#
	Field StartPoint:Vector2D
	Field EndPoint:Vector2D
	Field Normal:Vector2D
	
	'Create a Line from XY coordinates
	Function CreateXY:Line2D( StartX, StartY, EndX, EndY )
		Return Create( Point(StartX, StartY), Point(EndX, EndY) )
	EndFunction
	
	'Create a line from points or position vectors
	Function Create:Line2D( StartPoint:Vector2d, EndPoint:Vector2d )
		Local Line:Line2D = New Line2D
		Line.StartPoint = StartPoint
		Line.EndPoint = EndPoint
		Return Line 	
	End Function
	
	Function createParallelXY:Line2d(Line1:Line2d , x# , y# , Length#)
		Local Line2:Line2d = New Line2d
		Line2.StartPoint = Vector2d.create( 0 , 0)
		Line2.EndPoint = Vector2d.create( 0 , 0)
		Line2.StartPoint.x = x#
		Line2.StartPoint.y = y#
		Line2.EndPoint.x = Line2.StartPoint.x + ( Cos(Line1.getAngle() ) * Length)
		Line2.EndPoint.y = Line2.StartPoint.y - ( Sin(Line1.getAngle() ) * Length)
		Return Line2
	End Function
	
	Function createVertical:Line2d(Line1:Line2d , _x# , _y# , _Length#)
		Local Line2:Line2d = Line2d.createXY(_x , _y , Line1.StartPoint.x , Line1.StartPoint.y)
		Line2.StartPoint.x = _x
		Line2.StartPoint.y = _y
		Line2.EndPoint.x = Line2.StartPoint.x + ( Cos(Line1.getAngle() + 90) * _Length)
		Line2.EndPoint.y = Line2.StartPoint.y - ( Sin(Line1.getAngle() + 90) * _Length)
		Return Line2
	End Function


	
	Method New()
		If Not List Then List = CreateList()
		List.AddLast(Self)
	EndMethod

	Method Draw()
		DrawLine StartPoint.X , StartPoint.Y , EndPoint.X , EndPoint.Y
	End Method
	
	Method GetLength:Float()
		Return Sqr( (EndPoint.x - StartPoint.x) * (EndPoint.x - StartPoint.x) + (EndPoint.y - StartPoint.y) * (EndPoint.y - StartPoint.y) )
	End Method
	
	Method getAngle:Float()
		Return ATan2(StartPoint.y - EndPoint.y , EndPoint.x - StartPoint.x)
	End Method
	
	Method extendLine(Ex:Float , dir:Byte = 1)
		Local an:Float = self.getAngle()
		If Dir = True
			EndPoint.x = EndPoint.x + (Cos(an) * Ex)
			EndPoint.y =   EndPoint.y - (Sin(an) * Ex)
		End If
		If Dir = False
			StartPoint.x = StartPoint.x - (Cos(an) * Ex)
			StartPoint.y =   StartPoint.y + (Sin(an) * Ex)
		End If
	End Method
	
	Method reverse()
		Local xr# = StartPoint.x
		Local yr# = StartPoint.y
		StartPoint.x = EndPoint.x
		StartPoint.y = EndPoint.y
		EndPoint.x = xr
		EndPoint.y = yr
	End Method
	
	Method setLength(L:Float , dir:Byte = 1)
		Local an:Float = getAngle()
		If dir = True
			EndPoint.x = StartPoint.x + (Cos(an) * L)
			EndPoint.y = StartPoint.y - (Sin(an) * L)
		End If
		If dir = False
			StartPoint.x = EndPoint.x - (Cos(an) * L)
			StartPoint.y = EndPoint.y + (Sin(an) * L)
		End If
	End Method
	
	Method setAngle(an:Float , tr:Byte = 1)
		Local L:Float = self.getLength()
		If tr = True
			EndPoint.x = StartPoint.x + ( Cos(an) * L)
			EndPoint.y = StartPoint.y - ( Sin(an) * L)
		End If
		If tr = False
			StartPoint.x = EndPoint.x + ( Cos(an) * L)
			StartPoint.y = EndPoint.y - ( Sin(an) * L)
		End If
	End Method
	
	Method MoveTo(_x , _y , tr:Byte = 1)
		Local an# = getAngle()
		Local L# = getLength()
		If tr = True
			StartPoint.x = _x
			StartPoint.y = _y
			EndPoint.x = StartPoint.x + (Cos(an) * L)
			EndPoint.y = StartPoint.y - (Sin(an) * L)
		End If
		If tr = False
			EndPoint.x = _x
			EndPoint.y = _y
			StartPoint.x = EndPoint.x - (Cos(an) * L)
			StartPoint.y = EndPoint.y + (Sin(an) * L)
		End If
	End Method
	
	Method addLine(L:Line2d)
		EndPoint.x = EndPoint.x + Cos( L.getAngle() ) * L.getLength()
		EndPoint.y = EndPoint.y - Sin( L.getAngle() ) * L.getLength()
	End Method
	
	Method CollideLine(_Line:Line2d)

		Local L1d:Float			 
		Local L2d:Float			
		Local L1x#,L1y#,L2x#,L2y#
	
		L1x = EndPoint.x-StartPoint.x
		L1y = EndPoint.y-StartPoint.y
		L2x = _Line.EndPoint.x-_Line.StartPoint.x
		L2y = _Line.EndPoint.y-_Line.StartPoint.y
		If L2x = 0 Then L2x =0.00001  ''' Just as small it can be
		
		L1d = ( _Line.StartPoint.y - StartPoint.y + (L2y/L2x)*( StartPoint.x - _Line.StartPoint.x )) / ( L1y - L2y*L1x/L2x )
		'If L2y = 0 Then L1d = ( _Line.StartPoint.y - StartPoint.y + (L2y/L2x)*( StartPoint.x - _Line.StartPoint.x )) / ( L1y - L2y*L1x/L2x )

		If L1d >=0 And L1d <=1 
			L2d  = ( StartPoint.x + L1x*L1d - _Line.StartPoint.x ) / L2x 
			
			If L2d >=0 And L2d <=1 
				Return True
			EndIf
		EndIf
		Return False			
	
	End Method
	
	Method GetCollideLinePoint(xi# Var , yi# Var , _Line:Line2d)

		Local L1d:Float			 
		Local L2d:Float			
		Local L1x#,L1y#,L2x#,L2y#
	
		L1x = EndPoint.x-StartPoint.x
		L1y = EndPoint.y-StartPoint.y
		L2x = _Line.EndPoint.x-_Line.StartPoint.x
		L2y = _Line.EndPoint.y-_Line.StartPoint.y
		If L2x = 0 Then L2x =0.00001  ''' Just as small it can be
		L1d = ( _Line.StartPoint.y - StartPoint.y + (L2y/L2x)*( StartPoint.x - _Line.StartPoint.x )) / ( L1y - L2y*L1x/L2x )
	
		If L1d >=0 And L1d <=1 
			L2d  = ( StartPoint.x + L1x*L1d - _Line.StartPoint.x ) / L2x 
			If L2d >=0 And L2d <=1 
				xi = StartPoint.x + L1d*L1x
				yi = StartPoint.y + L1d*L1y
				Return True
			EndIf
		EndIf
		Return False			
	
	End Method
	
	Method reflectedLine:Line2d(L2:Line2d , tr:Byte = 1)
	Local xi# , yi#
		If GetCollideLinePoint(xi , yi , L2)		
			Local L3:Line2d = Line2d.createVertical(L2 , xi , yi , 100)
			Local an# =  L3.getAngle() - getAngle() 
			L3 = Line2d.createXY(xi , yi , xi-100 , yi)
			an = getAngle() + an*2
			If tr = True Then an:-180
			L3.setAngle(an)
			If tr = True Then L3.setLength(Sqr( (EndPoint.x - xi)*(EndPoint.x - xi) + (EndPoint.y - yi) * (EndPoint.y - yi) ))
			If tr = False Then L3.setLength(Sqr( (StartPoint.x - xi)*(StartPoint.x - xi) + (StartPoint.y - yi) * (StartPoint.y - yi) ))
			Return L3
		End If
		Return Null
	End Method

EndType




and here the reflexion sample
Local L1:Line2d = Line2d.createXY(100 , 180 , 400 , 180)
Local L2:Line2d = Line2d.createXY(300 , 180 ,200 , 300)

SetGraphicsDriver GLMax2DDriver()
Graphics 1024 , 756 , 0
SetClsColor 40 , 40 , 40


While Not KeyDown(Key_Escape)
	Local timer:Int = MilliSecs()    '''''for frames per seconds
	Cls
	test(L1 , L2)
	DrawText ( (MilliSecs() - timer)) , 400 , 10

	Flip
	FlushMem
Wend
End


Function Test(L1:Line2d , L2:Line2d )
	SetColor(255 , 40 , 40)
	L1.draw()
	
	SetColor(40 , 255 , 40)
	L2.Draw()
	

	

	If KeyDown(Key_1)
		L1.StartPoint.x = MouseX()
		L1.StartPoint.y = MouseY()
	End If
	If KeyDown(Key_2)
		L1.EndPoint.x = MouseX()
		L1.EndPoint.y = MouseY()
	End If
	If KeyDown(Key_3)
		L2.StartPoint.x = MouseX()
		L2.StartPoint.y = MouseY()
	End If
	If KeyDown(Key_4)
		L2.EndPoint.x = MouseX()
		L2.EndPoint.y = MouseY()
	End If
	

	
	Local r:Line2d = L1.reflectedLine(L2 , True)
	If r<>Null 
		r.draw()
	End If
		
	
End Function

The red line is the line that reflected

EDIT: I think we must make the create function in a differnt way so we can use create() and get the minimum.

For example
Function Create:Vector2D( X! = 0, Y! = 0 )
	
		Local Vector:Vector2D
		Vector = New Vector2D
		
		Vector.X!  = X!
		Vector.Y!  = Y!
		Return Vector 
		
	End Function


EDIT: How to use the reflection demo
keys: 1 puts the starting point of red line to the mousecursor
2 puts the end point of red line to the mousecursor
3 puts the starting point of green line to the
4 puts the end point of green line to themousecursor

what it do: Think that some think will travel from red's start point to the end of it. but then it collides to the green line and bounce so the real position of this travel it's the end of the new green line

EDIT4: The problem is from the colideLine Method created by Warpy in this post : http://www.blitzmax.com/Community/posts.php?topic=52384

I fixed it in a way. I changed the D2x to 0.0001 if it is 0. It's not perfect but this is what I have right now

Great Work!

The reason the create method has no default values is that you are supposed to use the function CreateVector() if you want to have defaults. The library itself uses the method and then you also have to specify both X and Y, for security reasons.

We would really need someone who knows C++, that would save us countless hours. Converting the polygon code from that library.

What did you think about my "collidionPlanes" idea?

We should really try to make a simple demo and show how a object (let's start with a circle) would slide and bounce against some lines. Where you can set the Friction and Bounce parameters.

The worst thing, I really hope making "demos" will be so much easier when we have the GUI mod..

RE:EDIT2 ok, I didn't get a null error, what I meant was the wrong reflection I got when I took the end point and put it first (then it reflects through the other line instead of away from it).

Also I would like to make a simple map editor (poly/line editor) so that we can build physics demos. Yet that would also "require" the GUI module..

I think our first priority should be a nice demo that shows off EVERY ascpect of the library. With loads of options and switches. Having a really good testing enviroment would allow us to test new features much easier and without having to rely on teori. I'm afraid we will do a lot of work that we have to redo because we edit a major thing.

One thing that came to my mind (sorry) was the Line2D. I think we would benifit from having fields liek this:
StartX, StartY
Vector:Vector2D 'The Line vector , From startXY to EndXY
EndX,EndY
Normal:Vector

Because this would mean that checking the lenght of the Line would mean checking the vector. Also the angle would follow. The best thing in my opinion of using the Vector2D type as much as possible (instead of rewriting code) is that if someone comes up with a better or more efficient way to calculate basic vector stuff then ALL of the library/module will benefit. And you never know what will happen in the future, only time will tell =)

I will soon create a new thread to sort the project up a bit.

We still have a lot of unanswered questions about the projectplan that needs to be discussed further.

I found the problem with the collideLine Method and I fixed in a way. I updated my post with the new vertion.

I cannot find your collidePlanes. pls point them to me.

I haven't written anything involving them yet. It's just a design idea. Implementing it shouldn't be too hard. We can simple have one TList for every plane. The planes are just a way to make collision checks easier and simpler for the end-user (or so I hope).

See my post on "full library architecture" (8 posts above)

To make the line bounce and slide all information we need is in this topic:
http://www.blitzbasic.com/Community/posts.php?topic=52511
All thanks to Warpy!

This is a little off topic but here is a simple Circle-Circle Collision routine for you to use.

Strict


Global CollisionObjectList:TList = CreateList()

Const COLL_DISABLED:Int = 0
Const COLL_STATIC:Int = 1
Const COLL_DYNAMIC:Int = 2

Global COLL_FRICTION:Float = 1.0
Global COLL_BOUNCE:Float = 1.0

Const COLL_CIRCLE:Int = 0

Type TCollisionObject
	Field Position:TVector2
	Field Velocity:TVector2
	Field Acceleration:TVector2

	Field LastCollider:TCollisionObject
	Field SeperationVector:TVector2
	
	Field Kind:Int
	Field Response:Int
	Field Radius:Float
	Field width:Float
	Field height:Float
	
	Method New()
		CollisionObjectList.AddLast(Self)
		SeperationVector = TVector2.Create()
		Position = TVector2.Create()
		Velocity = TVector2.Create()
		Acceleration = TVector2.Create()
	End Method
	
	Function CreateCircle:TCollisionObject(_parent:Object,_Response:Int,_Radius:Float,_X:Float = 0,_Y:Float = 0)
		Local Collider:TCollisionObject = New TCollisionObject
		Collider.Kind = COLL_CIRCLE
		Collider.Response = _Response
		Collider.Radius = _Radius
		Collider.width = _Radius * 2
		Collider.height = _Radius * 2
		Collider.Position.x = _X
		Collider.Position.Y = _Y
		Return Collider
	End Function
	
	Method Collision()
		LastCollider = Null
		For Local Collider:TCollisionObject = EachIn CollisionObjectList
			If Collider <> Self
			
				Select Collider.Kind
					Case COLL_CIRCLE
						Local _Distance:Float = sqr((Collider.Position.x-Position.x)*(Collider.Position.x-Position.x) + (Collider.Position.Y-Position.Y)*(Collider.Position.Y-Position.Y))
						If _Distance <= Collider.Radius + Radius 
							
							LastCollider = Collider
					
							Local _SeperationVector:TVector2 = TVector2.Create(Collider.Position.x-Position.x,Collider.Position.Y-Position.Y)
							Local _Angle:Float = _SeperationVector.Angle()
							
							_SeperationVector.x = Cos(_Angle) * (_Distance - (Radius+Collider.Radius)-1)
							_SeperationVector.Y = Sin(_Angle) * (_Distance - (Radius+Collider.Radius)-1)

							SeperationVector.x :+ _SeperationVector.x
							SeperationVector.Y :+ _SeperationVector.Y
						End If
				End Select
			End If
		Next
	End Method
	
	Method Render()
		SetColor 0,255,0
		If LastCollider SetColor 255,0,0
		Select Kind
			Case COLL_CIRCLE
				DrawOval Position.x-Radius,Position.Y-Radius,width,height
		End Select
		SetColor 255,255,255
	End Method
	
	Method Update()
		Velocity.AddVector(Acceleration)
		Position.AddVector(Velocity)
		
		Collision()

		If LastCollider
			Local BounceAngle:Float = SeperationVector.Angle()
			Local BounceLength:Float = Velocity.length()
			Local BounceVector:TVector2 = New TVector2
			BounceVector.x = Cos(BounceAngle) * BounceLength
			BounceVector.Y = Sin(BounceAngle) * BounceLength				
			BounceVector.Mult(COLL_BOUNCE)

			Velocity.Mult(COLL_FRICTION)		
			Velocity.AddVector(BounceVector)

			Position.AddVector(SeperationVector)
			SeperationVector.Set(0,0)
		End If
	End Method

End Type

Type TVector2
	Field X:Float, Y:Float
	Function Create:TVector2 (_X:Float = 0, _Y:Float = 0)
		Local _V:TVector2 = New TVector2
		_V.X = _X
		_V.Y = _Y
		Return _V
	End Function   
	Method Set (_X:Float, _Y:Float)
		X  =  _X
		Y  =  _Y
	End Method
	Method AddVector (_V:TVector2)
		X :+ _V.X
		Y :+ _V.Y
	End Method
	Method Mult (_M:Float)
		X :* _M
		Y :* _M
	End Method
	Method length:Float ()
		Return sqr(X * X + Y * Y)
	End Method
	Method Angle:Float ()
		Return ATan2 (Y, X)
	EndMethod
End Type

Local CO:TCollisionObject = TCollisionObject.CreateCircle(Null,COLL_DYNAMIC,25,100,100)  

For Local I:Int = 1 to 10
	TCollisionObject.CreateCircle(Null,COLL_STATIC,Rnd(10,50),Rnd(0,640),Rnd(100,380))
Next

Graphics 640,480,0

While not KeyHit(KEY_ESCAPE)
	Cls

	CO.Acceleration.x = (KeyDown(KEY_RIGHT) - KeyDown(KEY_LEFT))*.08
	CO.Acceleration.Y = (KeyDown(KEY_DOWN) - KeyDown(KEY_UP))*.08
	
	If MouseDown(1)
		CO.Position.Set(MouseX(),MouseY())
		CO.Velocity.Set(0,0)
	End If
	               
	For Local CollisionObject:TCollisionObject = EachIn CollisionObjectList
		CollisionObject.Update
		CollisionObject.Render
	Next

	Flip
	FlushMem
Wend


Altitudems, this is not off topic at all, it is really good. Will be used.

This is cool. With the circle code and our line2D code combined we already have all physics we would need for a pinball game.

Awesome :)

I wish I was less busy so I could even get a chance to try the examples out above.

I'm very busy just now trying to finish of a couple of projects, but hopefully I'll have some time at some stage in the run up to Christmas (I hope!).

In the meantime I'll keep an eye on this thread for info.


IPete2.

Good to hear ;)

I'll soon make a fresh thread and start he project for real. I think we should have the project work threads in Moudle/Tweaks forum instead.


This does not seem to work, I'm trying to get the line normal, Method lies in Type Line2D:

Method CalculateNormal()
'Both these ways should work (WARPY)
'But none of them do!?

' Local Angle# = ATan2( X, Y )
' Normal.X = Cos( Angle + 90 )
' Normal.Y = Sin( Angle + 90 )

'OR

Normal.X = 1
Normal.Y = - X/Y
'Normal.Normalize()
EndMethod



MOST IMPORTANT:

How to handle collisions?
The library will take care of most of the work for the user. The user only needs to create som eCollisionplanes, fill them with objects and then set the collisionresponse for each plane against each other plane. In other words this determines how the Shots collides with walls, how they collide with Ships or ships with sheilds. The result would be that a Plane for each response type will be required. One object is recommended to only be in one plane.

Example code not runnable (See the idea)
Type Line2D

	Method CircleCollide( Circle:Circle2D ) 'Line or Vector vs Circle
		
		
		'All calculations is done here
		'Check is they collide
		If Collide Then Return True	
		
		
		'Most times we want to know more than that they just collided:
		
		'The intersection point
		'The reflecting vector

		'This is optional and is done after we know they collided
		
		'All data of the collision needs To be accesible
		'to further functions that deals with collision response
			
	EndMethod

	Method Collision_GetIntersection( X Var , Y Var)
		'.....
	EndMethod

	Method Collision_GetSeparationVector:Vector2D()
		'.....
		'Usually you use this to alter you position back - so that you do not collide
		'Then depending on elasticy and friction we alter the response.
	EndMethod

EndType

Type MaxPhysicsObject

	Method Collision_ApplyResponse()
		'Alters your speed and your location after a collision
	EndMethod
	
EndType


Type Circle2D Extends MaxPhysicsObject

	Method LineCollide( Line:Line2D ) 'Circle vs Line
		
		Line.CollideCircle( Self )'Call the actuall Line vs Circle method which lies in Line2D
						
	EndMethod
	
EndType


How is this?
Strict

'List of collision objects
Global CollisionObjectList:TList = CreateList()

'Define collision response types
Const COLLISION_STATIC:Int = 0
Const COLLISION_DYNAMIC:Int = 1

'Our base collision object
Type TCollisionObject
	Field ResponseType:Int
	
	Field Position:TVector2
	Field Velocity:TVector2
	Field Acceleration:TVector2
	
	Field LastColliders:TList
	Field LastSeperationVectors:TList
		
	Method New()
		CollisionObjectList.AddLast(Self)
		Position = New TVector2
		Velocity = New TVector2
		Acceleration = New TVector2
		LastColliders = CreateList()
		LastSeperationVectors = CreateList()
	End Method
	
	Method Destroy()
		CollisionObjectList.Remove(Self)
	End Method
	
	Method TestForCollision()		
	End Method
	
	Method Update()	
	End Method
		
End Type

'A type of collision object
Type TCircle2D Extends TCollisionObject
	Method TestForCollision()
		'Test for a collision between each object in list
		For Local Collider:TCollisionObject = EachIn CollisionObjectList
			'Make shure not to check collisions with self
			If Collider <> Self
				'Check for collision based the the type of object
				If TCircle2D(Collider)
					'Test for collision
					'If objects collide
					If CollisionIsFound
						'Add this collider to the collider list
						LastColliders.AddLast(Collider)
						'Find the seperation vector
						Local SeperationVector:TVector2 '= Shortest Path to Seperate Objects
						'and add it to the list 
						LastSeperationVectors.AddLast(SeperationVector)
					End If
				End If
				'Repeat for each type of object
			End If
		Next
	End Method

	Method Update()
		Velocity.AddVector(Acceleration)
		Position.AddVector(Velocity)
		
		TestForCollision
        
        'Convert lists to arrays to avoid miss linkage
        '(there may be a better way)
		Local ColliderArray:TCollisionObject[] = LastColliders.ToArray()
		Local SepVectorArray:TVector2[] = LastSeperationVectors.ToArray()

		For Local I:Int = EachIn ColliderArray
			'Do collision response / seperate objects
			Select ResponseType
				'We are static (won't move)
				Case COLLISION_STATIC
					'Collider is dynamic and will move
					If ColliderArray[I].Response = COLLISION_DYNAMIC
						'Seperate obects by moving collider along seperation vector
						ColliderArray[I].Position.X :- SepVectorArray[I].X
						ColliderArray[I].Position.Y :- SepVectorArray[I].Y
					End If
				'We are dynamic and will move
				Case COLLISION_DYNAMIC
					Select ColliderArray[I].Response
						'Collider is dynamic and will move
						Case COLLISION_DYNAMIC
							'Both objects are dynamic so
							'seperate them by moving them equaly
							Position.X :+ SepVectorArray[I].X *.5
							Position.Y :+ SepVectorArray[I].Y *.5
							ColliderArray[I].X :- SepVectorArray[I].X *.5
							ColliderArray[I].Y :- SepVectorArray[I].Y *.5
						'Collider is static (won't move)
						Case COLLISION_STATIC
							'Seperate obects by moving us along seperation vector
							Position.X :+ SepVectorArray[I].X
							Position.Y :+ SepVectorArray[I].Y
					End Select
			End Select
			'Clear our lists
			LastColliders.Clear
			LastSeperationVectors.Clear
		Next
	End Method
End Type


Do you think we could eliminate a lot of work/confusion and start by porting over the PollyColly code previously mentioned?

Altitudems, yes that is a very good suggestion, Actually I was playing around with your circle demo in a similar fashion.

This is with planes (I will add more later) :

Strict

'List of collision objects
Global CollisionObjectList:TList = CreateList()

'Define collision response types
Const COLLISION_STATIC:Int = 0
Const COLLISION_DYNAMIC:Int = 1

'Our base collision object
Type TCollisionObject
	Field ResponseType:Int
	
	Field Shape:TShape
	
	Field Position:TVector2
	Field Velocity:TVector2
	Field Acceleration:TVector2
	
	Field LastColliders:TList
	Field LastSeperationVectors:TList
		
	Method New()
		CollisionObjectList.AddLast(Self)
		Position = New TVector2
		Velocity = New TVector2
		Acceleration = New TVector2
		LastColliders = CreateList()
		LastSeperationVectors = CreateList()
	End Method
	
	Method Destroy()
		CollisionObjectList.Remove(Self)
	End Method
	
	Method TestForCollision()		
	End Method

	Method Update()
		Velocity.AddVector(Acceleration)
		Position.AddVector(Velocity)
	End Method
	
	Method Response( Collider:TCollisionObject )
	' Check collision response
	'1. Circle vs Circle
	'2. Line vs Line
	'3. Circle vs Line
	'4. Polygon... 5,6
		Select Self
			
			Case Circle2D(Self)
			
				Select Shape
					Case Circle2D(Collider)
						CircleReponse()'In this case Circle vs Circle Only
					Case Line2D(Collider)	
						LineReponse()
				EndSelect
				
			Case Line2D(Collider)
				
				Select Shape
					Case Circle2D(Collider)
						CircleReponse()
					Case Line2D(Collider)	
						LineReponse()
				EndSelect		
			
		EndSelect	

	EndMethod
	
	
	Method CircleResponse()
        'Convert lists to arrays to avoid miss linkage
        '(there may be a better way)
		Local ColliderArray:TCollisionObject[] = LastColliders.ToArray()
		Local SepVectorArray:TVector2[] = LastSeperationVectors.ToArray()

		For Local I:Int = EachIn ColliderArray
			'Do collision response / seperate objects
			Select ResponseType
				'We are static (won't move)
				Case COLLISION_STATIC
					'Collider is dynamic and will move
					If ColliderArray[I].Response = COLLISION_DYNAMIC
						'Seperate obects by moving collider along seperation vector
						ColliderArray[I].Position.X :- SepVectorArray[I].X
						ColliderArray[I].Position.Y :- SepVectorArray[I].Y
					End If
				'We are dynamic and will move
				Case COLLISION_DYNAMIC
					Select ColliderArray[I].Response
						'Collider is dynamic and will move
						Case COLLISION_DYNAMIC
							'Both objects are dynamic so
							'seperate them by moving them equaly
							Position.X :+ SepVectorArray[I].X *.5
							Position.Y :+ SepVectorArray[I].Y *.5
							ColliderArray[I].X :- SepVectorArray[I].X *.5
							ColliderArray[I].Y :- SepVectorArray[I].Y *.5
						'Collider is static (won't move)
						Case COLLISION_STATIC
							'Seperate obects by moving us along seperation vector
							Position.X :+ SepVectorArray[I].X
							Position.Y :+ SepVectorArray[I].Y
					End Select
			End Select
			'Clear our lists
			LastColliders.Clear
			LastSeperationVectors.Clear
		Next
	EndMethod
	
End Type


'The user type
Type TTank Extends TCollisionObject

	Field Weapon = 2

	Method New()
		Shape = New TCircle2D
	EndMethod
		
EndType

	Local Tank:TTank = New Tank
	Local Tank2:TTank = New Tank	
	Const TANK_PLANE = 1 'Collision Plane for Tanks
	Const WALL_PLANE = 2 'Collision Plane for Walls	
		
	Tank.AddToPlane( TANK_PLANE )
	Tank2.AddToPlane( TANK_PLANE )	

	Local WallA:TWall = New TWall
	Local WallB:TWall = New TWall
	Local WallC:TWall = New TWall
	Local WallD:TWall = New TWall			

	'Another way to add objects
	AddPhysicsObjectToPlane( [WallA,WallB,WallC,WallD], WALL_PLANE )

	'Or we could do it like this:
	'Will add ever Wall created so far to the WallPlane (id = 2) or plane 2
	AddPhysicsObjectToPlane( Wall.List.ToArray[], WALL_PLANE )
	
	SetDynamicPlane( TankPlane )'All Tanks will bounce and slide
	SetStaticPlane( WallPlane )	'All Walls can't move
		
	While '---
	
		'Only checks if it collides
		'See WallPlane and TankPlane as Lists with objects
		If Collision( [WallPlane,TankPlane] ) 
		'Runs the Collison method in every object
		'First selects which shape the object has then
		'it check for collision
		'So it doesn't matter if our tank is a circle or a line or a polygon
		
			Print "Collided"
			For Local Tank:TTank = EachIn CollisionList 'All Tanks that collided
				
				Tank.Armor:-1
				If Tank.SheildActivated = True
					Tank.Elasticy = 1
					Tank.Friction = 0
				Else
					Tank.Elasticy = 0
					Tank.Friction = 0.5					
				EndIf
							
				Tank.Response()'The Tank is Dynamic so this alters velocity and position		
									
			Next
			For Local Wall:Twall = EachIn  CollisionList 'All Walls that collided
				'Something like this
				Local PositionOfImpact:Vector2d = Wall.GetImpactLocation()
				CreateExplosionAt( PositionOfImpact , ExplosionType("Nuclear")  )
			Next
		EndIf
			
	Wend'----
	

'A type of collision object
Type TCircle2D
	Method CollideCircle()
		'Test for a collision between each object in list
		For Local Collider:TCollisionObject = EachIn CollisionObjectList
			'Make sure not to check collisions with self
			If Collider <> Self
				'Check for collision based the the type of object
				If TCircle2D(Collider)
					'Test for collision
					'If objects collide
					If CollisionIsFound
						'Add this collider to the collider list
						LastColliders.AddLast(Collider)
						'Find the seperation vector
						Local SeperationVector:TVector2 '= Shortest Path to Seperate Objects
						'and add it to the list 
						LastSeperationVectors.AddLast(SeperationVector)
					End If
				End If
				'Repeat for each type of object
			End If
		Next
	End Method
End Type


I think we should separate shapes and Collison objects. Because you might want to check a circle against a line without having the circle being an actuall object, for example the mouse pointer. Anyway it feels more flexible if any object can have any shape! And there is no problem changing the shape while we run the game :)

See the above code (based upon yours). What do you think?
Please add/change/suggest more. I'm open to anything.


Do you think we could eliminate a lot of work/confusion and start by porting over the PollyColly code previously mentioned?

Indeed. That would be a super start. Do you know C++?

I mean I have never manage to successfully add rotation and torque to a game. And the polly code demos is so damn cool. Converting it would save a lot of head acke, if I knew C++ I would alread have started that.

I found a problem in the Line2d I posted above to the function createParallel and I fixed it.(I Edited the post)

This may help for the circle Line collision case
(I found it in the codearchives)
Function MinDistPointLine#(px#,py#,x1#,y1#,x2#,y2#)

	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


I still trying to find out a way to handle poly poly collision but sadly with no luck. I will still searching.
No luck to the convertion of methods in polycolly.(I just losted the game in the first tutorial shame on me)
I found an nPoly lib maded for blitz in the showcase it even have it's entry to the number 9 of the Blitznews.
Here is the post : http://www.blitzmax.com/Community/posts.php?topic=36003&hl=npoly
but you will find out that we cannot take it and look throu it. The code of nPoly may solve some of the problems right now.
After all this concept it's a really good learning curve for me and I am glad thinking that I am part of it.

Edit: And another think to have the poly poly collision we must find a way to imliment this method : http://gpwiki.org/index.php/Polygon_Collision
This is the fastest and the mostly used.

Edit: My fault. This was not good enought. I will posted again if it will work as it must work. Sorry about that I will make more tests before posting.

@Wave
I am only slightly familiar with c++, I just look up what I don't understand. I have allready started converting some of the code from PollyColly. Here is what I have so far:

Vector.bmx : Ported From Vector.h
Const Two_Pi:Float = 2 * Pi
Const Rad_k:Float = 180.0 / Pi

Function Sign:Float (X:Float)
	If (X < 0.0) Then  Return -1.0 Else Return 1.0
End Function

Function Swap (A:Float Var, B:Float Var)
	Local C:Float = A
	A = B
	B = C
End Function

Function RadiansToDegrees:Float(Rad:Float)
	Local K:Float = 180.0 / Pi
	Return Rad * K
End Function

Function DegreesToRadians:Float(Deg:Float)
	Local K:Float = Pi / 180.0
	Return Deg * K
End Function

Function NewVector:TVector2(_X:Float = 0, _Y:Float = 0)
	Local V:TVector2 = New TVector2
	V.X = _X
	V.Y = _Y
	Return V
End Function

Type TVector2
	Field X:Float
	Field Y:Float

	Function Create:TVector2(_X:Float, _Y:Float)
		Local V:TVector2 = New TVector2
		V.X = _X
		V.Y = _Y
		Return V
	End Function
	
	Method Clone:TVector2 ()
		Local V:TVector2 = New TVector2
		V.X = X
		V.Y = Y
		Return V
	End Method
	
	Method Set (_X:Float = 0, _Y:Float = 0)
		X = _X
		Y = _Y
	End Method
	
	Method Div:TVector2 (Scalar:Float)
		Local V:TVector2 = Self.Clone()
		V.X :/ Scalar
		V.Y :/ Scalar
		Return V
	End Method

	Method Mult:TVector2 (Scalar:Float)
		Local V:TVector2 = Clone()
		V.X :* Scalar
		V.Y :* Scalar
		Return V
	End Method
	
	Method Add:TVector2 (_X:Float, _Y:Float)
		Local V:TVector2 = Clone()
		V.X :+ _X
		V.Y :+ _Y
		Return V
	End Method

	Method Sub:TVector2 (_X:Float, _Y:Float)
		Local V:TVector2 = Clone()
		V.X :- _X
		V.Y :- _Y
		Return V
	End Method

	Method AddVector:TVector2 (_V:TVector2)
		Local V:TVector2 = Clone()
		V.X :+ _V.X
		V.Y :+ _V.Y
		Return V
	End Method
	
	Method SubVector:TVector2 (_V:TVector2)
		Local V:TVector2 = Clone()
		V.X :- _V.X
		V.Y :- _V.Y
		Return V
	End Method
	
	Method Cross:Float (_V:TVector2)
		Return (X * _V.Y) - (Y * _V.X)
	End Method

	Method Dot:Float (_V:TVector2)
		Return (X * _V.X) + (Y * _V.Y)
	End Method

	Method Reverse:TVector2 ()
		Local _V:TVector2 = Clone()
		_V.X = -_V.X
		_V.Y = -_V.Y
		Return _V
	End Method
	
	Method Length:Float ()
		Return Sqr(X * X + Y * Y)
	End Method
	
	Method Normalise:TVector2 ()
		Local _V:TVector2 = Clone()
		Local _L:Float = _V.Length()
		If (_L = 0.0) Return Null
		_V = _V.Mult(1.0 / _L)
		Return _V
	End Method
	
	Method Direction:TVector2 ()
		Local _V:TVector2 = Clone()
		_V.Normalise()
		Return _V
	End Method
	
	Method Angle:Float(_V:TVector2)
		Local Dot:Float = Dot(_V)
		Local Cross:Float = Cross(_V)
		
		'angle between segments
		Local Angle:Float = Float(ATan2(Cross, Dot))

		Return Angle
	End Method

	Method Rotate:TVector2 (_Angle:Float)
		Local _V:TVector2 = Clone()
		Local _X:Float = _V.X
		_V.X =  _V.X * Cos(_Angle) - _V.Y * Sin(_Angle)
		_V.Y = _X * Sin(_Angle) + _V.Y * Cos(_Angle)
		Return _V
	End Method
	
	Method RotateOnCenter:TVector2 (_Center:TVector2, _Angle:Float)
		Local Diff:TVector2 = Clone().SubVector(_Center)
		Diff.Rotate(_Angle)
		Local _V:TVector2 = Diff.AddVector(_Center)
		Return _V
	End Method

	Method Clamp (_Min:TVector2, _Max:TVector2)
		If (X < _Min.X)
			X = _Min.X
		ElseIf (X > _Max.X)
			X = _Max.X
		End If
		If (Y < _Min.y)
			Y = _Min.Y
		ElseIf (Y > _Max.Y)
			Y = _Max.Y
		End If
	End Method

	Method Randomise(_Min:TVector2, _Max:TVector2)
		X = RndFloat() * (_Max.X - _Min.X) + _Min.X
		Y = RndFloat() * (_Max.Y - _Min.Y) + _Min.Y
	End Method

	Method Render(_X:Float, _Y:Float)
		DrawLine _X,_Y,_X + X,_Y + Y
	End Method
End Type

I'll post more soon.

Aside from the pollycolly code I posted a working polygon collision lib a while back.

http://www.blitzbasic.com/Community/posts.php?topic=46332

That vector part you converted has a lot of functions we don't have in our Vector2D, so great job. Now our vector library base is very solid. I'm looking forward to see more.

I'll add that vector lib to our Vector2D tomorrow and altitudems, you have to promise you use the main vector2D library, when/if you manage to convert more of the pollycode.

Haramanai, good job on the VectorLib. I'll combine it all in the Vector2D and start a new threat for the project tomorrow.

Meanwhile we need to decide on how it should work for the end user and also how we are going to split up the code in several files/types so that it get's both modular; easy to build on in the future and that we finilize the core; so that we can start making a simple tutorial /w examples.

Remember the end goal is something like the polly code. I'm also writing a tutorial for newcomers.

Don't forget we need any fancy vector example anyone could have. My idea is to combine several demos into one big fat demo.

you have to promise you use the main vector2D library

I won't promise you that, because if I did it would make the conversion much harder. The vector lib I posted is a strait line for line conversion of the PollyColly code. Once we have the PollyColly code completely converted then we can think about adding/modifing the vector lib.

My post above was not good and I edited.
altitudems good job with polygons.

@Altitudems. You are right. Better to get it working first.

I'll try to structure our project a bit and finaly create some new threads.

Is there a way to fill and texture a polygon? vertices?

Textured polys

I can't find the main loop in PollyCode..

If C++ is anything like java then this is the start of the program:


void main(int argc, char** argv)
{
	//--------------------------------------------------------------------------
	// OpenGL / GLUT init
	//--------------------------------------------------------------------------
    glutInit( &argc, argv );
	glutInitDisplayMode		(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	
	glutInitWindowSize		(width, height);
	glutInitWindowPosition	(0, 0);
	glutCreateWindow		("Tutorial 2 - Extending the method of separating axis for collision response");
	
	glPointSize(3.0f);
	glEnable				(GL_BLEND);
	glBlendFunc				(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable				(GL_DEPTH_TEST);
	glDisable				(GL_LIGHTING);
	
	glutDisplayFunc			(Display);
	glutReshapeFunc			(Reshape);
//	glutIdleFunc			(Idle);
	glutTimerFunc			(0, Timer, (int) 100.0f / 60.0f);
	glutPassiveMotionFunc	(PassiveMotion);
	glutMouseFunc			(Mouse);
	glutMotionFunc			(Motion);
	glutKeyboardFunc		(Keyboard);
	glutSpecialFunc			(ExtKeyboard);

	Init					();
	glutMainLoop			();
}



glutMainLoop(); // I this is it.. But where does this function call go? What file? What function? The dll?

EDIT
Tony, thanks. A nice addition to the physics lib would be a method that draws the polygon with textures. "at the moment it uses trianglefans" - Does that mean the textures will break if not perfect squares or triangles?

take a look at this : http://www.aidspan.org/alec/physical/index.htm

Physical is a game creation system based on the foundation of an innovative 2D physics engine. Its main features include:

* Incorporated functionality for graphics, keyboard handling, and game flow

* A framework that provides a direct mapping from game design to game programming

* Interchangeable, reusable parts

o Interactive game elements from any game can be used in any other game

o This includes reusing not just model and image files, but the actual dynamics that make a plane fly or a gun shoot

o This allows for the creation of a common library of freely downloadable game elements: the Repository

* An included object editor

* A new kind of physics engine that naturally handles object deformation - things can bend, break, flow, and explode

@wave
i think it is a call to a libary function - it says - requirements : GLUT library, OpenGL support.

EDIT: try This

Sergio Thanks! Great link will help a lot in organizing and setting up our engine.


@Diablo
Ok now I get it. The Glut library uses some Callback Registration Philosophy. And what you do before the mainloop function is to thell Glutt the names (pointers?) of the functions you are useing as display/update and so on.

Thread continued right here

@Shagwana
Can I have the project in Module Tweak forum instead?
It's going to be ~5 topics

And as of the moment it is created it is going to stay open to modification/tweaks from anyone.

5 topics?

My thinking is that all these community projects should be in the same place (so thats why its over there near fmod one!)

I will have one here to enlist people and tell them about the project (Link to the main topic): It should be a Locked topic.

Then in module tweaks I have all the "work" topics

One for each part:
Structure and News (Overall Suggestions)
Examples and Demos (For testing)
Completed Parts (The most up to date code)
Working Parts ( including each of the types:
Vector2D
Line2D
Polygon2D
Circle2D
PhysicsObject )

That makes up for five topics in total, one here and four in Tweaks.

Or can we have whole new forum? (for community projects)

To clearify
The "Working parts" is the parts we work on: It should be "In progress". This is where everyone adds code (actual work and not ideas). This topic needs to be cleaned up once in a while and the result will be in the "Completed Parts" topic.

The idea and benifit with this system is that newcommers will have an easy time. They will see what the project is about. Whan they can do and what need to be done. They can also see what is already done. All without the need to read through 100's of long posts.

Well i dont wish to be cluttering up the sticky area of the forum with multipul threads on the same topic. So please put links in your sticky one to the relative threads you have planned.

You sure you need 5 threads to do what you want?. Fmod managed it all with 1 thread!.

Fmod managed it all with 1 thread!.

Yes, but is it worth the cost? See this thread. We haven't even started the project and even on my connection the page takes several seconds to load. And no sane person would read through everything so that they are up-to-date. How are the FMod project going by the way?
To be honest I don't know how they manage, perhaps their project is smaller/simpler?

Can you move my "MaxPhysics Community Project : Main" topic back to the Tweak forum and I will create a new one here as I planned from the start. I do think that is the best way to do it, but I'm always open for suggestions.

EDIT
I'll use the current main, no problem. But I will create the rest of the topics I "need" in the tweak forum if that is ok.

@wave
Dont know if this will help you. its some help functions and types to draw textured polygons (doesn't work with directX at the mo)

DrawPolly

You will need to have done this first tho (and added the openGl code) (thx tonyg - didn't know about this cool code)

Nice, is there a way to tile or cut the texture instead of scaling or distorting it? In case you want to make a poly map for example.