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.

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