Physics engine

Blitz3D Forums/Blitz3D Beginners Area/Physics engine

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.

I have started on a new verlet physics engine myself,... I'm about to move things into 3d right now, but here is my 2d verlets for dummies code. Note: This is based on some code from the code archives, so some things may look similar to those. When I am trying to learn something new I strip it down to the very bare essentials and start building up to where I need it. This is about as basic as I can get it.

The next phase will involve getting collisions working between different objects. There are a few extra lines of code in here dealing with the collision code I have already started on.

Edit: see my following posts for a version with collisions, and a full 3d version as well.

Global screen_w = 640
Global screen_h = 480
Global gravity# = .25

Graphics screen_w,screen_h,0,2
SetBuffer BackBuffer()

;SeedRnd MilliSecs()
timer = CreateTimer (60) ; lock game fps to this

Type vector2
	Field x#
	Field y#
End Type

Type Verlet
	Field pos.vector2	; verlet position
	Field vel.vector2	; verlet velocity
	Field old.vector2 ; store the previous pos here
	Field radius ; size of verlet
	Field id ;use to identify groups
	Field collide ; is this colliding?
End Type

Type constraint
	Field p1.verlet
	Field p2.verlet
	Field length#
End Type 

Global circle=CreateImage (40,40)
Global circlehit=CreateImage (40,40)
initCircleGFX() ;create circle graphics

;For loop = 1 To 10
	definebox() ;create verlet box
;Next

;CreateVerlet.verlet (xpos,ypos,size,id)
Global v1.verlet = CreateVerlet (400,100,20,1)
Global v2.verlet = CreateVerlet(400,150,20,1)
Global v3.verlet = CreateVerlet (500,100,20,1)
Global v4.verlet = CreateVerlet(500,150,20,1)
ConstrainVerlet (v1,v2)
ConstrainVerlet(v2,v3)
ConstrainVerlet(v1,v3)
ConstrainVerlet(v1,v4)
ConstrainVerlet(v2,v4)
ConstrainVerlet(v3,v4)

While Not KeyHit(1)
	WaitTimer(Timer) ; Pause until the timer reaches 60 (caps the game framerate on faster systems)

	UpdateVerlets()
	UpdateConstraints()

	; move verlet 1 based on arrow keys
	v1\pos\y =	v1\pos\y + (KeyDown(208) - KeyDown(200) )*2
	v1\pos\x =	v1\pos\x + (KeyDown(205) - KeyDown(203) )*2

	If KeyHit(57)
		For v.verlet = Each verlet
			v\pos\y = v\pos\y - Rnd(1,20)
			v\pos\x = v\pos\x + Rnd(-5,5)
		Next
	EndIf 

	drawscreen()


	Flip()
	Cls()
Wend

End 

Function initCircleGFX()
	SetBuffer ImageBuffer(circle)
	Color 128,128,128
	Oval 0,0,40,40
	Color 0,255,0
	Oval 0,0,40,40,0
	MidHandle circle
	
	SetBuffer ImageBuffer(circlehit)
	Color 255,0,0
	Oval 0,0,40,40
	MidHandle circlehit
	SetBuffer BackBuffer()

	Color 255,255,255
End Function 

Function definebox()
	; define the shape and constraints
	;CreateVerlet.verlet (xpos,ypos,size,id)
	v1.verlet = CreateVerlet.verlet (100,100,20,num)
	v2.verlet = CreateVerlet.verlet (150,100,20,num)
	v3.verlet = CreateVerlet.verlet (100,150,20,num)
	v4.verlet = CreateVerlet.verlet (150,150,20,num)
	v5.verlet = CreateVerlet.verlet (100,200,20,num)
	v6.verlet = CreateVerlet.verlet (150,200,20,num)

	c.constraint = 	ConstrainVerlet	(v1,v2)
	c.constraint = 	ConstrainVerlet	(v2,v4)
	c.constraint = 	ConstrainVerlet	(v3,v4)
	c.constraint = 	ConstrainVerlet	(v3,v1)
	c.constraint = 	ConstrainVerlet	(v6,v1)
	c.constraint = 	ConstrainVerlet	(v2,v5)
	c.constraint = 	ConstrainVerlet	(v4,v6)
	c.constraint = 	ConstrainVerlet	(v5,v6)
	c.constraint = 	ConstrainVerlet	(v3,v5)
	c.constraint = 	ConstrainVerlet	(v3,v6)
	c.constraint = 	ConstrainVerlet	(v4,v1)

End Function

Function CreateVerlet.verlet (xpos,ypos,size,id)
	v.verlet=New verlet
	v\pos = New vector2
	v\pos\x = xpos
	v\pos\y = ypos
	v\vel = New vector2
	v\vel\x = 0
	v\vel\y = 0
	v\old = New vector2
	v\old\x = xpos
	v\old\y = ypos
	v\radius = size
	v\id = num

	Return v
End Function 

Function ConstrainVerlet.constraint (head.verlet,	tail.verlet)
	Local dx#,dy#

	;this creates a new constraint and sets the length equal to the current distance between the verlets
	c.constraint = New constraint
	c\p1.verlet = head.verlet
	c\p2.verlet = tail.verlet

	dx = c\p1\pos\x - c\p2\pos\x
	dy = c\p1\pos\y - c\p2\pos\y
	c\length = Sqr ( dx*dx + dy*dy )

	;DebugLog c\length
	Return c
End Function

Function UpdateVerlets()
	Local tx#,ty#
	For v.verlet = Each verlet
		v\collide = False
		v\vel\x = (v\pos\x - v\old\x)*.985 ; Get the velocities of the verlet,...add a bit of decay to simulate friction
		v\vel\y = (v\pos\y - v\old\y)*.985

		v\old\x = v\pos\x ; store position in "old"
		v\old\y = v\pos\y

		v\pos\x = v\pos\x + v\vel\x ;store new postion based on velocity
		v\pos\y = v\pos\y + v\vel\y + gravity

		;check screen bounds
		If v\pos\x	>	screen_w - v\radius
			v\pos\x=screen_w - v\radius
			v\collide = True
		ElseIf v\pos\x	<	v\radius
			v\pos\x	=	v\radius
			v\collide = True
		EndIf
		If v\pos\y	>	screen_h - v\radius
			v\pos\y=screen_h - v\radius
			v\collide = True
		ElseIf v\pos\y	<	v\radius
			v\pos\y=	v\radius
			v\collide = True
		EndIf
	Next
End Function

Function UpdateConstraints()
	Local dx#,dy#,length#,diff#;,nx#,ny#,tx#,ty#

	For loop = 1 To 5 ;iterations
		For c.constraint = Each constraint
			dx=c\p2\pos\x	-	c\p1\pos\x
			dy=c\p2\pos\y	-	c\p1\pos\y
					
			length=Sqr(dx*dx+dy*dy) ; distance between p1 and p2
	
			If length<>0 ;avoid divide by 0, then normalize the vector
				diff = (length - c\length) / length ; vector length minus constraint length
			EndIf
	
			dx = dx * .5 ;find the midpoint
			dy = dy * .5
	
			c\p1\pos\x = c\p1\pos\x + diff * dx 
			c\p1\pos\y = c\p1\pos\y + diff * dy
	
			c\p2\pos\x = c\p2\pos\x - diff * dx
			c\p2\pos\y = c\p2\pos\y - diff * dy

		Next  ;constraints
	Next ;iterations
End Function 

Function DrawScreen()
	For v.verlet=Each verlet
		If v\collide = False
			DrawImage circle,v\pos\x,v\pos\y	; draw circle
			;Oval v\pos\x-v\radius,v\pos\y-v\radius,v\radius*2,v\radius*2,0 ;draw the actual radius (slow)
		Else
			DrawImage circlehit,v\pos\x,v\pos\y	; draw red circle if colliding
		EndIf		
	Next

	For c.constraint = Each constraint
		Line c\p1\pos\x,c\p1\pos\y,c\p2\pos\x,c\p2\pos\y
	Next 

	Text 10,10,"Use arrow keys to move V1, space bar for earthquake"
	Text v1\pos\x,v1\pos\y,"V1"
End Function