Spielephysik (game physics): Simulation von Beschleunigung und Bewegung (Einführung)

Die Physik spielt bei der Entwicklung von Computerspielen eine immer wichtigere Rolle. So realistisch die Simulationen letzten Endes auch erscheinen mögen, die grundlegende Physik dahinter ist überraschend einfach, denn alle Berechnungen lassen sich auf eine einfache Gleichung – das 2. Newtonsche Axiom – zurückführen:

F = m a      Kraft = Masse mal Beschleunigung.

Diese simple Gleichung besagt, dass man die Beschleunigung eines Spieleobjekts (physikalisch gesehen ein Massenelement) berechnen kann, sofern man nur alle auf das Massenelement einwirkenden Kräfte kennt:

a = F / m      Beschleunigung = Kraft durch Masse.

Über die Beschleunigung lassen sich die aktuelle Geschwindigkeit und Position berechnen. Im einfachsten Fall ergibt sich die neue Position eines Spieleobjekts wie folgt:

Position = Position + Velocity*FrameTime;

bzw.

Position += Velocity*FrameTime;

Ein Physiker würde diese Beziehung in allgemeingültiger Form wie folgt formulieren:

s(t + Δt) = s(t) + v(t) Δt.

Δt ist die Zeitdauer, die zwischen zwei Positionsberechnungen vergeht. Hier haben wir einfach die Zeitdauer zwischen zwei aufeinander folgenden Frames verwendet.
Wirken irgendwelche Kräfte, dann ändert sich natürlich auch die Geschwindigkeit:

Velocity = Velocity + Acceleration*FrameTime;

bzw.

Velocity += Acceleration*FrameTime;

oder wie ein Physiker es ausdrücken würde:

v(t + Δt) = v(t) + a(t) Δt = v(t) + (F(t) / m) Δt,  F(t) = Summe aller Kräfte.

Vor Berechnung der neuen Geschwindigkeit und Position müssen zunächst alle auf das Massenelement einwirkenden Kräfte addiert werden. Die soeben beschriebene Technik – das so genannte Euler-Verfahren – ist zwar sehr einfach, dennoch lässt sie sich immer dann einsetzen, wenn lediglich die Kraftwirkung auf ein einzelnes Objekt (z.B. die Gravitationswirkung der Sonne auf einen Planeten) berechnet werden muss. Verkleinert man den Zeitschritt Δt, dann vergrößert sich die Genauigkeit der Berechnung. Im Grenzfall (Δt->0; Δt->dt) werden die Ergebnisse zwar exakt, doch natürlich können die Zeitschritte aus Performancegründen nicht beliebig verkleinert werden. Nachfolgend ist die Berechnung von zwei Simulationsschritten pro Frame skizziert:

long NumSimulationStepsPerFrame = 2;

float SimulationTime = FrameTime/NumSimulationStepsPerFrame;


for(long i = 0, i < NumSimulationStepsPerFrame; i++)
{
    // hier die Beschleunigung ermitteln:

   
...

    // neue Geschwindigkeit berechnen:
    Velocity += Acceleration*SimulationTime;

    // neue Position berechnen:
    Position += Velocity*SimulationTime;
}