PlanetSwitch Planet3DS PlanetVita PSP.de PlanetiPhone Classics Forum

PGN-ID:[?] (Nicht eingeloggt)
Login
Registrieren
PlanetDS PlanetGameboy N-Page.de

-

Sonstiges: Entwicklertagebuch - Der Weg zum eigenen 3DS/Switch-Spiel

Michael Grönert, am 26.12.2016, Seite 19 von 20

Artikel mögen: Weitersagen:



Teil 19: Fizhy in GameMaster einbauen & KI
Das letzte Mal haben wir mit Fizhy Zen ein neues Minispiel fertiggestellt, welches alleinstehend im Google Play Store für Android und Apple App Store für iOS verfügbar ist. Heute wollen wir dieses Spiel als drittes Minispiel in unser Hauptprojekt GameMaster portieren.

Die üblichen Aufgaben beim Portieren
Dieses Mal habe mir eine Art Anleitung erstellt, für die einzelnen Schritte, die immer nötig sind, wenn ich ein neues Spiel einbauen möchte. Ich hoffe damit den Prozess weiter optimieren zu können, damit es in Zukunft noch schneller geht. Nachdem die Dateien aus dem Fizhy-Projekt in das GameMaster-Projekt kopiert wurden, gibt es nämlich vieles zu tun. Ich führe ein neues Spiel-Modul ein, damit man Fizhy via GameGuy starten kann, aber auch eine Schnellstart-Referenz, um den Prozess zum Testen des Minispiels abzukürzen. Vorher hart kodierte Texte müssen nun in die Übersetzungsdateien ausgelagert und von dort ausgelesen werden. Es müssen Referenzen an verschiedene Objekte verteilt werden, damit diese dann entsprechende Infos finden. Beispielsweise muss die GameGuy-Konsole wissen, welches Objekt es zu instanziieren hat, um das Spiel zu starten. Alles in Allem sehr viele kleine Aufgaben die einem keinen Spaß bereiten können. Ein großer Anteil davon ist nötig, bevor das neue Spiel überhaupt erst gestartet werden kann. Weitere Aufgaben wie das Anlegen eines Skilltrees, Achievements und Optionen, oder das Ermöglichen von Spielständen und (Online-) Multiplayer bieten sich erst an, nachdem das Spiel erfolgreich eingebunden wurde.

Leider habe ich einen Punkt im Voraus nicht gut durchdacht. Fizhy Zen ist nicht auf die Art Multiplayer ausgelegt, wie ich ihn umsetzen würde. Das Problem ist die Struktur der Objekte: Spielfeld, Fische, Köder, Angel usw. sind nicht dem Spieler untergeordnet, sondern dem Spiel selbst. Mit anderen Worten, es ist ohne eine große Umstrukturierung im Code nicht möglich, ein Spielfeld pro Spieler zu haben. Denkbar problemlos wäre stattdessen eine Art Koop-Spiel umzusetzen, bei dem zwei Spieler gleichzeitig an einem Spielfeld angeln, doch so habe ich mir das nicht vorgestellt und somit muss ich in den sauren Apfel beißen und vieles umbauen.

Eine künstliche Intelligenz
Im Vergleich zu den beiden bereits vorhandenen Minispielen ist eine KI bei diesem Spiel eine gewaltige Herausforderung. Selten greife ich direkt auf theoretisches Wissen zurück, welches ich mir im Studium angeeignet habe, doch hier fehlt es mir an praktischer Erfahrung. Begriffe wie „Backtracking“, „Breiten-“ und „Tiefensuche“ sowie damit verbundene Vorgänge werden sofort in Erinnerung gerufen. Vielleicht das spannendste Thema, dem ich in diesem Projekt bisher gegenüber stehe. Allerdings muss sehr viel geplant und durchdacht werden, bevor man zu viele Schritte in die falsche Richtung unternimmt. Eine ideale Lösung gibt es hier nicht, solange man den üblichen natürlichen Einschränkungen unterliegt, wie begrenztem Speicherplatz und begrenzter Laufzeit. Perfekt spielen könnte eine KI mit einer Datenbank, mit optimalen Spielzügen für jede mögliche Situation. Diese Option fällt weg, selbst wenn der benötigte Speicherplatz dafür heutzutage weniger das Problem wäre, bräuchte ich dafür womöglich Jahre, sofern ich so etwas überhaupt manuell anlegen könnte. Man kennt das vom Schach - man kann nicht immer alle folgende Züge ausprobieren, um den besten Ablauf zu bestimmen. Hier wird meist eine Kombination aus einem Suchalgorithmus und einer Datenbank wichtiger Züge verwendet.

Ich beginne zunächst damit einen rekursiven Suchalgorithmus vorzubereiten: Eine Funktion, die für jeden eingeworfenen Köder alle erreichbaren Felder auf dem Spielfeld testen soll. In einer vorgegebenen Reihenfolge testet er jede mögliche Köder-Bewegung nacheinander durch. Man kann unterscheiden, ob er zunächst nach links oder rechts geht, also in die Breite (Breitensuche), oder nach unten in die Tiefe (Tiefensuche). Die KI läuft also „Pfade“ im Spielfeld ab. Dies tut sie allerdings nicht im sichtbaren Spielfeld, sondern in einer internen Datenstruktur, welche eine Kopie davon darstellt. Bei jedem Feld, auf dem ein Köder liegen bleiben kann, weil sich unter ihm ein Fisch, ein anderer Köder, oder der Boden befindet, wird eine Testfunktion ausgeführt. Dieser Test soll bestimmen wie gut oder schlecht die Position ist und bewertet sie mit einer Punktzahl. Immer wenn der Köder in eine Sackgasse läuft, also keine weitere Richtung zur Verfügung hat, geht man zum vorherigen Feld zurück und nutzt von dort aus die nächste freie verbliebene Richtung. Dieses Vorgehen nennt man dann Backtracking, in diesem Fall ein rekursives. Jedes Feld welches bereits durchlaufen wurde, wird zudem markiert, damit man es nicht erneut besucht, von einem anderen Feld ausgehend. Am Ende wird der Pfad gewählt, welcher zur Position mit der höchsten Punktzahl führt. Dazu wird bei jedem Test der aktuelle Pfad gespeichert, wenn er die bisher höchste Punktzahl überboten hat.


Zur Veranschaulichung kann ich mir beim Testen die Pfade der Suche ausgeben lassen.

Die Bewertungsfunktion
Unser Suchalgorithmus versucht also verschiedene Lösungen zu bewerten, ohne die Folgen ihres Handelns zu beachten. Ein übliches Vorgehen wäre es, die Punkte zur Bewertung zu nutzen, welche auch der Spieler bekäme. Bei Fizhy wäre das also die Punktzahl für das Einfangen von Fischen. Dass dies hier nicht genügen kann, ist offensichtlich - es sind meist einige Züge im Voraus nötig, um Fische fangen zu können. Außerdem ist es nicht stets die beste Strategie, möglichst schnell viele Fische zu fangen, da man sich so andere Fische verbauen könnte. Zudem habe ich beschlossen, immer nur den aktuellen Zug zu beachten und keine Folgezüge durchzurechnen. Immerhin kann man die nächsten drei Köder sehen, es wäre also fair. Aber ich möchte zunächst vermeiden, dass zu lange Rechenprozesse Probleme verursachen könnten, vor allem auf schwächeren Geräten.

Da ist sie also, die größte Herausforderung in diesem Projekt bisher - die Bewertungsfunktion zum Testen der Positionen. Ausgehend von der zu testenden Position schauen wir für beide Köderteile in jeweils alle vier Richtungen, um zu sehen was für Köder und Fische sich dort befinden. Einfach gesagt möchten wir zählen wie viele gleichfarbige und andersfarbige Objekte sich neben uns befinden und bei gleicher Farbe mehr Punkte geben und bei anderer Farbe weniger oder gar negative. Das ist aber leichter gesagt als getan. Zum einen sollten leere Felder zwischen dem Köder und den umliegenden Objekten eine Rolle spielen. Sie sollten die Wertung insoweit beeinflussen, dass der Köder näher an die relevanten Objekte gelegt werden. Also gewichten wir die Punkte in einem Verhältnis zur Entfernung der Objekte zum aktuellen Feld. Zum anderen sollten gleichfarbige Objekte hinter einem andersfarbigen Objekt nicht mehr, oder nicht viel, zur Bewertung beitragen, da sie mit dem Köder keine direkte Linie bilden können. Außerdem müssen wir auch nicht endlos weit in alle Richtungen schauen, sondern natürlich nur bis zum Rand des Spielfeldes oder einer gewissen Entfernung. Beispielsweise würden sich vier oder mehr gleichfarbige Objekte sofort auflösen, also muss man nur bis zu einer Entfernung von drei oder vier in alle Richtungen schauen. Ein Sonderfall sind Objekte über dem aktuellen Feld: Eventuell würden sich die Köder beim Aufstapeln bereits auflösen, bevor das Objekt erreicht wird. Außerdem muss darauf geachtet werden, dass es überhaupt genügend Platz gibt, um weitere Köderteile unterzubringen mit denen die Kette abgeschlossen werden kann. Demnach müsste man zudem nochmals in die gegenüberliegende Richtung schauen, ob dort bereits gleichfarbige liegen oder noch Platz ist. Dabei muss natürlich auch jeweils das andere Köderteil beachtet werden, welches zum Zeitpunkt des Tests noch kein Teil des Spielfelds ist. Dazu kommt noch die Tatsache, dass man sich so leicht den Einwurfbereich, oben in der Mitte des Spielfelds, verbauen kann. Deshalb sollte man wiederum eine negative Bewertung in Abhängigkeit der Entfernung zum Einwurfpunkt geben.

Wie ihr seht, kommen unzählige kleine Sonderfälle auf, welche das Implementieren schwierig gestalten. Und selbst wenn alles beachtet wird, muss lange mit den Punkten experimentiert und beobachtet werden, um gute Werte zu finden. Im folgenden ein paar Basis-Beispielswerte:

Punkte für gleichfarbigen Fisch: 200
Punkte für gleichfarbigen Köder: 30
Punkte für andersfarbigen Fisch: -150
Punkte für andersfarbigen Köder: -40
Etwas kann aufgelöst werden: 350
Nicht genug Platz um die Kette abzuschließen: -50

Sind alle diese Dinge umgesetzt, finden sich noch weitere Sonderfälle. Etwa ein Fisch, der weit oben liegt und von oben nicht genug Platz bietet, um gefangen zu werden. Wie bereits erwähnt kann dies zur Folge haben, dass dieser von unten nicht erreicht werden kann, da sich ein gleichfarbiger Stapel bereits vorher auflösen würde. Deshalb wird hier die Regel benötigt, andere Farben zu bevorzugen. Außerdem folgt daraus, dass man nach oben mehr Felder kontrollieren muss, als nach unten oder zur Seite. Eine weitere Beobachtung zeigt, dass es schwierig für die KI ist, an verbaute Fische zu kommen, wenn das Auflösen anderer Köderteile an einem anderen Ort, ebenfalls so viele Punkte gibt, wie den Fisch freizuräumen. Also brauchen wir hier wieder eine Regel, welche besagt dass Teile in der Nähe von Fischen bevorzugt aufgelöst werden sollen. Dieses Thema für sich ist bereits ein komplexes Problem. Genau genommen muss für jedes Feld bekannt sein, wie viele Fische in ihrer Umgebung liegen, gewichtet mit deren Entfernungen. Ein so gewonnener Wert kann dann auf die bisherige Bewertung addiert werden. Es ist allerdings nicht einfach, ein gutes Mittelmaß zu finden, so dass der gewünschte Bereich zwar bevorzugt wird, aber nicht ausschließlich bespielt wird.


Hier sieht man die Gewichtungen der Felder in Abhängigkeit zu ihrer Fisch-Nähe.

Die KI ist noch weit davon entfernt perfekt zu spielen - muss sie aber auch nicht, man möchte ja noch gewinnen können. Allerdings befürchte ich, dass sie auch nicht gut genug spielt, um eine Herausforderung für einen fortgeschrittenen Spieler zu sein. Trotzdem muss ich voranschreiten und darf mich nicht zu lange an einer Sache festbeißen, auch wenn ich ungern Dinge unfertig liegen lasse.


Multiplayer
Da die KI-Entwicklung bereits so viel Zeit eingenommen hat, verschiebe ich die Implementierung des Online-Multiplayer fürs Erste. Einen lokalen Multiplayer möchte ich aber gleich umsetzen. Wie zu Beginn dieses Tagebucheintrag erwähnt, ist hierfür eine umfangreiche Umstrukturierung des Codes nötig. Alle Instanzen, die zu einem bestimmten Spieler gehören, müssen diesem untergeordnet werden, anstatt dem Spiel selbst. Selbstredend muss auch die Mechanik angepasst werden. Beispielsweise ist zu entscheiden, wann ein Spiel zuende ist. Wenn wir vier Spieler haben und einer hat seinen Level beendet, ist das Spiel dann für alle vorbei oder können die restlichen noch um den zweiten, dritten und vierten Platz kämpfen? Eine weitere große Neuerung ist, dass die Spieler verschiedene Level spielen können. Also benötigen wir vor dem Start ein weiteres Menü, in dem für alle Spieler dieser festgelegt werden kann.


Jeder Spieler kann in einem anderen Level starten.

Außerdem müssen je nach Spieleranzahl die Positionen der Spielfelder und der UI-Texte angepasst werden. Vor allem wenn wir verschiedene Bildschirmgrößen und Seitenverhältnisse unterstützen wollen, kann dies zu einer Herausforderung werden. Nicht zu vergessen, dass ich noch immer die 3DS-Auflösung unterstütze und auf solch einem kleinen Bildschirm nicht viel Platz ist.


Vier Spieler auf einem 3DS-Bildschirm - es bleibt noch viel zu optimieren.

Skills und Achievements
Zu guter Letzt möchte ich noch kurz auf die anderen oben erwähnten Themen eingehen. Auch Fizhy bekommt einen Fähigkeiten-Baum. Wie gewohnt bieten wir das Erlernen verschiedener KI-Schwierigkeitsgrade an. Dazu kommt die grafische Aufwertung von 2D-Sprites zu dreidimensionalen Modellen und der bereits gezeigte lokale Multiplayer für bis zu vier Spieler.


Diese Fähigkeiten werden bisher angeboten.

Sobald die 3D-Fische erlernt sind, können diese in den Optionen jederzeit aktiviert und deaktiviert werden. Achievements setze ich gleich mehrere um. Teilweise kann ich hier Grafiken aus der alten Fizhy-Version wiederverwerten. Man kann diese Errungenschaften freischalten, indem man Fische fängt, Köder auflöst, Kombos macht, Spiele gewinnt und schließlich alle Achievements gesammelt hat.


Ein paar simple Grafiken für die Fizhy-Achievements

Damit möchte ich den heutigen Tagebucheintrag abschließen - da ist ganz schön was zusammengekommen. Und das obwohl ich die Themen nur ankratze und vieles gar nicht behandle. Das nächste Mal möchte ich auf die Community eingehen, welche hinter solch einem Projekt stehen sollte. Sie ist in vielerlei Hinsicht unerlässlich. Neben der Gesellschaft gleichgesinnter stehen weitere Aspekte im Vordergrund, von reiner Informationsfindung über Support bis Marketing.

Ihr möchtet die Auszüge aus dem Leben eines Entwicklers lieber in englischer Sprache lesen? Unter diesem Link findet ihr die englische Version dieses Tagebucheintrags!


Gehe zu Seite:
Vorherige Seite | Nächste Seite

ANZEIGE:
Kommentare verstecken

- Kommentare


- Noch keine Kommentare vorhanden -

Um Kommentare zu schreiben, bitte oben einloggen oder jetzt Registrieren!