first project.. verlet physics

BlitzMax Forums/BlitzMax Beginners Area/first project.. verlet physics

Hi I am doing a small verlet physics engine as my first project in Bmax to get me used to doing types and lists and just about every part of blitz max that I dont really understand fully.. well now I think I understand it. :)

I wrote the following code in about 30 minutes after buying bmax but I have a few questions and weird happenings...

controls.. spacebar = add object
arrow keys to control verlet #2

Graphics 800,600,0,60
AppTitle = "Verlet PhysX"


Global Verletlist:TList = New TList 'Verlet List
Global ConstraintList:TList = New TList 'Constraint List

Const Friction:Float = .985		'Friction should be close to 1 unless you want very slow movement
Const Gravity:Float = .1			'Gravity
Const Waterlevel:Int = 400		'Waterlevel in pixels
Const Waterdensity:Float = 10		'The depth at wich boyancy maxes out
Const BoyancyForce:Float = .1		'Best if close to gravity
Const WaterFriction:Float = .01	'Needs to be really low for a very subtle effect
Const ConstraintIterations:Int = 10	'constraint iterations



v1:verlet = Verlet.Create(100,100,21,10,1)' x, y, size, mass, ID, ox offset, oy offset
v2:verlet = Verlet.Create(200,150,11,1,1)' x, y, size, mass, ID, ox offset, oy offset
v3:verlet = Verlet.Create(200,100,11,1,1)' x, y, size, mass, ID, ox offset, oy offset
v4:verlet = Verlet.Create(100,150,21,10,1)' x, y, size, mass, ID, ox offset, oy offset

Constraint.Create(v1:verlet,v2:verlet)	'Verlet1 and verlet2
Constraint.Create(v1:verlet,v3:verlet)
Constraint.Create(v3:verlet,v2:verlet)
Constraint.Create(v1:verlet,v4:verlet)
Constraint.Create(v4:verlet,v2:verlet)

v5:verlet = Verlet.Create(300,100,21,10,2)' x, y, size, mass, ID, ox offset, oy offset
v6:verlet = Verlet.Create(400,150,11,1,2)' x, y, size, mass, ID, ox offset, oy offset
v7:verlet = Verlet.Create(400,100,11,1,2)' x, y, size, mass, ID, ox offset, oy offset
v8:verlet = Verlet.Create(300,150,21,10,2)' x, y, size, mass, ID, ox offset, oy offset

Constraint.Create(v5:verlet,v6:verlet)	'Verlet1 and verlet2
Constraint.Create(v5:verlet,v7:verlet)
Constraint.Create(v7:verlet,v6:verlet)
Constraint.Create(v5:verlet,v8:verlet)
Constraint.Create(v8:verlet,v6:verlet)

Function createtriverl(x#,y#,siz#,mass#,id)

	v1:verlet = Verlet.Create(x,y,siz,mass,id)' x, y, size, mass, ID, ox offset, oy offset
	v2:verlet = Verlet.Create(x+siz,y+Rnd(-20,20)+siz,siz,mass,id)' x, y, size, mass, ID, ox offset, oy offset
	v3:verlet = Verlet.Create(x-siz,y+Rnd(-20,20)+siz,siz,mass,id)' x, y, size, mass, ID, ox offset, oy offset
	
	constraint.Create(v1:verlet,v2:verlet)
	constraint.Create(v2:verlet,v3:verlet)
	constraint.Create(v3:verlet,v1:verlet)


End Function
phybodycnt = 2

While Not KeyDown(Key_Escape)
Cls

If KeyHit(key_space) Then
	phybodycnt = phybodycnt + 1
	createtriverl(Rnd(600)+100,-100,Rnd(5,30),Rnd(.1,20),phybodycnt)
EndIf

If KeyDown(key_right) Then
	v2.ox = v2.ox - .7
EndIf
If KeyDown(key_left) Then
	v2.ox = v2.ox + .7
EndIf

If KeyDown(key_up) Then
	v2.oy = v2.oy + .7
EndIf
If KeyDown(key_down) Then
	v2.oy = v2.oy - .7
EndIf


SetAlpha .5
SetColor 0,0,255

DrawRect 0,waterlevel,800,480		'Temporary.. draws the waterline

SetColor 255,255,255
SetAlpha 1

UpdateVerlets()
UpdateConstraints()

Flip
Wend


Type Constraint
	
	Field v1:Verlet
	Field v2:Verlet
	Field Length:Float
	Field Elasticity:Float
	
	Function Create:Constraint(v1:Verlet, v2:Verlet, Length:Float = -1)
		
		CC:Constraint = New Constraint
		CC.v1:Verlet = v1:Verlet
		CC.v2:Verlet = v2:verlet
		If length < 0 Then
			CC.Length = Sqr( (v1.x - v2.x)^2 + (v1.y - v2.y)^2 )	'Distance formula for the length
		Else
			CC.Length = Length
		EndIf
		
		CC.Elasticity = 0
		Constraintlist.addlast(CC:Constraint)	'verlet list
				
		Return CC:Constraint
	End Function
	
	
End Type

Function UpdateConstraints()

	For a = 1 To ConstraintIterations
		For c:Constraint = EachIn ConstraintList
			
			totalmass# = c.v1.mass# + c.v2.mass#
			
			v1prop# = (c.v1.mass#/totalmass#) * 2
			v2prop# = (c.v1.mass#/totalmass#) * 2
			
			dx# = c.v1.x - c.v2.x
			dy# = c.v1.y - c.v2.y
			
			length# = Sqr(dx#*dx# + dy#*dy#)
			
			If length# <> 0 Then
				diff# = (length# - c.length) / length#
			Else
				diff# = 0
			EndIf
			
			dx# = dx# * .5
			dy# = dy# * .5
			
			c.v1.x = c.v1.x - (diff# * dx#) * v2prop#
			c.v1.y = c.v1.y - (diff# * dy#) * v2prop#
			
			c.v2.x = c.v2.x + (diff# * dx#) * v1prop#
			c.v2.y = c.v2.y + (diff# * dy#) * v1prop#
			
			DrawLine(c.v1.x,c.v1.y,c.v2.x,c.v2.y)
		Next
	Next

End Function



Type Verlet				'Verlet Type

	Field X!
	Field Y!
	Field OX!
	Field OY!
	Field VX!
	Field VY!
	Field Siz:Float
	Field Collided
	Field ID = 0
	Field mass:Float
	
	Function Create:Verlet(x!,y!,siz:Float,mass:Float,ID,ox! = 0,oy! = 0)
		VV:Verlet = New Verlet
		VV.x! = x!			'verlet x
		VV.y! = y!			'verlet y
		VV.ox! = x! + ox!		'verlet old x
		VV.oy! = y! + oy!		'verlet old y
		VV.siz = siz			'verlet radius
		VV.Collided = False		'collision variable
		VV.ID = ID			'Verlet ID
		VV.mass = mass			'Verlet mass
		VV.vx! = 0			'Verlet velocity x
		VV.vy! = 0			'Verlet velocity y
		Verletlist.addlast(VV:Verlet)	'verlet list
		
		Return VV:Verlet
	End Function
	
End Type

Function UpdateVerlets()
	
	SetScale 1,1	'sets the color rotation alpha scale and blend mode for the verlets
	SetRotation 0
	SetAlpha .5
	SetBlend 3
	SetColor 255,255,255
	For V:Verlet = EachIn VerletList
		
		V.collided = False		'Resets collision variable
		
		If v.y > waterlevel Then	'Detects if verlet is below water for water friction flag
			wfric = True	'water friction flag set to true
		Else
			wfric = False	'water friction flag set to false
		EndIf
		
		v.vx = (v.x - v.ox) * (Friction-(wfric*WaterFriction)) 'Gets velocities of verlets
		v.vy = (v.y - v.oy) * (Friction-(wfric*WaterFriction))
		
		v.ox = v.x 'Updates O values O=old
		v.oy = v.y
		
		v.x = v.x + v.vx			'Keeps track of X velocity
		v.y = v.y + v.vy + Gravity	'Applies Gravity
		
		
		For vv:verlet = EachIn verletlist
			If v <> vv And v.id <> vv.id   ' If Not the same verlet Or group
				dx# = v.x - vv.x
				dy# = v.y - vv.y
				dist# = Sqr ( dx#*dx# + dy#*dy#)		
				totalr# = v.siz# + vv.siz#
				If dist# < totalr# Then
				
					
					Diffx# = ( dist# - totalr# ) * ( dx# / dist# )
					Diffy# = ( dist# - totalr# ) * ( dy# / dist# )

					v.x = v.x - Diffx# '* .5
					v.y = v.y - Diffy# '* .5

					vv.x = vv.x + Diffx# '* .5
					vv.y = vv.y + Diffy# '* .5
				EndIf 				
			EndIf
		Next 


		If v.y > waterlevel Then			'This does water calculations I came up with
			dtmp# = waterlevel-v.y
			If dtmp# > Waterdensity Then
				v.oy = v.oy - (BoyancyForce*(1/v.mass#))
			Else
				v.oy = v.oy - BoyancyForce * (dtmp#/Waterdensity) * (1/v.mass#)
			EndIf
		EndIf
		
		DrawOval V.x-V.siz , V.y-V.siz , V.siz*2 , V.siz*2  'Draws the verlet (temporary)
	Next
	
End Function



I know this is a really general question but I was just wondering if this is what a typical bmax program looks like or am I doing it wrong... well it works so I guess I am doing something right... I cant get strict to work but I dont know if it is really important. build time isnt an issue for me

also.. how is frame limiting controlled in bmax.. I know in the graphics command sets the frame rate but in my program things randomly get choppy and then go back to normal..

sorry for the noobish questions but I have only had bmax for a few days so I can hardly consider myself a pro

Neat demo!

Definitely use SuperStrict. You were just missing some locals and :Int entries. This compiles:

SuperStrict
Graphics 800,600,0,60
AppTitle = "Verlet PhysX"


Global Verletlist:TList = New TList 'Verlet List
Global ConstraintList:TList = New TList 'Constraint List

Const Friction:Float = .985		'Friction should be close to 1 unless you want very slow movement
Const Gravity:Float = .1			'Gravity
Const Waterlevel:Int = 400		'Waterlevel in pixels
Const Waterdensity:Float = 10		'The depth at wich boyancy maxes out
Const BoyancyForce:Float = .1		'Best if close to gravity
Const WaterFriction:Float = .01	'Needs to be really low for a very subtle effect
Const ConstraintIterations:Int = 10	'constraint iterations



Local v1:verlet = Verlet.Create(100,100,21,10,1)' x, y, size, mass, ID, ox offset, oy offset
Local v2:verlet = Verlet.Create(200,150,11,1,1)' x, y, size, mass, ID, ox offset, oy offset
Local v3:verlet = Verlet.Create(200,100,11,1,1)' x, y, size, mass, ID, ox offset, oy offset
Local v4:verlet = Verlet.Create(100,150,21,10,1)' x, y, size, mass, ID, ox offset, oy offset

Constraint.Create(v1:verlet,v2:verlet)	'Verlet1 and verlet2
Constraint.Create(v1:verlet,v3:verlet)
Constraint.Create(v3:verlet,v2:verlet)
Constraint.Create(v1:verlet,v4:verlet)
Constraint.Create(v4:verlet,v2:verlet)

Local v5:verlet = Verlet.Create(300,100,21,10,2)' x, y, size, mass, ID, ox offset, oy offset
Local v6:verlet = Verlet.Create(400,150,11,1,2)' x, y, size, mass, ID, ox offset, oy offset
Local v7:verlet = Verlet.Create(400,100,11,1,2)' x, y, size, mass, ID, ox offset, oy offset
Local v8:verlet = Verlet.Create(300,150,21,10,2)' x, y, size, mass, ID, ox offset, oy offset

Constraint.Create(v5:verlet,v6:verlet)	'Verlet1 and verlet2
Constraint.Create(v5:verlet,v7:verlet)
Constraint.Create(v7:verlet,v6:verlet)
Constraint.Create(v5:verlet,v8:verlet)
Constraint.Create(v8:verlet,v6:verlet)

Function createtriverl(x#,y#,siz#,mass#,id:Int)

	Local v1:verlet = Verlet.Create(x,y,siz,mass,id)' x, y, size, mass, ID, ox offset, oy offset
	Local v2:verlet = Verlet.Create(x+siz,y+Rnd(-20,20)+siz,siz,mass,id)' x, y, size, mass, ID, ox offset, oy offset
	Local v3:verlet = Verlet.Create(x-siz,y+Rnd(-20,20)+siz,siz,mass,id)' x, y, size, mass, ID, ox offset, oy offset
	
	constraint.Create(v1:verlet,v2:verlet)
	constraint.Create(v2:verlet,v3:verlet)
	constraint.Create(v3:verlet,v1:verlet)


End Function
Local phybodycnt:Int = 2

While Not KeyDown(Key_Escape)
	Cls
	
	If KeyHit(key_space) Then
		phybodycnt = phybodycnt + 1
		createtriverl(Rnd(600)+100,-100,Rnd(5,30),Rnd(.1,20),phybodycnt)
	EndIf
	
	If KeyDown(key_right) Then
		v2.ox = v2.ox - .7
	EndIf
	If KeyDown(key_left) Then
		v2.ox = v2.ox + .7
	EndIf
	
	If KeyDown(key_up) Then
		v2.oy = v2.oy + .7
	EndIf
	If KeyDown(key_down) Then
		v2.oy = v2.oy - .7
	EndIf
	
	
	SetAlpha .5
	SetColor 0,0,255
	
	DrawRect 0,waterlevel,800,480		'Temporary.. draws the waterline
	
	SetColor 255,255,255
	SetAlpha 1
	
	UpdateVerlets()
	UpdateConstraints()
	
	Flip 1
Wend


Type Constraint
	
	Field v1:Verlet
	Field v2:Verlet
	Field Length:Float
	Field Elasticity:Float
	
	Function Create:Constraint(v1:Verlet, v2:Verlet, Length:Float = -1)
		
		Local CC:Constraint = New Constraint
		CC.v1:Verlet = v1:Verlet
		CC.v2:Verlet = v2:verlet
		If length < 0 Then
			CC.Length = Sqr( (v1.x - v2.x)^2 + (v1.y - v2.y)^2 )	'Distance formula for the length
		Else
			CC.Length = Length
		EndIf
		
		CC.Elasticity = 0
		Constraintlist.addlast(CC:Constraint)	'verlet list
				
		Return CC:Constraint
	End Function
	
	
End Type

Function UpdateConstraints()

	For Local a:Int = 1 To ConstraintIterations
		For Local c:Constraint = EachIn ConstraintList
			Local totalmass# = c.v1.mass# + c.v2.mass#
			
			Local v1prop# = (c.v1.mass#/totalmass#) * 2
			Local v2prop# = (c.v1.mass#/totalmass#) * 2
			
			Local dx# = c.v1.x - c.v2.x
			Local dy# = c.v1.y - c.v2.y
			
			Local length# = Sqr(dx#*dx# + dy#*dy#)
			Local diff#
			
			If length# <> 0 Then
				diff# = (length# - c.length) / length#
			Else
				diff# = 0
			EndIf
			
			dx# = dx# * .5
			dy# = dy# * .5
			
			c.v1.x = c.v1.x - (diff# * dx#) * v2prop#
			c.v1.y = c.v1.y - (diff# * dy#) * v2prop#
			
			c.v2.x = c.v2.x + (diff# * dx#) * v1prop#
			c.v2.y = c.v2.y + (diff# * dy#) * v1prop#
			
			DrawLine(c.v1.x,c.v1.y,c.v2.x,c.v2.y)
		Next
	Next

End Function



Type Verlet				'Verlet Type

	Field X!
	Field Y!
	Field OX!
	Field OY!
	Field VX!
	Field VY!
	Field Siz:Float
	Field Collided:Int
	Field ID:Int = 0
	Field mass:Float
	
	Function Create:Verlet(x!,y!,siz:Float,mass:Float,ID:Int,ox! = 0,oy! = 0)
		Local  VV:Verlet = New Verlet
		VV.x! = x!			'verlet x
		VV.y! = y!			'verlet y
		VV.ox! = x! + ox!		'verlet old x
		VV.oy! = y! + oy!		'verlet old y
		VV.siz = siz			'verlet radius
		VV.Collided = False		'collision variable
		VV.ID = ID			'Verlet ID
		VV.mass = mass			'Verlet mass
		VV.vx! = 0			'Verlet velocity x
		VV.vy! = 0			'Verlet velocity y
		Verletlist.addlast(VV:Verlet)	'verlet list
		
		Return VV:Verlet
	End Function
	
End Type

Function UpdateVerlets()
	
	SetScale 1,1	'sets the color rotation alpha scale and blend mode for the verlets
	SetRotation 0
	SetAlpha .5
	SetBlend 3
	SetColor 255,255,255
	For Local V:Verlet = EachIn VerletList
		
		V.collided = False		'Resets collision variable
		
		Local wfric:Int
		
		If v.y > waterlevel Then	'Detects if verlet is below water for water friction flag
			wfric = True	'water friction flag set to true
		Else
			wfric = False	'water friction flag set to false
		EndIf
		
		v.vx = (v.x - v.ox) * (Friction-(wfric*WaterFriction)) 'Gets velocities of verlets
		v.vy = (v.y - v.oy) * (Friction-(wfric*WaterFriction))
		
		v.ox = v.x 'Updates O values O=old
		v.oy = v.y
		
		v.x = v.x + v.vx			'Keeps track of X velocity
		v.y = v.y + v.vy + Gravity	'Applies Gravity
		
		
		For Local vv:verlet = EachIn verletlist
			If v <> vv And v.id <> vv.id   ' If Not the same verlet Or group
				Local dx# = v.x - vv.x
				Local dy# = v.y - vv.y
				Local dist# = Sqr ( dx#*dx# + dy#*dy#)		
				Local totalr# = v.siz# + vv.siz#
				If dist# < totalr# Then
				
					
					Local Diffx# = ( dist# - totalr# ) * ( dx# / dist# )
					Local Diffy# = ( dist# - totalr# ) * ( dy# / dist# )

					v.x = v.x - Diffx# '* .5
					v.y = v.y - Diffy# '* .5

					vv.x = vv.x + Diffx# '* .5
					vv.y = vv.y + Diffy# '* .5
				EndIf 				
			EndIf
		Next 


		If v.y > waterlevel Then			'This does water calculations I came up with
			Local dtmp# = waterlevel-v.y
			If dtmp# > Waterdensity Then
				v.oy = v.oy - (BoyancyForce*(1/v.mass#))
			Else
				v.oy = v.oy - BoyancyForce * (dtmp#/Waterdensity) * (1/v.mass#)
			EndIf
		EndIf
		
		DrawOval V.x-V.siz , V.y-V.siz , V.siz*2 , V.siz*2  'Draws the verlet (temporary)
	Next
	
End Function


ok thanks a million DavidDC. I guess I will just study the code you modified so I can figure out superstrict and strict :) What are the advantages/disadvantages of superstrict and strict besides compile time?

What are the advantages/disadvantages of superstrict and strict besides compile time?

You'll never, ever have an (hard to find) error where you have mistyped a variable name and accidentally found yourself using a variable which does not exist, and thus has a 0 or NULL value.

I think I get it now! thanks!

Hi I have another question.. when I build without quick build or debug on, when I run my program a command prompt window pops up along with my game. Why is this? is there a way to get rid of it because it is getting annoying. I am running vista if that helps any

you might have "build GUI app" disabled.

oh yeah I thought that was for Max GUI which I dont have so I disabled it. my bad... blitz max is so addicting! thanks for the help.