2D Physics: Ideas for a Community Project

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

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

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