
Einleitung
Kollisionen werden in KWEngine auf folgende Weise stattfinden:
- Eine
GameObject-Instanz bittet die Engine, eine Liste mit den Objekten zu erstellen, mit denen die Instanz zum Zeitpunkt des aktuellen Frames kollidiert. - Die Engine sucht nach allen Objekten, die sich zum aktuellen Zeitpunkt in der Nähe der aufrufenden Instanz befinden und prüft dann für jedes dieser Objekte, ob es mit der aufrufenden Instanz kollidiert.
- Wenn die Engine gebeten wurde, nur nach einer Kollision zu suchen, wird das erste Objekt zurückgegeben, für das eine Kollision festgestellt wurde. Alle nachfolgenden Kollisionen werden ignoriert.
Sollte keine Kollision festgestellt werden, wird der Wertnullzurückgegeben. - Wenn die Engine stattdessen gebeten wurde, alle Kollisionen zu erfassen, erstellt sie eine Liste aller Kollisionen (Intersections). Diese Liste wird der aufrufenden
GameObject-Instanz als Rückgabewert zurückgegeben. Diese Liste kann leer sein, wenn keine Kollisionen festgestellt werden.
- Wenn die Engine gebeten wurde, nur nach einer Kollision zu suchen, wird das erste Objekt zurückgegeben, für das eine Kollision festgestellt wurde. Alle nachfolgenden Kollisionen werden ignoriert.
- Der/die Programmierer/-in muss dann manuell entscheiden, wie auf die Kollisionen reagiert wird.
Wird z.B. genau eine Kollision gefunden, erhält die GameObject-Instanz diese in Form eines Intersection-Objekts. In diesem Objekt sind folgende Informationen zu finden:
- Ein Verweis auf das Kollisionsobjekt, so dass je Objektart unterschiedlich reagiert werden kann.
- Der „minimale Translationsvektor“ (kurz: MTV), der angibt, wie man die eigene Instanz verschieben müsste, um die Kollision rückgängig zu machen.
In der oben abgebildeten Skizze ist der MTV als roter Pfeil eingezeichnet und würde für Objekt A (grün) andeuten, dass eine Bewegung nach rechts die Kollision „ungeschehen“ machen würde.
Bevor die eigentliche Überprüfung stattfinden kann…
…müssen die betroffenen Objekte noch so eingestellt werden, dass sie für die Kollisionsprüfung aktiviert sind:
public class GameWorld : World
{
public override void Prepare()
{
Player p = new Player();
p.SetPosition(+5, 0, 0);
p.IsCollisionObject = true; // Das ist NEU!
AddGameObject(p);
Enemy e = new Enemy();
e.SetPosition(-5, 0, 0);
e.IsCollisionObject = true; // Das ist NEU!
AddGameObject(e);
}
}
Im obigen Codebeispiel werden zwei Objekte (eines vom Typ Player, das andere vom Typ Enemy) erzeugt. Bei beiden Objekten (p und e) wird die Eigenschaft IsCollisionObject auf true gesetzt. Nur dann werden beide Objekte für die Kollisionsprüfung betrachtet.
Überprüfung aller objektbezogenen Kollisionen
Verwendet man die Methode GetIntersections(), wird eine Liste von Kollisionen (Intersection-Instanzen) zurückgegeben. Diese kann dann z.B. in einer foreach-Schleife durchlaufen werden und auf jede Kollision individuell reagiert werden:
public class Player : GameObject
{
public override void Act()
{
MoveOffset(-0.1f, 0f, 0f);
// Erfrage eine Liste aller Kollisionen des Objekts mithilfe von GetIntersections():
List<Intersection> intersections = GetIntersections();
// Durchlaufe in einer foreach-Schleife alle Kollisionen.
// In jedem Schleifendurchgang heißt die gerade betrachtete Kollision 'i':
foreach(Intersection i in intersections)
{
// Erfrage von der Kollision i das verantwortliche Objekt:
GameObject collider = i.Object;
// Handelt es sich dabei um ein Objekt der Klasse 'Enemy'?
if(collider is Enemy)
{
// Referenz auf das exakte Kollisionsobjekt mit der korrekten Klasse erhalten:
Enemy e = collider as Enemy;
KWEngine.LogWriteLine("Kollision mit Enemy");
}
// Erfrage von der aktuellen Kollision den MTV:
Vector3 mtv = i.MTV;
// Beweg dich nach den Vorgaben des MTV, um die
// eigene Position so auszurichten, dass du nicht
// mehr mit dem Objekt kollidierst:
MoveOffset(mtv);
}
}
}
Überprüfung von genau einer Kollision
Wenn Sie sich sicher sind, dass die Instanz definitiv nur mit einer anderen Instanz kollidieren kann, können Sie stattdessen auch nur nach der erstbesten Kollision suchen:
public class Player : GameObject
{
public override void Act()
{
// Erst Bewegungen ausführen:
MoveOffset(-0.1f, 0f, 0f);
// Die Engine bitten, nach genau einer Kollision zu suchen:
Intersection i = GetIntersection();
// Wenn es eine Kollision gibt, dann ist i NICHT null.
if(i != null)
{
// In der Kollision i ist ein Verweis auf
// das Kollisionsobjekt:
GameObject collider = i.Object;
// Das Objekt ist immer vom allgemeinen Typ 'GameObject'.
// Es kann aber gefragt werden, welche Objektart (Klasse)
// tatsächlich dahinter steckt:
if(collider is Enemy)
{
// Referenz auf das exakte Kollisionsobjekt mit der korrekten Klasse erhalten:
Enemy e = collider as Enemy;
KWEngine.LogWriteLine("Enemy berührt!");
}
// i wird um den MTV gebeten (ein Vector3-Objekt):
Vector3 mtv = i.MTV;
// Die Player-Instanz bewegt sich entlang des MTV
// um nicht mehr mit dem Objekt zu kollidieren:
MoveOffset(mtv);
}
}
}

Schreibe einen Kommentar