Game Engine Math

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. Diese Prüfung arbeitet präzise für die (meist kubische) Hitbox des Objekts aber arbeitet nicht pixelgenau.

public class Player : GameObject
{
    public override void Act()
    {
        bool mouseIsOnMe = IsMouseCursorInsideMyHitbox();
    }
}

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

using System;
using KWEngine3;
using KWEngine3.GameObjects;
using KWEngine3.Helper;

public class GameWorld : World
{
    private Player _p1;

    public override void Act()
    {
        bool mouseIsOnObject = HelperIntersection.IsMouseCursorInsideHitbox(_p1);
        //Alternativ, wenn die Überprüfung nicht exakt sein muss:
        // bool mouseIsOnObject = HelperIntersection.IsMouseCursorInsideHitboxFast(_p1);
        if(mouseIsOnObject == true)
        {
            // Handeln, falls der Cursor auf dem Objekt ist...
        }
    }

    public override void Prepare()
    {
        _p1 = new Player();
        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, um vorab zu prüfen, ob der Cursor überhaupt in der Nähe eines Objekts des gewünschten Typs ist.

  • Die Methode 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…
    • …eine Variable vom Typ der gesuchten Klasse mit Hilfe des out-Schlüsselworts angegeben werden.
      (Das out-Schlüsselwort bedeutet, dass die Methode IsMouseCursorOnAny() Änderungen am Inhalt dieses Parameters vornehmen wird. Im Prinzip kann man das out-Schlüsselwort nutzen, wenn mehr als nur ein Wert zurückgegeben werden soll.
  • Als Rückgabewert bekommt man einen bool-Wert zurück. Ist dieser true, wurde ein Objekt gefunden, und die mit dem out-Schlüsselwort angegebene Variable besitzt einen Inhalt.

Anschließend kann mit Hilfe des (ggf.) zurückgegebenen Objekts geprüft werden, wo genau der Mauszeiger auf dem Objekt liegt. Dies geschieht mit dem Aufruf der Methode GetIntersectionPointOnObjectForRay(). Diese Methode nimmt als Parameter…

  • …das zu prüfende Objekt,
  • die aktuelle Kameraposition,
  • der Strahl von der Kameraposition zum Mauszeiger,
  • die Position des Mauszeigers auf dem Objekt (als Ergebnis via out) und
  • den Oberflächenvektor an dieser Position (als Ergebnis via out).
public class GameWorld : World
{
    public override void Act()
    {
        bool result = HelperIntersection.IsMouseCursorOnAny<Player>(out GameObject g);
        // Alternativ, wenn Prüfung nicht exakt sein muss:
        // bool result = HelperIntersection.IsMouseCursorOnAnyFast<Player>(out GameObject g);

        // Wenn der Mauszeiger näherungsweise über der Hitbox eines Player-Objekts ist:
        if(result == true)
        {
            // Berechne den genauen Schnittpunkt:
            result = HelperIntersection.RaytraceObject(
                g,
                HelperIntersection.GetMouseOrigin(),
                HelperIntersection.GetMouseRay(),
                out Vector3 intersectionPoint,
                out Vector3 faceNormal
            );
            if(result == true)
            {
                // Hier entsprechend handeln!
            }
        }
    }

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

Achtung:
Die Nutzung dieser Methoden 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.


Beispiel für einen Strahl der auf ein Objekt trifft

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.