Spielephysik (game physics): Planetenbewegung

Elite 2 Frontier gilt als das erste Spiel, in dem Gravitationskräfte auf Planeten und Raumschiffe korrekt simuliert werden. Es ist sogar möglich, so genannte Swing-By-Manöver zu fliegen, bei denen ein Raumfahrzeug im Einflussbereich des Gravitationsfelds eines Planeten zeitweilig von diesem mitgezogen wird, wobei sich seine Fluggeschwindigkeit relativ zur Sonne entweder erhöht oder erniedrigt (siehe hierzu http://de.wikipedia.org/wiki/Swing-by).

Planeten werden durch zwei Kräfte auf ihrer Bahn (Orbit) gehalten, die zwar vom Betrag her gleich groß sind, aber in entgegengesetzte Richtungen wirken. Die Zentrifugalkraft (Fliehkraft) zeigt von der Sonne weg und versucht einen Planeten gewissermaßen aus der Bahn zu schleudern. Die Zentripetalkraft zeigt in Richtung der Sonne und kompensiert die Fliehkraft vollständig. Ursache der Zentripetalkraft ist die Massenanziehung (Gravitation) der Sonne, die durch das Newtonsche Gravitationsgesetz beschrieben wird:

F = Kraftrichtung * G * (m(Planet) * m(Sonne)) / Distanz(Planet zur Sonne)2, G := GravityConstant

Für die resultierende Gravitationsbeschleunigung gilt wegen a = F / m:

a = Beschleunigungsrichtung * G * m(Sonne) / Distanz (Planet zur Sonne)2

Im ersten Simulationsschritt müssen die Beschleunigungsrichtung sowie die Distanz zwischen Planet und Sonne bestimmt werden:

Direction = SunPosition – PlanetPosition;
Distance = Normalize3DVector(&Direction, &Direction);

Im nächsten Schritt kann der Betrag der Beschleunigung (Acceleration) berechnet werden:

AccelerationAmount = Gravity_Constant*Mass_Sun/(Distance*Distance);

Mithilfe von Beschleunigungsrichtung und Beschleunigungsbetrag kann nun die neue Planetengeschwindigkeit berechnet werden:

PlanetVelocity += AccelerationAmount*SimulationTime*Direction;

Im letzten Schritt wird schließlich die neue Position des Planeten berechnet:

PlanetPosition += PlanetVelocity*SimulationTime;

Hier das Ganze noch einmal zusammengefasst:


long NumSimulationStepsPerFrame = 2;

float SimulationTime = FrameTime/NumSimulationStepsPerFrame;

D3DXVECTOR3 SunPosition, PlanetPosition, PlanetVelocity, Direction;

float AccelerationAmount, Distance;
const float Gravity_Constant = 1.0f;


for(long i = 0, i < NumSimulationStepsPerFrame; i++)
{
    // hier die Beschleunigung ermitteln:
    Direction = SunPosition – PlanetPosition;
    Distance = Normalize3DVector(&Direction, &Direction);
    AccelerationAmount = Gravity_Constant*Mass_Sun/(Distance*Distance);

    // neue Geschwindigkeit berechnen:
    PlanetVelocity += AccelerationAmount*SimulationTime*Direction;

    // neue Position berechnen:
    PlanetPosition += PlanetVelocity*SimulationTime;
}