Monday, January 17, 2011

Multi-planet prototyping

The past couple of weeks I've been working on a prototype of multi-planet gameplay for my lunar lander game. Results are not terribly encouraging, so far.

One of the big problems is figuring out how to miniaturize the solar system without getting totally wacky gravity. On Earth's surface (if I've done my calculations right) the acceleration due to the sun is about 1600 times weaker than the acceleration due to the Earth itself. Thus it doesn't much matter where the sun is in the sky; up is always pretty much the same direction.

I would like to have a smaller, denser solar system to cut down on travel times between planets. Unfortunately in my experiments so far this results in slanted gravity as the sun and other nearby bodies move across the sky.

Our solar system has about 99.9% of its mass in the sun. Thus, there's very little gravitational influence from one planet to another. As I distribute more of the solar system's mass to the planets this makes it harder to fly between them due to the perturbations. (It would also make their orbits unstable but I'm restricting them to only pay attention to the sun's gravity.)

I'm also hitting numerical precision issues as I expand the play area, so I'm trying to track those down.

I may end up falling back to having an “overworld map” for travel between planets, similar to Gravitar. This would lose some of the wow factor that continuous flight between planets would have, but you could operate on different time scales in the two modes and reduce boredom and precision problems.

8 comments:

kometbomb said...

I "solved" a similar problem by having only the planet with the strongest local gravity affect the player. The planets itselves would orbit on fixed ellipses.

James McNeill said...

I'll give that a try. My concern is that it will produce noticeable discontinuities at the boundaries between influence areas. I have various trajectory plots that could make it obvious. Maybe it won't be too bad though.

owen said...

I hate physics but maybe you are not calculating the mass of the player in relation to the other objects. I guess that the way gravity works is that the gravity of bigger objects only affect objects that are as big as they are. hence the sun's gravity only affects the planets (the next biggest objects). Then the planet's gravity only affects the player and the moons. So the sun realy doesn't affect the player because he is too small. Hope that makes some sense. So as the player escapes the one planets gravity, then the gravity of the next closest thing bigger that he is the gravity that he should be attracted to.

James McNeill said...

Owen,

Sorry for getting back so late.

The force of gravity between two bodies is something like this:

F = (m1 * m2) / d^2

It's proportional to both masses, and inversely proportional to the square of the distance between them. Since acceleration is force divided by mass, each body's acceleration effectively proportional to the other body's mass (and inversely proportional to the squared distance between them):

a1 = m2 / d^2
a2 = m1 / d^2

If the spacecraft's mass is very small relative to the planet then the planet's acceleration due to the spacecraft is negligible. As you move from planet to planet, it's that "inversely proportional to the squared distance" part that rapidly attenuates one planet's influence and increases another's.

owen said...

no prob, I had the page in my feed reader. don't have a clue what you just said but I'll take you word for it. lol. Sounds like you have it solved unless you are having problems with many to one attenuation.

Just last night I tried hacking together a system but I'm getting a weird 240 number. What's wrong with this? I pass the center point to the function and the box spins around it;

void planets(float x, float y, float z ){

float gap=105; //distance from center point
float d=360, dx=0, dy=0;
static float ra;

ra+=0.3;
if(ra > 240) ra=0; //magic number

dx = cosf( M_PI * 3.0f * ra / d );
dy = sinf( M_PI * 3.0f * ra / d );

do_draw_box( x+(gap * dx), y+(gap * dy), z, 0, YELLOW, 13, 13, 13 );
//do_draw_box( b.x+(gap * dy), b.y+(gap * dx), b.z, a, b.colour, 3, 3, 3 );

}

James McNeill said...

There are 2.0*M_PI radians in a full circle (so 180 degrees = M_PI radians). If you change your degrees-to-radians computation to this:

float radians = ra * M_PI / 180;
dx = cos(radians);
dy = sin(radians);

...then ra can be wrapped at 360 instead of 240.

owen said...

cool thanx

zproxy said...

Do post a screenshot or concept imagery! :)