Elastic physics algorithm

Blitz3D Forums/Blitz3D Programming/Elastic physics algorithm

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 can take no credit for this as you can see .. it should help you though. Use the arrow keys ...

; quick thrust game, by Wiebo de Wit
; Using verlet integration for movement and stick constraints for the ball and chain =]
; green line is your ship. I'm sorry but i didn't have the strength to include my new
; vector object engine. a and s to rotate, r-shift to thrust

Const TIMESTEP# = 0.05
Const GRAVITYANGLE = 0			; 0 = straight down, 90 = right, etc
Const GRAVITYFORCE# = 10
Const DRAG# = 0.995
Const THRUST# = 40
Const NUM_PARTICLES = 5
Const RESTLENGTH# = 20

Type Particle
	Field x#, y#
	Field old_x#, old_y#
	Field a_x#, a_y#
	Field mass#
	Field nxt.particle
End Type

Type Player
	Field angle#
	Field thrust#
	Field point.particle
End Type

Global player.player, p.particle

Graphics 640,480
SetBuffer BackBuffer()

; create player
player.player = New player

; player is a particle too, but you can control it
player\point = New particle
p.particle = player\point
p\x = 200 : p\y = 200
p\old_x = 200 : p\old_y = 200
p\a_x = 0 : p\a_y = 0

; make ship heavy
p\mass =1

For count = 1 To NUM_PARTICLES

	p\nxt = New particle
	p = p\nxt

	p\x = 200 : p\y = 200
	p\old_x = Rand(200,205) 
	p\old_y = Rand(200,205)
	p\a_x = 0 : p\a_y = 0
	p\mass = 60
Next

; last particle is ball. make heavy
p\mass = 1

; loop
While KeyHit( 1 ) = False

	GetInput()
	ApplyPhysics()
	Verlet()
	ConstrainParticlesMass()
	DrawParticles()
	Flip
	Cls

Wend

; ------------------------------------------------------------

Function GetInput()

	If KeyDown( 203 )
		;rotate
		player\angle = player\angle + 5
	EndIf

	If KeyDown( 205 )
		;rotate
		player\angle = player\angle - 5
	EndIf

	If KeyDown( 200 )
		;thrust, adjust player particle acceleration
		p.particle = player\point
		p\a_x = p\a_x - Sin( player\angle ) * THRUST
		p\a_y = p\a_y - Cos( player\angle ) * THRUST
	EndIf

End Function


Function ApplyPhysics()

	; apply gravity to particles
	For p.particle = Each particle
		p\a_x = p\a_x + Sin( GRAVITYANGLE ) * GRAVITYFORCE / p\mass
		p\a_y = p\a_y + Cos( GRAVITYANGLE ) * GRAVITYFORCE / p\mass
	Next

End Function


Function ConstrainParticlesMass()

	p.particle = player\point

	While p\nxt <> Null
		dx# = p\nxt\x - p\x
		dy# = p\nxt\y - p\y

		deltalength# = Sqr( dx*dx + dy*dy )
		diff# = ( deltalength - RESTLENGTH ) / (deltalength * ( -p\mass + -p\nxt\mass ) )

		p\x = p\x + -p\mass * dx * diff
		p\y = p\y + -p\mass * dy * diff
		p = p\nxt
		p\x = p\x - -p\mass * dx * diff
		p\y = p\y - -p\mass * dy * diff
	Wend

End Function


Function DrawParticles()

	p.particle = player\point

	; draw player, green line

	Color 0,255,0
	dx# = Sin( player\angle) 
	dy# = Cos( player\angle)
	Line p\x-dx*20, p\y-dy*20 , p\x + dy*5, p\y - dx*5
	Line p\x-dx*20, p\y-dy*20 , p\x - dy*5, p\y + dx*5
	Line p\x + dy*5, p\y - dx*5, p\x - dy*5, p\y + dx*5

	; draw line
	Color 255,0,0
	While p\nxt <> Null
		Line p\x, p\y, p\nxt\x, p\nxt\y
		p = p\nxt
	Wend

	; draw ball at end
	Color 255,255,0
	Oval p\x -14, p\y-14, 28,28, 0

	; white dots, for clarity
	Color 255,255,255
	For p.particle =Each particle
		Plot p\x, p\y
	Next

End Function


Function Verlet()

	; eg: move particles, introducing drag

	For p.particle = Each particle

		x# = p\x
		y# = p\y

		tempx# = p\x
		tempy# = p\y

		oldx# = p\old_x
		oldy# = p\old_y

		p\x = p\x + DRAG * x - DRAG * oldx + p\a_x * TIMESTEP * TIMESTEP
		p\y = p\y + DRAG * y - DRAG * oldy + p\a_y * TIMESTEP * TIMESTEP

		p\old_x = tempx
		p\old_y = tempy

		; reset acceleration after moving particle
		p\a_x = 0 : p\a_y = 0
	Next

End Function