Orbit

BlitzPlus Forums/BlitzPlus Programming/Orbit

I want to create a program that lets an object move around a center point as a mouse avoider part for my game. Does anyone have code that would do that?

Just wrote a little gravity engine. Leave z# value to zero for just 2D gravity.

Functions:
obj% = CreatePhysicsObject(x#, y#, z#, mass#, friction#) ; Object's position and parameters
AffectPhysicsObject(obj%, xx#, yy#, zz#, gravity#, range#) ; xx#, yy#, zz# is the location of the gravity
PhysicsObjectX#(obj%)
PhysicsObjectY#(obj%)
PhysicsObjectZ#(obj%)
PhysicsObjectX#Speed(obj%)
PhysicsObjectY#Speed(obj%)
PhysicsObjectZ#Speed(obj%)
SetPhysicsObjectX#(obj%, value#)
SetPhysicsObjectY#(obj%, value#)
SetPhysicsObjectZ#(obj%, value#)
SetPhysicsObjectXSpeed#(obj%, value#)
SetPhysicsObjectYSpeed#(obj%, value#)
SetPhysicsObjectZSpeed#(obj%, value#)

Engine:
Function CreatePhysicsObject(x#, y#, z#, mass# = 1, friction# = 1, xs# = 0, ys# = 0, zs# = 0)
	bank% = CreateBank(8 * 4)
	If bank%
		PokeFloat bank%, 0 * 4, x#
		PokeFloat bank%, 1 * 4, y#
		PokeFloat bank%, 2 * 4, z#
		
		PokeFloat bank%, 3 * 4, xs#
		PokeFloat bank%, 4 * 4, ys#
		PokeFloat bank%, 5 * 4, zs#
		
		PokeFloat bank%, 6 * 4, mass#
		PokeFloat bank%, 7 * 4, friction#
	EndIf
	Return bank%
End Function

Function AffectPhysicsObject(obj%, xx#, yy#, zz#, gravity# = 1, range# = 100)
	; Get information
	x# = PeekFloat(obj%, 0 * 4)
	y# = PeekFloat(obj%, 1 * 4)
	z# = PeekFloat(obj%, 2 * 4)
	
	xs# = PeekFloat(obj%, 3 * 4)
	ys# = PeekFloat(obj%, 4 * 4)
	zs# = PeekFloat(obj%, 5 * 4)
	
	mass# = PeekFloat(obj%, 6 * 4)
	friction# = PeekFloat(obj%, 7 * 4)
	
	; Distance
	obj_distance# = Sqr#(Abs(x# - xx#)^2 + Abs(y# - yy#)^2 + Abs(z# - zz#)^2)
	
	; Calculate new speeds
	If obj_distance# < range#
		xs# = xs# + mass# * gravity# * Cos(GetAngle(x#, y#, xx#, yy#)) * ((range# - obj_distance#) / range#)
		ys# = ys# + mass# * gravity# * Sin(GetAngle(x#, y#, xx#, yy#)) * ((range# - obj_distance#) / range#)
		zs# = zs# + mass# * gravity# * Cos(GetAngle(z#, y#, zz#, yy#)) * ((range# - obj_distance#) / range#)
	EndIf
	
	x# = x# + xs#
	y# = y# + ys#
	z# = z# + zs#
	
	; Friction
	xs# = xs# * friction#
	ys# = ys# * friction#
	zs# = zs# * friction#
	
	; Save new values
	PokeFloat obj%, 0 * 4, x#
	PokeFloat obj%, 1 * 4, y#
	PokeFloat obj%, 2 * 4, z#
	
	PokeFloat obj%, 3 * 4, xs#
	PokeFloat obj%, 4 * 4, ys#
	PokeFloat obj%, 5 * 4, zs#
End Function

Function PhysicsObjectX#(obj%)
	Return PeekFloat(obj%, 0 * 4)
End Function

Function PhysicsObjectY#(obj%)
	Return PeekFloat(obj%, 1 * 4)
End Function

Function PhysicsObjectZ#(obj%)
	Return PeekFloat(obj%, 2 * 4)
End Function

Function PhysicsObjectXSpeed#(obj%)
	Return PeekFloat(obj%, 3 * 4)
End Function

Function PhysicsObjectYSpeed#(obj%)
	Return PeekFloat(obj%, 4 * 4)
End Function

Function PhysicsObjectZSpeed#(obj%)
	Return PeekFloat(obj%, 5 * 4)
End Function


Function SetPhysicsObjectX#(obj%, value#)
	PokeFloat(obj%, 0 * 4, value#)
End Function

Function SetPhysicsObjectY#(obj%, value#)
	PokeFloat(obj%, 1 * 4, value#)
End Function

Function SetPhysicsObjectZ#(obj%, value#)
	PokeFloat(obj%, 2 * 4, value#)
End Function

Function SetPhysicsObjectXSpeed#(obj%, value#)
	PokeFloat(obj%, 3 * 4, value#)
End Function

Function SetPhysicsObjectYSpeed#(obj%, value#)
	PokeFloat(obj%, 4 * 4, value#)
End Function

Function SetPhysicsObjectZSpeed#(obj%, value#)
	PokeFloat(obj%, 5 * 4, value#)
End Function

Function GetAngle(basex, basey, targetx, targety)
	If targety>basey-1 Then
		angle=ACos((targetx-basex)/Sqr((targetx-basex)*(targetx-basex)+(targety-basey)*(targety-basey)))
	Else
		If targetx>basex-1 Then
			angle=270+90-ACos((targetx-basex)/Sqr((targetx-basex)*(targetx-basex)+(targety-basey)*(targety-basey)))
		Else
			angle=360-ACos((targetx-basex)/Sqr((targetx-basex)*(targetx-basex)+(targety-basey)*(targety-basey)))
		EndIf
	EndIf

	If targetx=basex And targety=basey Then Return 0 Else Return angle
End Function


That looks great, Thanks! Can you post an example?

Sure! This has 50 objects. Use mouse to affect them (space changes the polarity):
Include "gravity.bb"

AppTitle "Gravity"
Graphics 600, 600, 32, 2
SetFont LoadFont("Arial", 20, True)
SeedRnd MilliSecs()

; create balls
ball_count% = 50
Dim ball%(ball_count%)

gravity% = 2
r% = 200

; Create objects
For i% = 1 To ball_count%
	ball%(i%) = CreatePhysicsObject(Rand(10, GraphicsWidth() - 10), Rand(10, GraphicsHeight() - 10), 0, 2, Rnd(.95, .99))
Next

While Not KeyHit(1)
	Cls
	
	mx% = MouseX()
	my% = MouseY()
	
	; Draw gravity
	Color 100, 0, 0
	Oval mx% - r%, my% - r%, r% * 2, r% * 2, False
	
	; Loop all balls
	For i% = 1 To ball_count%
		; Affect balls
		SetPhysicsObjectZ#(ball%(i%), 0)
		AffectPhysicsObject(ball%(i%), mx%, my%, 0, gravity%, r%)
		
		; Don't let the ball to leave the screen
		If PhysicsObjectX#(ball%(i%)) < 0 Or PhysicsObjectX#(ball%(i%)) > GraphicsWidth() Then
			SetPhysicsObjectX#(ball%(i%), PhysicsObjectX#(ball%(i%)) - PhysicsObjectXSpeed#(ball%(i%)))
			SetPhysicsObjectXSpeed#(ball%(i%), -PhysicsObjectXSpeed#(ball%(i%)))
		EndIf
		If PhysicsObjectY#(ball%(i%)) < 0 Or PhysicsObjectY#(ball%(i%)) > GraphicsHeight() Then
			SetPhysicsObjectY#(ball%(i%), PhysicsObjectY#(ball%(i%)) - PhysicsObjectYSpeed#(ball%(i%)))
			SetPhysicsObjectYSpeed#(ball%(i%), -PhysicsObjectYSpeed#(ball%(i%)))
		EndIf
		
		; Draw ball
		Color 200, 200, 200
		Oval PhysicsObjectX#(ball%(i%)) - 5, PhysicsObjectY#(ball%(i%)) - 5, 10, 10, True
	Next	
	
	; Reverse gravity
	If KeyHit(57) Then gravity% = -gravity%
	
	Flip
Wend
End


After each affect of an object you should Zero the z position of it!

That is cool, but not exactly what I need. I need an object to orbit another object in a steady pattern. Like Earth orbits the sun. Do you have anything that would do that?

Petron, could you not just create a pivot that is a child of the base object and then make your orbiter a child of that pivot, then rotate the pivot on the orbit that you want thereby keeping a constant distance from base object but still rotating around the base object?

This is what I did for a simulation of the moon orbiting the earth and it worked great.

I don't know how, can you post an example.

Graphics 800, 600, 0, 2
SetBuffer BackBuffer()

x = 400
y = 300

Repeat

	Cls
	
	Oval x - 10, y - 10, 20, 20
	
	ax = Cos(ang) * 80 + x
	ay = Sin(ang) * 80 + y
	
	Oval ax - 3, ay - 3, 6, 6
	
	;ang = 270 - ATan2(MouseX() - x, MouseY() - y)
	ang = ang + 5
	
	Flip
	
Until KeyHit(1)

End


@
b32
again... THANK YOU !!!

:)))