Physics

Blitz3D Forums/Blitz3D Beginners Area/Physics

When you are ready heres some more code which demonstrates 2d gravitation in free space. its not entirely accurate as Ive played with the formulii to give pleasing results (IE it doesnt take half a year for a satelite to orbit a gravity well)

its based on the principle that the force on an object from a well varies inversely proportional to the distance of the object from the well. again its code ive posted before but a long time ago now.

;A simple program to demonstrate 2d gravitational physics
;the physics is not entirely accurate but more to the point
;it looks acceptable and produces nice patterns.
;incidentally this system also displays chaotic behaviour
;in that a small change in a satelites starting paramaters
;produces a large change in its path trail as you will see by the
;two demonstration satelites having a difference of 0.1 degree in their
;start angle and everything else identical
Type satelite
	Field x#;statelite position x and y coord
	Field y#
	Field dx#;speed of the satelite in x and y dir
	Field dy#
	Field fx#;forces acting on the satelite in x and y directions
	Field fy#
	Field mass; mass of the satelite
	Field pathStart.pathpoint
	Field colour ; colour of path
	Field crashed
End Type

Type well
	Field gravity#; gravitational force of the well
	Field x#; wells xy coords
	Field y#
End Type

Type pathpoint
	Field n.pathpoint
	Field x
	Field y
End Type

Graphics 800,600,32,2

Global period#
Global pathLength
Global maxLength = 1024
Global count = 0
Global maxmag#=0

Global this_time=MilliSecs()
Global Last_time=MilliSecs()


;make a satelite And set it with some initial values
a#=110
s.satelite =New satelite
s\x = 100
s\y = 150
s\dx=1*Sin (a)
s\dy=- 1* Cos (a)
s\mass = 5
s\colour=$FF0000

a2#=135
s2.satelite =New satelite
s2\x = 150
s2\y = 150
s2\dx=1* Sin (a2)
s2\dy=-1* Cos (a2)
s2\mass = 4
s2\colour=$00FF00

;create a gravity well
w.well= New well
w\x=400
w\y=300
w\gravity=90000

;And another For good measure
w2.well= New well
w2\x=200
w2\y=300
w2\gravity=90000


;And another For good measure
w3.well= New well
w3\x=350
w3\y=300-100*(Sqr(3)/2)
w3\gravity=90000

SetBuffer BackBuffer()

;this is the time passed in each program loop
;idealy you would set this each loop using some realtime clock code
;but for simplicity here we will hard code it to 10 milliseconds
period=0.01

While Not KeyHit(1)

	For s.satelite=Each satelite
	
		s\fx=0
		s\fy=0

		resolveForces(s,w)
		resolveForces(s,w2)
		resolveForces(s,w3)
		updateSatelite(s)
		;dampSatelite(s)
		drawSatelite(s)
		
	Next



	drawWell(w)
	drawWell(w2)
	drawWell(w3)


	makepath()
	drawpath()
	If crashed And (First satelite)=Null Then Exit
	count=count +1
	Text 10,10,period
	Flip
	Cls
	
	Last_time=this_time
	this_time=MilliSecs()
	;calc the period To the nearest 10 ms
	period=(this_time-Last_time)/(10)/Float(100.0)
	
Wend

End

Function dampSatelite(s.satelite)
	s\dx=0.999 * s\dx
	s\dy=0.999 * s\dy
	

End Function

Function resolveForces( s.satelite, w.well)
	;the force on the satelite always works towards the well
	;the force on the satelite is proportional to 1/r^2
	;where r is the distance between the satelite and the center of gravity

	;find the wells position relative to the satelite
	Local dx#=w\x-s\x
	Local dy#=w\y-s\y
	;calc r^2
	Local r2#=((dx)^2+(dy)^2)
	;calc r
	Local r#=Sqr(r2)
	;calc mag of force at the satelites position
	Local f#= w\gravity * r2^-1
	;resolve in the x and y
	s\fy=s\fy+f*(dy/r)
	s\fx=s\fx+f*(dx/r)
	

End Function


Function updateSatelite(s.satelite)
	If s\crashed=1 Then Return
	;apply newtons laws in x and y directions
	;incrementing the satelites position proportional to the period
	dx#=s\dx
	;newtons law f=ma re-arranged to be a=f/m
	ax#=s\fx/s\mass
	;newtons law v=u+at
	s\dx=dx+ax*period
	
	dy#=s\dy
	ay#=s\fy/s\mass
	s\dy=dy+ay*period
	s\x=s\x+s\dx
	s\y=s\y+s\dy


	
	
	For w.well=Each well
		Local x=s\x
		Local y=s\y
		Local x1=w\x
		Local y1=w\y
		If ((x-x1)^2+(y-y1)^2)<25 Then
			s\x=w\x
			s\y=w\y
			s\dx=0
			s\dy=0
			s\crashed=1
		End If
	Next
	
	
End Function



Function drawSatelite(s.satelite)
	;just a dot will do
	mag#=Sqr(s\fx^2+s\fy^2)
	Plot s\x,s\y
	Text s\x,s\y,"*",1,1
	l=50*(mag/80)
	;If Not s\crashed Then Line s\x,s\y,s\x+(l*(s\fx/mag)),s\y+(l*(s\fy/mag))
	
End Function

Function drawWell(w.well)

	;a nice + to mark the center of gravitation
	Line w\x-5,w\y,w\x+5,w\y
	Line w\x,w\y-5,w\x,w\y+5
	

End Function

Function makePath()

	If count = 3
		For s.satelite = Each satelite
			If Not s\crashed Then
				p.pathpoint=New pathpoint
				p\n=s\pathStart
				p\x=s\x
				p\y=s\y
				s\pathstart=p
				pathLength=pathLength+1
			End If
		Next
		count = 0
	
		
	End If
End Function

Function drawPath()
	LockBuffer BackBuffer()
	
	For s.satelite=Each satelite
		idx=0
		p.pathpoint=s\pathstart
		If p<> Null
			While p\n<> Null
				idx=idx+1
				If p\x>0 And p\x<800 And p\y>0 And p\y<600
					c=255*(maxlength-idx)/maxlength
					col=c Shl( 16) + c Shl(8) + c
					WritePixelFast p\x,p\y,s\colour And col
				End If
				p=p\n
			Wend
		End If
	
		If pathLength>maxLength Then
			Delete First pathPoint
		End If
		If pathlength>maxlength Then pathlength=pathlength -1	
	Next
	
	
	UnlockBuffer BackBuffer()
End Function





Interestingly enough this program also displays chaotic behaviour in that small changes to the satelites starting position/angle can create radical changes in its flight path. in the code I have given the 2 satellites do not interact with each other. they are only there so you can compare different settings. basically this is a toy.