Game Engine Math

KWEngine, Teil 9: Eine simple Sprungmechanik

Um eine vernünftige Sprungmechanik umzusetzen, müssen alle beteiligten Objekte als Kollisionsobjekte markiert werden (IsCollisionObject = true).

Die Player-Klasse sollte außerdem über drei Felder verfügen (siehe Code-Abschnitt unten):

  • Das Feld Status (z.B. string) merkt sich, in welchem Zustand sich die Figur gerade befindet:
    • springend
    • fallend
    • stehend
  • Das Feld Velocity (float) merkt sich die aktuelle Sprungkraft der Figur. Dabei gelten folgende Regeln für die Interpretation des Werts:
    • = 0: die Figur steht
    • > 0: die Figur springt nach oben
    • < 0: die Figur fällt runter
  • Das Feld Gravity (float) gibt die allgemeine Erdanziehungskraft für die Figur vor. Der Wert in diesem Feld wird in der Regel nicht verändert.

Was macht die Spielfigur im Status „stehend“?

  • Wenn die Spielfigur „steht“ und die Sprungtaste gedrückt wird, wechselt der Status der Figur nach „springt“ und die Sprungkraft wird auf einen bestimmten Wert (z.B. 0.75f) gesetzt (hier muss man ein wenig mit den Werten experimentieren).
  • Die Spielfigur wird mit Hilfe der Methode MoveOffset() jeden Frame um die aktuelle Sprungkraft nach oben versetzt (entlang der y-Achse, die in diesem Beispiel ‚oben‘ darstellt).

Was macht die Spielfigur im Status „springend“?

  • Jeden Frame wird die Gravitation von der aktuellen Sprungkraft abgezogen, so dass der Höhenzuwachs der Spielfigur jeden Frame etwas nachlässt.
  • Die Spielfigur wird mit Hilfe der Methode MoveOffset() jeden Frame um die aktuelle Sprungkraft nach oben versetzt.
  • Ist die Sprungkraft <= 0, so wechselt der Status von „springend“ in „fallend“.

Was macht die Spielfigur im Status „fallend“?

  • Jeden Frame wird die Gravitation von der aktuellen Sprungkraft abgezogen, so dass die Sprungkraft negativ wird. Dies ist sinnvoll, da sie ja „fallen“ soll.
  • Die Spielfigur wird mit Hilfe der Methode MoveOffset() jeden Frame um die (inzwischen negative) Sprungkraft nach unten versetzt.

Wann wechselt man den Status von „fallend“ auf „stehend“?

Hier kommt die Kollisionsabfrage zum Tragen:

  • Die Spielfigur holt sich eine Liste all ihrer Kollisionen und prüft für jede Kollision den minimalen Translationsvektor (MTV):
    • Ist der y-Wert des Vektors positiv (> 0), so muss die Spielfigur nach oben versetzt werden, um nicht mehr zu kollidieren.
    • Daraus lässt sich ableiten, dass die Figur eine Kollision unter sich hatte und somit wieder auf dem Boden steht. Der Status kann in diesem Fall auf „stehend“ wechseln.

Beispielcode (Minimalbeispiel)

Das folgende Codebeispiel behandelt lediglich den Kontakt mit dem Boden und dient nur als Einstieg:

Code der Player-Klasse:
using System;
using KWEngine3.GameObjects;
using KWEngine3.Helper;
using OpenTK.Mathematics;

public class Player : GameObject
{
    private string _status = "stand";   // Drei Status für stehen, springen, fallen
    private float _velocity = 0;        // Sprungkraft der Figur (wird verändert)
    private float _gravity = 0.001f;    // Gravitation (bleibt immer gleich)
    
    public override void Act()
    {
        // Wenn die Sprungtaste gedrückt wird und die Spielfigur
        // gerade "steht", dann wird ein Wechsel des Status in 
        // "springt" vollzogen und die anfängliche Sprungkraft
        // in 'velocity' gesetzt:
        if (Keyboard.IsKeyDown(Keys.Up) && _status == "stand")
        {
            _status = "jump";
            _velocity = 0.025f;
        }

        // Anschließend wird überprüft, in welchem Status sich die
        // Spielfigur gerade befindet:
        // Im Status "springt" wird die Figur um die Sprungkraft 
        // nach oben versetzt. Anschließend wird die in 'gravity'
        // gespeicherte Gravitation von der Sprungkraft abgezogen.
        // Ist die Sprungkraft aufgebraucht, wechselt der Status von
        // "springt" zu "fällt".
        if(_status == "jump")
        {
            MoveOffset(0, _velocity, 0);
            _velocity = _velocity - _gravity;
            if(_velocity <= 0)
            {
                _velocity = 0;
                _status = "fall";
            }
        }
        
        // Im Status "fällt" wirkt sich die Gravitation weiter
        // auf die Sprungkraft aus, so dass sie negativ wird.
        // Die Figur fällt mit jedem Frame immer stärker.
        else if(_status == "fall")
        {
            _velocity = _velocity - _gravity;
            MoveOffset(0, _velocity, 0);
        }


        // Um zu prüfen, ob die Figur wieder auf dem Boden
        // angekommen ist, wird eine Kollisionsprüfung gestartet
        List<Intersection> intersectionList = GetIntersections();

        // In einer Schleife wird jede dieser Kollisionen geprüft:
        foreach(Intersection i in intersectionList)
        {
            // Wenn der Status "fällt" ist und die Position der 
            // Spielfigur nach oben korrigiert werden muss, dann
            // ist sie wieder auf dem Boden angekommen.
            // Der Status muss also in "steht" wechseln.
            // Anschließend muss noch der Korrekturvektor (MTV) 
            // in Betracht gezogen werden, damit die Figur nicht mehr
            // "im Boden steckt".
            if(i.MTV.Y > 0 && _status == "fall")
            {
                _status = "stand";
                _velocity = 0;
                MoveOffset(0, i.MTV.Y, 0);
            }
        }
    }
}
Beispielanimation des Sprungs

Beitrag veröffentlicht

in

von

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.