Sign in to follow this  
Azh321

Planet Gravity

Recommended Posts

I was trying to figure out the math for a 2d game were you cruise around in space and get pulled around by different planets gravities, similar to an old atari game (forgot the name) or master of orion. I know the formulas for calculating mass, gravity, gravitational acceleration, and such, but im not sure how to turn it into code, specifically, the players rotation and x/y values. At the moment im calling this function every frame:
function run(self)
{
    self._x+=Math.sin(self._rotation*(Math.PI/180))*self.theSpeed;
    self._y+=Math.cos(self._rotation*(Math.PI/180))*self.theSpeed*-1;
}

And allowing the arrow keys to change _rotation and theSpeed. How exactly does the gravity come into play, specifically, how does it affect the angle that the player is moving in? Thanks!

Share this post


Link to post
Share on other sites
Actually to compute precisely the torque generated by the gravitational attraction, you would need to compute an integral:

torque = summation over all mass elements of r(x,y,z).cross( F(x,y,z) )dxdydx

x,y,z being the local coordinates of a mass point.

My guess is that value should be quite small, since the variation of F(x,y,z) over the volume defined by the spaceshift is quite small( it depends of the distance of the element considered to the center of the planet ). You could safely consider that each mass element is at the same distance from the center of a planet and each element of torque is annihilated by another one. The effect could be meaningful if and only if the size( and therefore mass ) of the spaceshift is comparable to the size of the planet. You could then simply compute the forces at two "end points" of the space shift( you approximate its shape by a segment ), and compute the related torques generated by each planet on the spaceshift, and sum them.


torque_acc = zero

for each planet
compute the attraction force, force_1, at end_1 of spaceshift
compute the torque, torque_1, it generates at the center of mass
compute the attraction force, force_2, at end_2 of spaceshift
compute the torque, torque_2, it generates at the center of mass
add torque_1 and torque_2 to the torque accumulator, torque_acc





Since, your game is two dimensional, there is a direct relationship between the torque variation and the variation of the orientation angle of the spaceshift.

[Edited by - johnstanp on March 9, 2010 3:38:15 AM]

Share this post


Link to post
Share on other sites
Can't help with the torque, but gravity works something like this: in the beginning you have the player-planet gravitational system (F = (G * m1 *m2) / (r*r)). You know the distance and both masses so you solve it and get a force. If you have more than one planet attracting the player you could just solve both systems and add the forces (ignoring attraction between planets). Knowing that F=ma you can turn that force into acceleration, then you change position by velocity * time and change velocity by acceleration * time (p, v, a, F are all vectors obviously). This is the very basic Euler integration (the one that so many people use and so many people say that it sucks / is unstable. But probably good enough for first approximation and for simple 2D game).

Share this post


Link to post
Share on other sites
Quote:
Original post by lightbringer
Can't help with the torque, but gravity works something like this: in the beginning you have the player-planet gravitational system. You know the distance and both masses so you solve it and get a force. The force is along the vector (planet minus player). Knowing that F=ma you can turn that force into acceleration, then you change position by velocity * time and change velocity by acceleration * time. This is the very basic Euler integration (the one that so many people use and so many people say that it sucks / is unstable. But probably good enough for first approximation and for simple 2D game).


My bad...
I assumed that he knew how to compute a gravitational force, and integrate it...I understood that he wanted to know how the gravitational forces could affect the rotation of his spaceshift(angular momentum). I skipped force and torque ant the integration computing because I thought that he wasn't asking for it.

[Edited by - johnstanp on March 10, 2010 2:57:30 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by johnstanp
I assumed that he knew how to compute a gravitational force...I understood that he wanted to know how the gravitational forces could affect the rotation of his spaceshift(angular momentum). The method you provide, will only give him effects on the linear velocity of its spaceshift. I skipped it because I thought that he wasn't asking for it.


I skipped torque because I honestly have no clue about it :) But given that Azh321 is trying to add rotation to position, I think he needs to hear about the linear stuff, too.

Share this post


Link to post
Share on other sites
Quote:
Original post by johnstanp
I understood that he wanted to know how the gravitational forces could affect the rotation of his spaceshift(angular momentum).
Yeah, I wasn't sure if that's what he wanted. Azh321, do you want the player's ship to rotate due to gravity, or just get pulled by gravity?

Share this post


Link to post
Share on other sites
This seems a lot more complicated than I was expecting, luckily im currently taking calc 3 :) I will have to look over the math when I get back to my desktop.

To answer your question johnstanp, im not sure yet. I really need to reference a similar game to see how it deals with it. Im thinking I do want the ship to rotate to point in the direction that its currently moving towards, so I will need to have a separate variable for the angle and for the actual rotation of the player.

Share this post


Link to post
Share on other sites


def gravitate(planet, body):

dx = planet.x - body.x
dy = planet.y - body.y

dist = sqrt((dx*dx) + (dy*dy))

#normalize dx and dy
dx /= dist
dy /= dist

force = (body.mass * planet.mass)/(dist*dist)

dx *= force
dy *= force

return (dx,dy)



Just add dx & dy to your ship's x,y position

Share this post


Link to post
Share on other sites
Quote:
And allowing the arrow keys to change _rotation and theSpeed. How exactly does the gravity come into play, specifically, how does it affect the angle that the player is moving in?
The force exerted by each planet will have an effect mostly on the ship's velocity, but, as has been stated before, will have very little effect on it's angular speed, unless you really want to complicate things.

Each force contributes to a change in the ship's acceleration, related by the know equation . Where F stands for all the accumulated force on the body. To calculate these forces, use something like this:

accumulated_force = vector2d(0,0)
for each planet:
force = compute_force_from_planet_to_ship()
accumulated_force += force
Where you can use, for the gravitational force, the code provided in the above post, except that you will want to return force instead of (dx,dy), and maybe multiply force by some constant, as stated in the link. When you've got this all you can use F=ma and dx/dt=v, dv/dt=a to numerically solve for the velocity and the position, using whatever method you want. To start out simple, even Euler's method should do fine.

Note that if you do this, you don't use an angle to represent the ship's velocity anymore, it really is just the velocity vector. You may want to compute an angle out of it to align the sprite of the ship to the direction it is currently flying to, but that would be computed after that vector.

Share this post


Link to post
Share on other sites
http://www.newgrounds.com/dump/item/40f6b15e7cb536a2eee2a442ae683870

Quick demo of the stuff I gathered from you guys. Use LEFT/RIGHT to change your rotation. I know the numbers need some major tinkering, especially since the "range" of the gravity seems far too short yet gets strong far, far too quickly. Shortly after you get in range of the gravity, it soon gets too strong to pull yourself out of so that needs some fiddling with.

Also, I think I do need the gravity to affect the rotation of the ship, because you cant really do the sling shot manuever or really anything, because as soon as you come into the range of the gravity, you pretty much have to angle yourself away from it in order to not get pulled in.

Share this post


Link to post
Share on other sites
Some time back I wrote these tutorial code samples:

http://www.jernmager.dk/stuff/freebasic/gravity_02.zip

They're very simple examples of physically correct planetary gravitation. Line-by-line commented. Ideal for games.

Cheers,
Mike

Share this post


Link to post
Share on other sites
Quote:
Original post by Azh321
This seems a lot more complicated than I was expecting, luckily im currently taking calc 3 :) I will have to look over the math when I get back to my desktop.

To answer your question johnstanp, im not sure yet. I really need to reference a similar game to see how it deals with it. Im thinking I do want the ship to rotate to point in the direction that its currently moving towards, so I will need to have a separate variable for the angle and for the actual rotation of the player.


Well, you don't need to explicitly do it. Basically, all the equations you need to know, in rigid body dynamics, are:

dx(t)/dt = P(t)/M
dR(t)/dt = w(t) * R(t)
dP(t)/dt = F(t)
dL(t)/dt = T(t)

v(t) = P(t)/M
inverse(I(t)) = R(t) * inverse(Ib) * transpose( R(t) )( provided R(t) is a rotation )
w(t) = inverse(I(t))L(t)

x(t): position
P(t): linear momentum
M: mass
R(t): orientation
w(t): angular momentum
F(t): total force
L(t): angular momentum
T(t): total torque
v(t): linear_velocity
I(t): inertia tensor expressed in world coordinates
Ib: inertia tensor expressed in local coordinates
w(t): angular momentum

in english:
the rate of variation of the position of a rigid body is equal to its velocity,
the rate of variation of the axes of the basis of a rigid body is equal to the cross product of its angular velocity and its axes,
the rate of variation of the linear momentum of a rigid body is equal to the total force applied to it,
the rate of variation of the angular momentum of a rigid body is equal to the total torque applied to it.

This is all you only need for a rigid body simulation. You should be able to compute the forces applied to your body, and the torques they generate and the torques directly generated. Since the equations I posted are differential, you'll need an integration scheme( generally Euler would be sufficient ), that is:

x(t+dt) = x(t) + P(t)/M * dt
R(t+dt) = R(t) + w(t) * R(t) * dt
P(t+dt) = P(t) + F(t) * dt
L(t+dt) = L(t) + T(t)

v(t+dt) = P(t+dt)/M
inverse(I(t+dt)) = R(t+dt) * inverse(Ib) * transpose( R(t+dt) )
( you'll need re-orhonormalizing R(t+dt) from time to time )
w(t+dt) = inverse(I(t+dt))L(t+dt)

For your simulation


/*initialize position, orientation, linear momentum,
and angular momentum of your spaceshift*/


for each frame
force_accumulator = get_force_from_imput();
torque_accumulator = get_torque_from_imput();

for each planet
delta_position = planet.position - spaceshift.position;
squared_dist = squared_distance( delta_position );

force =
gravitational_constant *
( spaceshift.mass * planet.mass / squared_dist ) *
unit_vector( delta_position );
force_accumulator += force;
/*we don't compute the generated torques because the forces are applied
on the center of mass*/

end

spaceshift.force = force_accumulator;
spaceshift.torque = torque_accumulator;
update_state( spaceshift, timestep ) //integration step
end







P.S: here I assume that the size of the spaceshift is not big enough to experience a torque generated by gravitional forces...And even if it was big enough, over time, the spaceshift would come to be oriented in such a way that the generated torque by gravitational forces, becomes null. It is easier to grasp for a single planet acting on the spaceshift.
**edit** w(t)*R(t) is a special operation. Let's call the result M(t).
Then M(t)i = w(t).cross_product(R(t)i) ( M(t)i, ith column of M(t) if the columns of M(t) are the vectors of the orthonormal basis represented by M(t). The same for R(t)i ). So w(t)*R(t) = skew_symmetric_matrix(w(t))*R(t)

[Edited by - johnstanp on March 10, 2010 2:06:24 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this