Gravity on round object ';..;'

Blitz3D Forums/Blitz3D Beginners Area/Gravity on round object ';..;'

FunTex(Posted 2004) [#1]
I'm having some problems with my gravity code, I've made a planet and i want a object to fall to the planet surface, not just down. I was almost succesful, but when a object moves near a pole of the planet, the screen starts to rotate, please give some help and sudgestions.

Best regards, Thomas


Rob Farley(Posted 2004) [#2]
2D or 3D?

[edit]
sounds like 3D... also sound like you're detailing with the camera trying to keep itself upright.

You need to attach the camera to a pivot, rotate one axis with the camera and the other from the pivot.


_PJ_(Posted 2004) [#3]

when a object moves near a pole of the planet, the screen starts to rotate,



Please could you be a bit more specific? Or maybe even post some code. As Rob says, 2D or 3D first, and how have you made this planet?


Avrigus(Posted 2004) [#4]
I assume Thomas means he's made a 3D sphere (the planet) and wants his object to be attacted to the center of the sphere no matter where it is on the surface, like a giant walking around a small moon. Much like the games Populous 3 or the mini game in the latest Ratchet and Clank game.

I too would like to get some tips on how this could be done :-)


Shambler(Posted 2004) [#5]
I suppose you could point the entity at the planet and then just move the entity forwards, that would make it fall toward the centre of the planet all the time.


sswift(Posted 2004) [#6]
For the sake of simplicity, you can assume the center of mass is at the center of an object.

Oxyz = Object center of mass
Pxyz = Planet center of mass
Gvxyz = Gravity vector
Gdxyz = Gravity direction
Gm = Gravity magnitude

; Units per meter.
; The number of units in a meter in your game.
; I like a distance of 1 to equal a meter, but in a space game that would be far too large a number to use for one meter.
UnitsPerMeter# = 1.0

; Set gravity to 9.8 meters per second squared.
Gravity# = 9.8

; Set this to the number of seconds which has passed since the last frame. This number is most likely to be less than 1. If you are running at a constant 60 frames per second, 1.0 / 60.0 = 0.0166 seconds per frame. You will want to calcualte this each frame probably if the frame times are different.
Time_Delta_Sec# = 0.166

; Calculate vector from object to planet.
Gvx# = Px# - Ox#
Gvy# = Py# - Oy#
Gvz# = Pz# - Oz#

; Calculate legth of vector.
; This is the distance between object and planet.
; The m stands for magnitude.
; A vecotr has a direction, and a magnitude. The magnitude is the length of the vector.
Gm# = Sqr(Gvx#*Gvx# + Gvy#*Gvy# + Gvz#*Gvz#)

; Divide vector by length of vector, to make it a normal.
; A normal is a vector with a length of 1.
; This is the DIRECTION in which gravity is pulling. It is also the gravity's "normal" or "normal direction".
Gdx# = Gvx# / Gm#
Gdy# = Gvy# / Gm#
Gdz# = Gvz# / Gm#


;Now you have a normal indicating in which DIRECTION gravity
;is pulling.

;Now you just need to calculate how much gravity is pulling
;on your object.

; Calculate how much velocity to add this frame.
; Ie, 9.8 meters per second, * 10 units per meter = 98.0 units per second. Then multiply by the number of seconds which have passed this frame, which we will say is 0.01, which would be 100 frames per second, and the result would be that we should move the object 0.98 units this frame.

Gm# = (Gravity# * UnitsPerMeter#) * Time_Delta_Sec#

; Multiply this velocity by the how much the gravity is pulling in each direction, and add the resulting velocity vector to your object's veloicity vector.

Ovx# = Ovx# + Gdx#*Gm#
Ovy# = Ovy# + Gdy#*Gm#
Ovz# = Ovz# + Gdz#*Gm#

; Finally, move your object according to it's velocity, and how many seconds the last frame took to render.

Ox# = Ox# + Ovx#*Time_Delta_Sec#
Oy# = Oy# + Ovy#*Time_Delta_Sec#
Oz# = Oz# + Ovz#*Time_Delta_Sec#

; Make sure you store Oxyz and Ovxyz with your object... you must retain it from one frame to the next!


Neo Genesis10(Posted 2004) [#7]
Simplicity... love it. Okay, I hit just this snag at one time and here's how I got around the problem (this assumes you're using Blitz 3D).

1) Create a pivot which is the PARENT of the object you are applying gravity to.
2) Then in each loop:
3) De-parent the object.
4) Point the pivot at the target sphere./
5) Re-parent the object.
6) Move the pivot by gravity speed.

Heres some code in action:
Graphics3D 640, 480
SetBuffer BackBuffer()

Global pivot = CreatePivot()
Global cube = CreateCube(pivot)
Global world = CreateSphere(16)
Global cam = CreateCamera()

Global gravity# = 0.01

Repeat
	EntityParent pivot, 0
	If KeyDown(200) MoveEntity cube, 0, 0, .01
	If KeyDown(208) MoveEntity cube, 0, 0, -0.01

	
	; The following simulates thrusters for moving away from the surface
	; NOTE: this is an example. Fiddling with gravity is not recommended :)
	If KeyDown(57)
		gravity# = -0.01
	Else
		gravity# = 0.01
	EndIf

	; Position the entity at our cubes exact position
	PositionEntity pivot, EntityX#(cube,1), EntityY#(cube,1), EntityZ#(cube,1)

	; Point the pivot at the planet
	PointEntity pivot, world

	; Re-parent the cube
	Entityparent cube, pivot

	; Move the objects
	MoveEntity pivot, 0, 0, gravity#

Until Keyhit(1)
This is similar to Shamblers suggestion, but it allows you to retain the current rotation of your object.


sswift(Posted 2004) [#8]
My way's the "right" way and in the long run you'll be far better off knowing how to do things with vectors. :-)


sswift(Posted 2004) [#9]
This simpler method will work if you don't want variable framerates, and you can live without gravity making an object fall faster and faster.


; Distance to move object each frame towards planet.
Gravity# = 10.0

Ox# = EntityX#(Ship)
Oy# = EntityY#(Ship)
Oz# = EntityZ#(Ship)

Px# = EntityX#(Planet)
Py# = EntityY#(Planet)
Pz# = EntityZ#(Planet)

; Calculate vector from object to planet.
Gvx# = Px# - Ox#
Gvy# = Py# - Oy#
Gvz# = Pz# - Oz#

; Shorten vector until it's one unit long.
Gm# = Sqr(Gvx#*Gvx# + Gvy#*Gvy# + Gvz#*Gvz#)
Gdx# = Gvx# / Gm#
Gdy# = Gvy# / Gm#
Gdz# = Gvz# / Gm#

; Move object towards planet.
Ox# = Ox# + Gdx#*Gravity#
Oy# = Oy# + Gdy#*Gravity#
Oz# = Oz# + Gdz#*Gravity#

PositionEntity Ship, Ox#, Oy#, Oz#


Neo Genesis10(Posted 2004) [#10]
I still prefer simplicity. Besides, its all very well having a piece of code but its pretty useless unless you know what its actually doing.