KI-Programmierung Teil 02: Zielverfolgung und Flucht

Zielverfolgung und Flucht gehören zu den elementarsten Verhaltensweisen eines Computergegners. Für die Implementierung bedarf es nur weniger Codezeilen. Ein einfacher Zielverfolgungs-Algorithmus für ein 2D-Spiel könnte wie folgt aussehen:


if(Player_x > Enemy_x)
    Enemy_x++;
else if(Player_x < Enemy_x)
    Enemy_x--;

if(Player_y > Enemy_y)
    Enemy_y++;
else if(Player_y < Enemy_y)
    Enemy_y--;

Der zugehörige Flucht-Algorithmus sieht dagegen wie folgt aus:

if(Player_x > Enemy_x)
    Enemy_x--;
else if(Player_x < Enemy_x)
    Enemy_x++;

if(Player_y > Enemy_y)
    Enemy_y--;
else if(Player_y < Enemy_y)
    Enemy_y++;

Die Schwäche beider Algorithmen besteht jedoch darin, dass diese die Gegnerbewegung explizit berechnen (gehe nach rechts, gehe nach links, usw.). In der Praxis ist die Bewegung jedoch vom verwendeten Bewegungsmodell abhängig. Beispielsweise kann ein Raumschiff nicht so ohne weiteres seine Flugrichtung ändern wie eine Rakete, ein Hubschrauber verhält sich anders als ein Kampfflugzeug, ein Jeep anders als ein Panzer, usw.
In der Praxis bedeutet dies, dass künstliche Intelligenz und Bewegungsablauf unabhängig voneinander gehandhabt werden müssen.

Die künstliche Intelligenz legt fest, was zu tun ist, das Bewegungsmodell legt fest, wie es zu tun ist!

Diesem Ansatz folgend berechnet der neue Zielverfolgungs-Algorithmus lediglich mögliche Bewegungsoptionen. Wie diese Optionen dann in eine konkrete Bewegung umgesetzt werden, ist Aufgabe des verwendeten Bewegungsmodells.

// mögliche Bewegungsoptionen:
Enemy_IncreasePosX = false;
Enemy_DecreasePosX = false;

Enemy_IncreasePosY = false;
Enemy_DecreasePosY = false;

Enemy_IncreasePosZ = false;
Enemy_DecreasePosZ = false;


// Auswahl der Bewegungsoptionen:

if(PlayerPos.x > EnemyPos.x)
    Enemy_IncreasePosX = true;
else if(PlayerPos.x < EnemyPos.x)
    Enemy_DecreasePosX = true;

if(PlayerPos.y > EnemyPos.y)
    Enemy_IncreasePosY = true;
else if(PlayerPos.y < EnemyPos.y)
    Enemy_DecreasePosY = true;

if(PlayerPos.z > EnemyPos.z)
    Enemy_IncreasePosZ = true;
else if(PlayerPos.z < EnemyPos.z)
    Enemy_DecreasePosZ = true;

Hier nun die Bewegungsoptionen für einen Flucht-Algorithmus:

// Auswahl der Bewegungsoptionen:

if(PlayerPos.x < EnemyPos.x)
    Enemy_IncreasePosX = true;
else if(PlayerPos.x > EnemyPos.x)
    Enemy_DecreasePosX = true;

if(PlayerPos.y < EnemyPos.y)
    Enemy_IncreasePosY = true;
else if(PlayerPos.y > EnemyPos.y)
    Enemy_DecreasePosY = true;

if(PlayerPos.z < EnemyPos.z)
    Enemy_IncreasePosZ = true;
else if(PlayerPos.z > EnemyPos.z)
    Enemy_DecreasePosZ = true;



Eine weitere Möglichkeit besteht darin, einfach die optimale Bewegungsrichtung von der aktuellen Position (WorldSpacePosition) hin zur Zielposition (Destination) zu berechnen.
Auf welche Weise ein Spieleobjekt dann seine Bewegungsrichtung ändert, ist wiederum vom jeweiligen Bewegungsmodell abhängig:

// Zielverfolgung:
MovementDirection = Destination - WorldSpacePosition;
D3DXVec3Normalize(&MovementDirection, & MovementDirection);

bzw.

// Flucht:
MovementDirection = WorldSpacePosition - Destination;
D3DXVec3Normalize(&MovementDirection, & MovementDirection);