KWEngine, Teil 11: Mehr Mauszeigerinteraktionen

1) Wie überprüfe ich, ob der Mauszeiger überhaupt auf einem Objekt liegt?

Jedes GameObject kann für sich prüfen, ob sich der Mauszeiger aktuell über ihm befindet:

public class Player : GameObject
{
    public override void Act(KeyboardState ks, MouseState ms)
    {
        bool mouseIsOnMe = IsMouseCursorInsideMyHitbox(ms);
    }
}

Um dies für andere Objekte zu prüfen (z.B. aus Sicht der Welt-Klasse), kann die Methode auch statisch aufgerufen werden:

public class GameWorld : World
{
    private Player p1;

    public override void Act(KeyboardState ks, MouseState ms)
    {
        bool mouseIsOnObject = HelperIntersection.IsMouseCursorInsideHitbox(p1, ms);
    }

    public override void Prepare()
    {
        p1 = new Player();
        p1.SetModel("KWCube");
        p1.IsCollisionObject = true;
        AddGameObject(p1);
    }
}

2)
Wie überprüfe ich die genaue Position des Mauszeigers auf einem Objekt?

Im folgenden Beispiel wird zunächst eine leere Vector3-Instanz (intersectionPos) angelegt, die später den Schnittpunkt mit dem unter dem Mauszeiger liegenden Objekt beinhalten soll.

Anschließend wird die Methode IsMouseCursorOnAny() aufgerufen.

  • Diese nimmt zunächst in spitzen Klammern eine Art Filter entgegen, so dass z.B. nur Objekte der Klasse Player geprüft werden.
  • In den runden Klammern muss dann…
    • …die Position des Mauszeigers (bzw. das gesamte MouseState-Objekt weitergereicht werden und
    • auch die Variable intersectionPos in Verbindung mit dem out-Schlüsselwort.
      (Das out-Schlüsselwort bedeutet, dass die Methode IsMouseCursorOnAny() Änderungen am Inhalt dieses Parameters vornehmen kann. Im Prinzip kann man das out-Schlüsselwort nutzen, wenn mehr als nur ein Wert zurückgegeben werden soll.
  • Als Rückgabewert bekommt man dann ein Objekt der in spitzen Klammern definierten Klasse zurück.
    Dieses Objekt hat den Wert null, wenn sich kein Objekt des angegebenen Typs unterhalb des Mauszeigers befindet.
    Wenn das Objekt nicht null ist, dann ist dort das Objekt enthalten, das sich unter dem Mauszeiger befindet und
  • in intersectionPos ist die genaue Position des Mauszeigers auf der Hitbox des Objekts enthalten.
public class GameWorld : World
{
    public override void Act(KeyboardState ks, MouseState ms)
    {
        Vector3 intersectionPos;
        Player p = HelperIntersection.IsMouseCursorOnAny<Player>(ms, out intersectionPos);
        if(p != null)
        {
            Console.WriteLine("Mouse is on Player object at " + intersectionPos);
        }
    }

    public override void Prepare()
    {
        // ...
    }
}

Achtung:
Die Nutzung dieser Methode sollte nur dann erfolgen, wenn wirklich die exakte Position auf der Hitbox benötigt wird, da der dahinter liegende Algorithmus viele Berechnungen ausführen muss.


3)
Wie prüfe ich die genaue Position eines Strahls auf einem bestimmten GameObject?

Beispiel für einen Strahl der auf ein Objekt trifft

Wenn Sie bereits wissen, für welches GameObject eine Prüfung ausgeführt werden soll, können Sie stattdessen den folgenden Algorithmus verwenden. Dieser setzt voraus, dass sie sowohl den Ursprung als auch die Richtung des Strahls kennen. Sowohl Ursprung als auch Richtung müssen als Vector3-Objekt vorliegen.

public class GameWorld : World
{
    private Player p1;

    public override void Act(KeyboardState ks, MouseState ms)
    {
        // Startpunkt des Strahls:
        Vector3 rayOrigin = new Vector3(25, 25, 25); 
 
        // Richtung des Strahls (muss normalisiert werden!)
        Vector3 rayDirection = new Vector3(-1, -1, -1);
        rayDirection.NormalizeFast();

        // Test auf Kollision des Strahls mit dem Objekt p1:
        Vector3 intersectionPos;
        bool objectHit = 
            HelperIntersection.GetRayIntersectionPointOnHitbox(
                p1, 
                rayOrigin, 
                rayDirection, 
                out intersectionPos);

        // Wenn die Methode 'true' zurückgegeben hat,
        // ist der Schnittpunkt in 'intersectionPos' enthalten:
        if(objectHit == true)
        {
            Console.WriteLine("object was hit at: " + intersectionPos);
        }
    }
    
    public override void Prepare()
    {
        p1 = new Player();
        p1.SetModel("KWCube");
        p1.IsCollisionObject = true;
        AddGameObject(p1);
    }
}

Im obigen Beispiel sind Ursprung und Richtung des Strahls immer gleich. Sie müssen dann in Ihrem Szenario dafür sorgen, dass diese beiden Angaben immer die Werte haben, die für Ihren Anwendungsfall sinnvoll sind.

Schreibe einen Kommentar

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