planet attraction code

BlitzMax Forums/BlitzMax Beginners Area/planet attraction code

Hi !
See this code.
when the white ship is near the planet (green zone) it should be attracted. In some situations it is not the case... so Could you help me to understand what'is wrong with my code ! Thanks !

Graphics 800,600

Const cte_div = 5

HideMouse()

' init

MoveMouse GraphicsWidth()/2, GraphicsHeight() / 2

px# = MouseX()
py# = MouseY()

cx = 200
cy = 150
cr1  = 50
cr2 = 120
speed# = 0.5

While Not KeyDown (KEy_ESCAPE)

Cls

' player movement (rockout style)

	xdist# = MouseX() - px
	ydist# = MouseY() - py
	xs = xdist / cte_div
	ys = ydist / cte_div
	px = px + xs
	py = py + ys
	
' display planet

	SetColor 0,255,0
	DrawOval cx - cr2, cy- cr2, cr2 * 2,cr2 * 2
	SetColor 0,0,255
	DrawOval cx - cr1,cy - cr1 ,cr1 * 2, cr1 * 2
	SetColor 255,255,255
	Plot ccx,ccy
	

' planet attraction code

	d = Int (Sqr((px-cx) * (px-cx) + (py-cy) * (py-cy)))
	
	If d <= cr2 And d > cr1 Then
	
		SetColor 255,255,255
		DrawText "attracted !",cx,cy
	
	    angle = ATan2((cy - py),(cx - px))
	
		xmov# = Cos (angle) * speed#
		ymov# = Sin (angle) * speed#
		px = px + xmov#
		py = py + ymov#
		
		MoveMouse MouseX() + xmov#, MouseY() + ymov#		
		DrawLine cx,cy, px,py
		
		
	End If

' display player

	SetColor 255,255,255
	DrawOval px-25, py-25, 50,50
	SetColor  255,0,0
	DrawOval MouseX()-3, MouseY()-3,6,6
	
' display infos
	
	DrawText "dist=" + String (d),0,0
	DrawText "x=" + String (px),0,10
	DrawText "y=" + String (py),0,20
	DrawText "xmov=" + String (xmov),0,30
	DrawText "ymov=" + String (ymov),0,40
	DrawText "angle=" + String (angle),0,50

Flip

Wend

ShowMouse()


General attraction formula for mass bodies:

force = mass * acceleration = (mShip * mPlanet) / (distance * distance)

So if you combine those two, the acceleration is force/mShip =>mPlanet/(distance*distance), targeted to the center of the planets mass (normally its center :))

Thanks, but what'is mShip or mPlanet ? planet mass and ship mass ? could you post a sample adapted to my code variables ?

this ?
Graphics 800,600

Const cte_div = 5
Const cte_planet_mass = 10000

HideMouse()

' init

MoveMouse GraphicsWidth()/2, GraphicsHeight() / 2

px# = MouseX()
py# = MouseY()

cx = 200
cy = 150
cr1  = 50
cr2 = 120
speed# = 0.5

While Not KeyDown (KEy_ESCAPE)

Cls

' player movement (rockout style)

	xdist# = MouseX() - px
	ydist# = MouseY() - py
	xs = xdist / cte_div
	ys = ydist / cte_div
	px = px + xs
	py = py + ys
	
' display object

	SetColor 0,255,0
	DrawOval cx - cr2, cy- cr2, cr2 * 2,cr2 * 2
	SetColor 0,0,255
	DrawOval cx - cr1,cy - cr1 ,cr1 * 2, cr1 * 2
	SetColor 255,255,255
	Plot ccx,ccy
	

' attracted object code

	d = Int (Sqr((px-cx) * (px-cx) + (py-cy) * (py-cy)))
	
	If d <= cr2 And d > cr1 Then
	
		SetColor 255,255,255
		DrawText "attracted !",cx,cy
		
		angle = ATan2((cy - py),(cx - px))
		
		xmov# = Cos (angle) * Float (cte_planet_mass / (d*d))
		ymov# = Sin(angle) * Float (cte_planet_mass / (d*d))
		px = px + xmov#
		py = py + ymov#
		
		MoveMouse MouseX() + xmov#, MouseY() + ymov#		
		DrawLine cx,cy, px,py
		
	End If

' display player

	SetColor 255,255,255
	DrawOval px-25, py-25, 50,50
	SetColor  255,0,0
	DrawOval MouseX()-3, MouseY()-3,6,6
	
' display infos
	
	DrawText "dist=" + String (d),0,0
	DrawText "x=" + String (px),0,10
	DrawText "y=" + String (py),0,20
	DrawText "xmov=" + String (xmov),0,30
	DrawText "ymov=" + String (ymov),0,40
	DrawText "angle=" + String (angle),0,50
Flip

Wend

ShowMouse()


actually the force equation is
F=(Gm1m2)/r^2
Where G is the gravitational constant = 6.67300 × 10^-11 m^3 kg^-1 s^-2 and m1 and m2 are the masses in kg, r is the distance from the centre of gravity of the two masses.
dreamora is just missing the G part.

mShip and mPlanet are the masses of the ship and the planet.

Moogles: Did not miss it, but G is only a linear physical scaling size, which is why I did not enter it to the formula. Linear can be applied on will at any time ...
1/FPS for example could be seen as a G as well in frame independent programming ... :-)

I played around with this too.
GravitySum:TVector.Equals(0,0)

For Local Planet:TPlanet=EachIn PlanetList
	Range.Between(Planet.Position,Self.Position)
	Local Distance:Float=Self.Position.DistanceTo(Planet.Position) 
	Local GravityPull:Float=(Mass*Planet.Mass*G)/(Distance^2)
	Local Angle:Float=ATan2(Range.Y,Range.X)  
	Local GravityNormal:TVector=Planet.Position.Copy()
	GravitySum.AddPolar(Angle,GravityPull)
Next


This code won't run but it's the idea.

The loop is because I had many planets all exerting a pull on my "Ship"

2 suggestions:
- use distance*distance instead of ^2. Its faster
- I would consider a maximum distance at which the gravity has an effect. If the distance becomes to large, the output becomes wrong.

Yeah that's true. Thanks.

.. In my program.. When you get too close GravityPull would get ridiculously huge. My ship would go hurling off into space at the speed of light.

So I clamped it to a maximum that worked in my program.

ah k. i thought it would be handy to know it as well ;).
you do physics dreamora? :P

Its a sideeffect of study of eletrotechnics and informationtechnology, that you are forced to learn physics (for building integrated circuits and the like :)).

But this specific topic here is a different thing: Have a project thats on ice atm, that focuses around gravitic / coulomb physics only.

uhm... is the code posted in my previous message is ok with dreamora formulae ? don't blame me i crap with maths and physics ! Thanks for your help

if you use the formula that dreamora posted it would work. G is just a constant you can include it if you like or not. id say include it if you want it to be real life physics.

in fact, there are something strange with my code. it seems not be realistic... (if ship enter into the green zone by the left). Maybe a bad implementation of dreamora formulae ?

An implementation of the code needs the following check
local radius_factor:float  = 1.0 / (distance * distance)
if radius_factor < 0.001   radius_factor = 0.001


Otherwise you might see the "gets near center and accelerates to infinity" behavior ;)

Can you describe your problem a little or even provide some running code?

Graphics 800,600

Const cte_div = 5
Const cte_planet_mass = 10000

HideMouse()

' init

MoveMouse GraphicsWidth()/2, GraphicsHeight() / 2

px# = MouseX()
py# = MouseY()

cx = 200
cy = 150
cr1  = 50
cr2 = 120
speed# = 0.5

While Not KeyDown (KEy_ESCAPE)

Cls

' player movement (rockout style)

	xdist# = MouseX() - px
	ydist# = MouseY() - py
	xs = xdist / cte_div
	ys = ydist / cte_div
	px = px + xs
	py = py + ys
	
' display object

	SetColor 0,255,0
	DrawOval cx - cr2, cy- cr2, cr2 * 2,cr2 * 2
	SetColor 0,0,255
	DrawOval cx - cr1,cy - cr1 ,cr1 * 2, cr1 * 2
	SetColor 255,255,255
	Plot ccx,ccy
	

' attracted object code

	d = Int (Sqr((px-cx) * (px-cx) + (py-cy) * (py-cy)))
	
	If d <= cr2 And d > cr1 Then
	
		SetColor 255,255,255
		DrawText "attracted !",cx,cy
		
		angle = ATan2((cy - py),(cx - px))
		
		xmov# = Cos (angle) * Float (cte_planet_mass / (d*d))
		ymov# = Sin(angle) * Float (cte_planet_mass / (d*d))
		px = px + xmov#
		py = py + ymov#
		
		MoveMouse MouseX() + xmov#, MouseY() + ymov#		
		DrawLine cx,cy, px,py
		
	End If

' display player

	SetColor 255,255,255
	DrawOval px-25, py-25, 50,50
	SetColor  255,0,0
	DrawOval MouseX()-3, MouseY()-3,6,6
	
' display infos
	
	DrawText "dist=" + String (d),0,0
	DrawText "x=" + String (px),0,10
	DrawText "y=" + String (py),0,20
	DrawText "xmov=" + String (xmov),0,30
	DrawText "ymov=" + String (ymov),0,40
	DrawText "angle=" + String (angle),0,50
Flip

Wend

ShowMouse()


try to enter into the green area from the left.

bump ;-)

Strict

Graphics 1024,768

Const cte_div = 5
Const cte_planet_mass = 50000

Const CTE_ATTIRER   = 1
Const CTE_REPOUSSER  = 2

Const MAX_PARTICULES = 500
Const CTE_RAYON_CORPS = 50

Global Liste_attracteurs:TList = CreateList()


Type TPoint

	Field x:Int
	Field y:Int
	
	Function Creer:TPoint (x:Int,y:Int)
	
		Local p:TPoint = New TPoint
		
		p.x = x
		p.y = y
		
		Return p
		
	End Function
	
End Type

Type TAttracteur

	Field CentreX
	Field CentreY
	Field Rayon_exterieur
	Field Masse : Int
	Field Mode
	Field hImage:Timage
	
	Field Particule_x : Int [MAX_PARTICULES]
	Field Particule_y : Int [MAX_PARTICULES]
		
	Function Creer:TAttracteur (Mode:Int, PosX : Int, PosY : Int, Rayon_exterieur = 200, Masse = 80000)
	
		Local a:Tattracteur = New TAttracteur
		
		a.CentreX = PosX
		a.CentreY = PosY
		a.Rayon_exterieur = Rayon_exterieur
		a.Masse = Masse
		a.Mode  = Mode
		
		For Local i=0 To MAX_PARTICULES - 1
		
			Local langle = Rand(0,360)
		
			Select mode
			
				Case CTE_ATTIRER
				
					a.Particule_x[i] = a.CentreX + Cos (langle) * (Rayon_exterieur - 5)
					a.Particule_y[i] = a.CentreY + Sin (langle) * (Rayon_exterieur - 5)
					
				Case CTE_REPOUSSER
				
					a.Particule_x[i] = a.CentreX + Cos (langle) * (CTE_RAYON_CORPS + 5)
					a.Particule_y[i] = a.CentreY + Sin (langle) * (CTE_RAYON_CORPS + 5)
					
			End Select
			
		Next
		
		ListAddLast Liste_attracteurs, a
		
		Return a
		
	End Function
	
	Method Maj_particules()
	
		Local p:Tpoint
		For Local i=0 To MAX_PARTICULES - 1
		
			p = Calculer(Particule_x[i], Particule_y[i])
			Particule_x[i] = p.x
			Particule_y[i] = p.y			
			p = Null
			
			Local d = Int (Sqr((Particule_x[i] - CentreX) * (Particule_x[i] - CentreX) + (Particule_y[i] - CentreY) * (Particule_y[i] - CentreY)))
			
			Local langle = Rand(0,360)
			
			Select Mode
			
				Case CTE_ATTIRER
				
					If d <= CTE_RAYON_CORPS  Then
						Particule_x[i] = CentreX + Cos (langle) * (Rayon_exterieur - 5)
						Particule_y[i] = CentreY + Sin (langle) * (Rayon_exterieur - 5)
					End If
					
				Case CTE_REPOUSSER
				
					If d >= Rayon_exterieur Then
						Particule_x[i] = CentreX + Cos (langle) * (CTE_RAYON_CORPS + 5)
						Particule_y[i] = CentreY + Sin (langle) * (CTE_RAYON_CORPS + 5)
					End If
			
			End Select
			
			'DebugLog "d=" + String (d)
			
		Next
		
		Select Mode
			Case CTE_ATTIRER 
				SetColor 255,0,0
			Case CTE_REPOUSSER
				SetColor 0,255,0
		End Select				
				
		For Local i=0 To MAX_PARTICULES - 1
			Plot Particule_x[i], Particule_y[i]
		Next
		SetColor 255,255,255
	
	End Method

	
	Method Calculer:Tpoint(x : Int, y:Int)
	
		Local p:Tpoint
		
		p = Tpoint.Creer (x,y)
	
		Local d:Int
		Local angle#
		Local xmov#, ymov#
	
		d = Int (Sqr((p.x - CentreX) * (p.x - CentreX) + (p.y - CentreY) * (p.y - CentreY)))
		
		If d > (CTE_RAYON_CORPS) And d < Rayon_exterieur Then
		
			angle = ATan2((CentreY - p.y),(CentreX - p.x))
			'DebugLog String(angle)

			Local a# = Float (Masse / (d*d))
			If a < 0.001 Then a = 0.001
			
			xmov# = Cos (angle) * a#
			ymov# = Sin (angle)  * a#
								
			Select Mode
			
				Case CTE_REPOUSSER
					
					p.x = p.x - xmov#
					p.y = p.y - ymov#					
					
				Case CTE_ATTIRER
					
					p.x = p.x + xmov#
					p.y = p.y + ymov#					
					
			End Select
			
		End If
		
		If d <=  CTE_RAYON_CORPS  Then
			DrawText "collided!",CentreX, CentreY
		End If	
		
		Return p		
	
	End Method
	
	Method Afficher()
	
		SetColor 255,255,255
		DrawOval CentreX - CTE_RAYON_CORPS, CentreY - CTE_RAYON_CORPS, CTE_RAYON_CORPS*2, CTE_RAYON_CORPS*2
		
		DrawVectorCircle CentreX, CentreY, Rayon_exterieur, Rayon_exterieur
	
	End Method
	
End Type

Function DrawVectorCircle(cx:Double,cy:Double,radiusx:Double, radiusy:Double)

	Local lx:Double=radiusx*Cos(0)
	Local ly:Double=radiusy*Sin(0)
	
	For Local d:Double=20 To 360 Step 20
		Local nx:Double = radiusx*Cos(d)
		Local ny:Double = radiusy*Sin(d)
		SetColor 0,100,0
		DrawLine(cx+lx,cy+ly-1,cx+nx,cy+ny-1)	
		SetColor 0,255,0
		DrawLine(cx+lx,cy+ly,cx+nx,cy+ny)
		SetColor 0,100,0
		DrawLine(cx+lx,cy+ly+1,cx+nx,cy+ny+1)
		
		lx=nx
		ly=ny
	Next
	
End Function

HideMouse()

MoveMouse GraphicsWidth()/2, GraphicsHeight() / 2

Global PosX# = MouseX()
Global PosY# = MouseY()

TAttracteur.Creer (CTE_ATTIRER, 200,200)
TAttracteur.Creer (CTE_ATTIRER, 400,300)
TAttracteur.Creer (CTE_REPOUSSER, 900,200)

While Not KeyDown (KEy_ESCAPE)

Cls

	Local xdist# = MouseX() - PosX
	Local ydist# = MouseY() - PosY
	Local xs = xdist / cte_div
	Local ys = ydist / cte_div
	PosX = PosX + xs
	PosY = PosY + ys
	
	' code attrateur
	
		Local p:Tpoint
		
		For Local a:TAttracteur = EachIn Liste_attracteurs 
			
			p = a.Calculer(PosX, PosY)
			a.Afficher()
			a.Maj_particules()			
			PosX = p.x
			PosY = p.y
			p = Null
			
		Next
		
		MoveMouse PosX, PosY
	
	' fin code	
	SetColor 255,0,255
	DrawOval PosX-25, PosY-25, 50,50
	SetColor  255,0,0
	DrawOval MouseX()-3, MouseY()-3,6,6
	
Flip

Wend

ShowMouse()


That is very cool indeed ! :)