Realistische Kampf-KI für 2D-Spiele

Bild

Obwohl Close Quarters vorwiegend ein Multiplayer-Spiel ist, müssen noch komplexe KI-Bots vorhanden sein, damit die Spieler weiter spielen können, wenn ihre Internetverbindung schlecht ist oder keine anderen Online-Spieler vorhanden sind. Darüber hinaus spielen Bots in einigen Spielmodi eine wichtige unterstützende Rolle. Daher sollten sie sich glaubwürdig verhalten und eine Reihe komplexer Verhaltensweisen zeigen, einschließlich der Verwendung von Schutzräumen, der Verwendung von Objekten zur richtigen Zeit, der Umgehung der Flanken, des Werfens von Granaten und der Flucht vor ihnen.

Umwelt und Einschränkungen


Die Spielumgebung besteht aus Polygonen. Die meisten Polygone blockieren Bewegung, Sichtbarkeit und Aufnahme, aber es gibt auch „niedrige“ Polygone, die nur die Bewegung blockieren. Die Umgebung ist dicht mit Hindernissen und Schutzräumen bedeckt.

Die KI ist auch durch mehrere technische Faktoren begrenzt. Das wichtigste davon: Der Server, auf dem Bots ausgeführt werden, wenn nur wenige Spieler online sind, sollte schnell an einem kostengünstigen VPS mit mindestens zehn Bots arbeiten. Darüber hinaus sollte die CPU-Auslastung niedrig genug bleiben, um mehrere Serverinstanzen auf demselben VPS zuzulassen, ohne das CPU-Limit zu überschreiten und ohne Sanktionen durch den VPS-Dienstanbieter zu verursachen.


Abbildung 1: Umgebungen


Abbildung 2: Blick vom Gesicht des Spielers auf Hindernisse, die den Blick blockieren (graue Bereiche sind für ihn unsichtbar)

Netz aus Navigation und Sichtbarkeit, taktische Suche nach einem Weg


Bots verwenden ein dichtes Navigationsnetz, das aus diskreten Punkten besteht. Das Netz wird wie folgt generiert: Zunächst werden die Polygone, aus denen die Umgebung besteht, erweitert und kombiniert . Zusätzliche Knoten werden in der Nähe der Ecken hinzugefügt, da diese Orte höchstwahrscheinlich geeignete Schutzpositionen sind. Der resultierende Bewegungsraum wird dann trianguliert , um ein Netz zu erzeugen.


Abbildung 3: Navigationsnetz

Da Bots eine taktische Suche nach dem Pfad durchführen müssen, muss das Navigationsnetz Sichtbarkeitsdaten enthalten, mit denen wir schnell überprüfen können, ob der Knoten Schutz vor dem ausgewählten Feind enthält. Daher enthält jeder Knoten ein Array von 24 Bytes, von denen jedes einen vorberechneten ungefähren Abstand zwischen dem Knoten und dem nächsten Hindernis darstellt, das das Sichtfeld in einer bestimmten Richtung blockiert.


Abbildung 4: Im Knoten gespeicherte Sichtbarkeitsdaten (blaue Linien). Jede Zeile stellt einen Einzelbytewert dar, der die Sichtbarkeit in einer bestimmten Richtung definiert.

Dank dieser Daten können Sie die Grafiken mit dem A * -Algorithmus durchsuchenauf dem Navigationsnetz, in dem Knoten, die für bekannte Feinde geöffnet werden können, ohne kostspielige Sichtlinienprüfungen eine niedrigere Priorität erhalten. Um zu überprüfen, ob ein bestimmter Knoten für den Feind offen ist, bestimmen wir die Richtung und Entfernung vom Knoten zum Feind und prüfen dann, ob diese Entfernung geringer ist als die Entfernung, die im Array-Element gespeichert ist, das dieser Richtung am nächsten liegt. Außerdem können wir überprüfen, ob der Feind auf den Knoten schaut. Dann können wir den Straffaktor auf die Kosten für das Bewegen durch Knoten anwenden, die für Feinde offen sind, und der resultierende Pfad wird dazu neigen, solche Knoten zu vermeiden.

Dieselben Sichtbarkeitsdaten können nicht nur den Pfad zwischen zwei bestimmten Punkten finden, sondern auch für andere „taktische“ Aktionen verwendet werden. Zum Beispiel sucht der Bot Schutz, indem er eine Breitensuche durchführt, und stoppt, sobald er eine geschützte Stelle findet. Mithilfe von Sichtverbindungstests wird überprüft, ob der Standort tatsächlich Schutz bietet. In ähnlicher Weise können wir Angriffspfade aus den Flanken erzeugen, indem wir A * nach dem Ziel durchsuchen. Gleichzeitig werden hohe Bußgelder gegen offene Knoten innerhalb des Zielschießkegels verhängt. Die Suche stoppt, sobald wir einen offenen Knoten außerhalb dieses Feuerkegels erreichen. (Eines der Probleme bei diesem Ansatz besteht darin, dass Bots, die außerhalb des Bereichs liegen, ständig versuchen, näher an das Ziel heranzukommen, und daher zu aggressiv erscheinen. Dies kann wahrscheinlich behoben werden, indem die A * -Heuristik so eingestellt wirddamit sich der Bot nicht direkt zum Ziel bewegt, sondern zu Knoten, die sich in einem ausgewählten Abstand vom Ziel befinden).

Gefühle und Erinnerung an Bots


Damit sich Bots überzeugend verhalten, sollten sie nicht als Betrüger erscheinen. Mit anderen Worten, die Informationen, mit denen der Bot arbeitet, sollten den Informationen des Spielers ähnlich sein. Zum Beispiel sollte der Feind hinter dem Hindernis für den Bot unsichtbar sein, so wie er für den Spieler nicht sichtbar ist.


Es gibt zwei Möglichkeiten, wie ein Spieler die Position eines Feindes erkennen kann: Er kann den Feind sehen oder hören, wie er sich bewegt, schießt oder eine andere Aktion ausführt.

Jeder Bot führt eine Liste bekannter "Fakten" über die Positionen und die Richtung des Blicks der Feinde. Ohne Updates werden diese Fakten nach zehn Sekunden gelöscht. Eine Tatsache, die sich auf einen bestimmten Feind bezieht, wird aktualisiert, wenn der Bot diesen Feind hören oder sehen kann. Wenn ein Bot einen Feind hört, um die Unsicherheit zu simulieren, wird die Position der entsprechenden Tatsache von der tatsächlichen Position des Feindes in zufälliger Richtung und Entfernung verschoben, je nachdem, wie nahe der Bot war (siehe Video, 1:28).


Abbildung 5: Fakten (rosa Kreise) im Speicher des Bots

Verhaltensbaum


In einer früheren Version von Close Quarters verwendete AI STRIPS, eine von FEAR im Jahr 2005 populäre Lösung . In STRIPS wird die Beziehung zwischen verschiedenen KI-Verhaltensweisen vom Programmierer nicht vordefiniert. Stattdessen enthält jedes Verhalten eine Liste binärer Voraussetzungen und Ergebnisse. Jeder Bot hat einen Status des Problems in der Welt und verwendet die Suche in der Grafik A *, um die Reihenfolge der Verhaltensweisen zu finden, um dies zu erreichen. Diese Lösung funktionierte gut, aber ich fand, dass sie für meine Anwendung zu komplex und besser für die KI geeignet war, die komplexe Pläne mit vielen verschiedenen Verhaltensweisen entwickeln musste. In den meisten Fällen kannte ich bereits die Umstände, unter denen der Bot dieses oder jenes Verhalten ausführen musste. Die Verwendung von A * für diesen Algorithmus war daher eine unnötige Verschwendung von CPU-Ressourcen.

Daher verwenden Bots jetzt einen einfachen Entscheidungsbaum und ein einfaches Verhalten. Bei jeder Maßnahme geht der Bot von der Wurzel aus um den Baum herum, bis er das Verhalten erreicht. Wenn dieses Verhalten das gleiche ist wie bereits ausgeführt, setzt der Bot dieses Verhalten fort. Wenn nicht, initiiert der Bot das Verhalten und beginnt, es auszuführen.

Einige Verhaltensweisen können „blockieren“, dh verhindern, dass der Bot den Baum wiederholt durchquert, bis eine bestimmte Bedingung erfüllt ist. Dies ist beispielsweise nützlich, um sicherzustellen, dass Bots in Deckung gehen, bevor Sie sich für einen Angriff entscheiden. Außerdem können sich Verhaltensweisen gegenseitig „aufheben“ und den Bot dazu zwingen, den Baum erneut zu durchlaufen und das Verhalten erneut zu initiieren. Dies ist beispielsweise nützlich, wenn ein Bot aus einer Granate entkommt und eine andere Granate erscheint, die ausgewählte Fluchtpositionen gefährdet.


Abbildung 6: Der derzeit verwendete Entscheidungs- und Verhaltensbaum

Einige sekundäre Verhaltensweisen werden in anderen, allgemeineren Verhaltensweisen codiert. Wenn ein Bot beispielsweise versucht, einen Feind anzugreifen und feststellt, dass sich der Feind nicht in der erwarteten Position befindet, nimmt er an, wo sich der Feind jetzt befinden kann, und berechnet einen neuen Angriffspfad, ohne das Angriffsverhalten zu verlassen.

Lastverteilung


Jeder Bot muss nicht in jedem Rahmen der Physik aktualisiert werden, dh 40 Mal pro Sekunde. Um die CPU-Kosten zu senken, "denkt" jeder Bot nur 20 Mal pro Sekunde (diese Anzahl kann bei Bedarf reduziert werden). Daher wird nur die Hälfte der Bots in jedem Physikzyklus aktualisiert.

Arbeite mit Granaten


Ein ernstes Problem war der sinnvolle Einsatz von Granaten durch Bots. Das Arbeiten mit Granaten ist viel schwieriger als das Schießen, da Granaten von Wänden fliegen können, einen Radius der Zerstörung haben und Zeit zum Werfen haben. Glücklicherweise müssen Bots Granaten nicht perfekt einsetzen, genug Überzeugungskraft.

Die traditionelle Lösung für dieses Problem besteht darin , die Pfade der Granaten in den Navigationsknoten vorab zu berechnen. Wenn sie jedoch implementiert sind, werden der Ladezeit jeder Karte einige Sekunden hinzugefügt, was meinem Ziel widerspricht: Close Quarters sollten Spieler innerhalb von Sekunden nach Spielbeginn in den Kampf werfen.

Daher suchen Bots nach Möglichkeiten, Granaten einzusetzen und die Wege der Granaten im laufenden Betrieb zu berechnen. In jedem Zyklus überprüft der angreifende Bot mehrere mögliche Flugbahnen in einer bestimmten Richtung innerhalb von 60 Grad von der Richtung des ausgewählten Ziels. Wenn eine Granate, die auf einem bewährten Pfad geworfen wird, das Ziel töten kann und das Ziel außer Reichweite ist, wirft der Bot eine Granate. Die überprüfte Richtung wird in jeder AI-Uhr wiederholt.


Abbildung 7: Vom Bot für eine Sekunde überprüfte Richtungen (blassrosa Linien) und getestete Flugbahnen (blaue Kreise) entlang der im aktuellen Maß ausgewählten Richtung (hellrosa Linie).

Das heißt, Bots verwenden nach Möglichkeit Granaten und bewegen sich nicht in eine bestimmte Position, um eine Granate zu werfen. Der vom Bot gewählte Weg, um den Feind anzugreifen, ist jedoch oft ein vernünftiger Weg, um eine Granate zu werfen.

Ein wesentlicher Nachteil eines solchen Systems besteht darin, dass Bots aufgrund der begrenzten Anzahl überprüfter Richtungen die Möglichkeit verpassen, Granaten zu werfen, damit sie von kleinen Hindernissen abprallen. Am auffälligsten ist dies neben den Türen, wo Bots normalerweise die Möglichkeit der Verwendung einer Granate nicht erkennen. Dieses Problem kann gelöst werden, indem mehrere Richtungen in einem Rahmen getestet werden und somit der Winkel zwischen der zu prüfenden Richtung und der nächsten verringert wird.

Bewegung zu mehr menschlichem Verhalten


Ein solches Problem wird schnell offensichtlich: Die Bots sind zu schnell, um den Abzug zu betätigen, da es sehr schwierig ist, sie in einem Einzelkampf zu besiegen. Die durchschnittliche menschliche Reaktionszeit auf visuelle Reize beträgt 250 Millisekunden, aber bei 20 Schlägen pro Sekunde beträgt die maximale Bot-Reaktionszeit nur 50 Millisekunden!

Um dieses Problem zu lösen, habe ich absichtlich eine Verzögerung zwischen dem Moment, in dem der Bot die Gelegenheit zum Schießen erhält, und dem Schuss selbst hinzugefügt, damit seine Reaktionszeit mit der Reaktionszeit einer Person vergleichbar ist.

Weitere Verbesserungen


Die oben vorgestellten Systeme bieten eine starke grundlegende KI, bieten jedoch keine Möglichkeiten für größere Verbesserungen. Zum Beispiel ist das räumliche Denken des Bots jetzt durch seine unmittelbare Umgebung begrenzt. Obwohl der Bot normalerweise versucht, den Feind von der Flanke zu umgehen, verfehlt er häufig die Flankenvermeidungsrouten um große Hindernisse. Außerdem wissen Bots nur grob über die Anwesenheit von Teamkollegen Bescheid, sodass sie sich manchmal an einem Ort ansammeln, anstatt von den Flanken getrennt und umgangen zu werden.

All Articles