KWEngine, Teil 3: Objekte steuern

In KWEngine kann jedes Objekt den aktuellen Status des Keyboards und den der Maus erfragen. Die beiden Status stehen der Act()-Methode via Parameter (ks und ms) zur Verfügung.

1) Abfragen einer Keyboard-Taste

public class Player : GameObject
{
    public override void Act(KeyboardState ks, MouseState ms)
    {
        if(ks.IsKeyDown(Key.A))
        {
            MoveOffset(-0.1f, 0f, 0f);
        }
    }
}

Die in der Act()-Methode verfügbare Variable ks kann mit Hilfe der IsKeyDown()-Methode ermitteln, ob eine bestimmte Taste gerade gedrückt bzw. gehalten wird. Im oben abgebildeten Beispiel wird dem Objekt immer dann befohlen, sich entlang der x-Achse nach links zu bewegen, wenn die Taste A gedrückt bzw. gehalten wird.

Da die Act()-Methode bei einem Standardmonitor 60x pro Sekunde aufgerufen wird, würde sich das Objekt bei gedrückter A-Taste somit innerhalb einer Sekunde um sechs Einheiten (60 * -0,1 = -6) nach links bewegt haben.

2) Abfragen einer Maustaste

Das Abfragen einer Maustaste funktioniert auf ganz ähnliche Weise:

if(ms.IsButtonDown(MouseButton.Left))
{

}

3) Auf welche Arten kann sich ein Objekt bewegen?

a) MoveOffset(float x, float y, float z)

Bewegt das Objekt von seiner aktuellen Position aus in Richtung der drei Weltachsen x, y und z.

b) Move(float f)

Bewegt das Objekt von seiner aktuellen Position aus entlang seiner aktuellen Blickrichtung.

c) MoveXZ(float f)

Bewegt das Objekt von seiner aktuellen Position aus entlang seiner aktuellen Blickrichtung, ignoriert dabei jedoch die y-Achse (Höhe). Diese Methode ist z.B. dann sinnvoll, wenn das Objekt seine aktuelle Höhe zwingend beibehalten soll.

4) Auf welche Arten kann sich ein Objekt drehen?

Jedes Objekt in KWEngine blickt zunächst in Richtung der positiven z-Achse:

Standardorientierung jedes Objekts (in Richtung +z)

Um das in der Abbildung gezeigte Objekt in Richtung der positiven x-Achse zu rotieren, könnte der Aufruf
AddRotationY(90);
verwendet werden. Dies bewirkt eine Rotation des Objekts um die (lokale) y-Achse gegen den Uhrzeigersinn.

Objekt nach Rotation um 90° um die (lokale) y-Achse

a) SetRotation(float x, float y, float z)

Setzt eine absolute Rotation des Objekts fest. Die aktuelle Blickrichtung des Objekts spielt dabei keine Rolle – es wird immer von der Standardblickrichtung (entlang der positiven z-Achse) ausgegangen. Das Objekt dreht sich dabei zuerst um seine lokale z-Achse, dann um seine lokale y-Achse und schlussendlich um seine lokale x-Achse.
Negative Gradzahlen bedeuten eine Rotation im Uhrzeigersinn.

b) AddRotationX(float f, bool absolute)

Fügt dem Objekt ausgehend von seiner bisherigen Orientierung eine relative Rotation entlang seiner lokalen x-Achse hinzu.
Der zweite Parameter sorgt (wenn true) dafür, dass die Rotation nicht entlang der lokalen Objektachse, sondern um die Weltachse erfolgt.
Für Rotationen um die y- und z-Achse sind analog die Methoden AddRotationY() und AddRotationZ() zu verwenden.

c) TurnTowardsXYZ(Vector3 target)

Dreht das Objekt so, dass es sich der in target beschriebenen Zielposition zuwendet.
Analog dazu gibt es auch die Methoden TurnTowardsXZ() und TurnTowardsXY().

5) Abfrage der Blickrichtung eines Objekts

a) Der „Look-At“-Vektor

Anhand der Rotationszahlen eines Objekts kann oft nur schwer erkannt werden, in welche Richtung ein Objekt gerade blickt. Deshalb gibt es in der Engine für jedes Objekt den sogenannten „Look-At“-Vektor.

Vector3 myLookAtVector = GetLookAtVector();

Dieser Vektor könnte z.B. diese Werte für x-, y und z haben:
(-1.0, 0.0, 0.0)
In diesem Beispiel würde das Objekt also ausschließlich entlang der negativen x-Achse blicken (siehe folgende Abbildung):

Look-At-Vektor einer Spielfigur, die entlang der negativen x-Achse blickt

Ein anderes Beispiel wäre z.B.:
(0.707, 0.0, 0.707)
Jetzt würde das Objekt sowohl entlang der positiven x-Achse, als auch entlang der positiven z-Achse blicken.
(Die seltsamen Zahlenwerte entstehen übrigens weil der Look-At-Vektor immer die Länge 1 hat.)

b) Strafe-Bewegung mit Hilfe des Look-At-Vektors

Manchmal soll ein Objekt auch ohne First-Person-Modus eine Seitwärtsbewegung ausführen können. Dafür ist es nötig, die aktuelle Blickrichtung abzufragen und dann eine Bewegung entlang einer Richtung auszuführen, die im rechten Winkel zur Blickrichtung liegt.

Vector3 lookAtVector = GetLookAtVector();

// Die folgende Anweisung rotiert den Vektor um 90° nach rechts um die z-Achse. 
// Wenn die Blickrichtung der Kamera entlang der z-Achse verläuft (Standard),
// ist das höchstwahrscheinlich die richtige Rotationsachse.
// Sollte die Kamera entlang der y-Achse nach unten blicken (Vogelperspektive)
// ist eine Rotation um die y-Achse sinnvoller.
Vector3 lookAtVector90 = HelperRotation.RotateVector(lookAtVector, -90, Plane.Z);
if(ks.IsKeyDown(Key.D))
{
    MoveAlongVector(lookAtVector90, 0.1f); // Seitwärtsschritt nach rechts
}

6) Rotation weiterreichen

Möchte eine Instanz der Klasse A eine Instanz der Klasse B erzeugen und dieser neuen Instanz die eigene Rotation (Ausrichtung) übergeben, reicht es aus, den aktuellen Rotationswert zu übergeben:

public class A: GameObject
{
    public override void Act(KeyboardState ks, MouseState ms)
    {
        if(ks.IsKeyDown(Key.Space))
        {
            Quaternion rotationOfA = this.Rotation;

            // Neues Objekt des Typs B erzeugen:
            B instanceOfB = new B();
            b.SetModel("KWCube");

            // Dem neuen Objekt die Rotation von Objekt A zuweisen:
            // (Es blickt danach in die gleiche Richtung)
            b.SetRotation(rotationOfA);

            // Die Welt bitten, das neue Objekt hinzuzufügen:
            CurrentWorld.AddGameObject(b);
        }
    }
}

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.