2D Isometric Medieval RTS
Devlog II
Am Ende meines letzten Devlogs haben ich angekündigt mich das nächste Mal um das Abbauen und Sammeln der Ressourcen zu kümmern. Das ist auch passiert - und noch vieles mehr.
In diesem Beitrag werde ich vor allem auf die Systeme eingehen. Zwar habe ich im Laufe der Zeit auch einige grafische Verbesserungen vorgenommen, doch die werden sich wahrscheinlich noch vielfach ändern. Somit macht es nicht allzu viel Sinn groß darauf einzugehen.
Komponent-System
Ein Pattern, mit welchem ich mich sehr stark angefreundet habe, war das Entity-Component-Pattern, welches man auch schon von Unity kennt. Dieses habe ich mir als Inspiration genommen, möglichst KISS-Nodes zu entwickeln, welche nur eine einzige Aufgabe erfüllen und so eine Einheit oder auch ein Gebäude in ihren Features definieren.
So kann z.B. eine Einheit ein Resource-Storage als Komponente besitzen, aber auch ein Gebäude. Ein Turm kann eine Komponente besitzen, welche es ihm erlaubt einen Fernkampf-Angriff auszuführen, genauso aber auch ein Bogenschütze.
Navigation System
Aus Code-Design Gründen dient die TileMap nun nur mehr als Darstellung des Geländes. Alle Objekte (z.B. Einheiten, Gebäude, Bäume, etc.) sind eigene Nodes, die in der Welt platziert werden.
Ein eigenes Navigation-System, basieren auf Theta* und Flocking hält den Status darüber, welche Felder begehbar sind und welche nicht. Ich hatte viel zu kämpfen mit der Konvertierung der verschiedenen Systeme von Cell-ID bis hin zu den isometrischen Koordinaten auf dem Display.
Letztendlich habe ich nun aber sehr viel mehr Kontrolle über das System. Zusätzlich bildet jedes Objekt als eigene Szene eine atomare Einheit, welche keine große Abhängigkeit mit anderen Systemen hat.
Building Placement
Mit dem aktualisierten Navigation-System habe ich das Feature implementiert, mit welchem Spieler:innen Gebäude platzieren können. Diese selbst können ihre eigene Logik beinhalten und mit der Welt interagieren, wie z.B. als Warenlager dienen oder Spieler:innen die Möglichkeit geben Einheiten auszubilden.
Gebäude lassen sich als Blaupause über die Welt bewegen und färben sich rot, wenn sie nicht platziert werden können. Sei es, weil die benötigten Ressourcen nicht vorhanden sind oder der Platz blockiert ist.
Resource Gathering
Arbeiter können jetzt Ressourcen selbständig sammeln und zum Warenlager bringen. Dabei haben Arbeiter eine interne Kapazität sozusagen eine Maximallast, die sie an Ressourcen tragen können. Ist diese erschöpft, bringen sie die Ressourcen zum nächsten Warenlager.
Realisiert wurde das Verhalten mit einer State Chart, einer erweiterten Version von Finite-State-Machines, welche wegen dem bekannten Problem der State Explosion schnell in ihrer Komplexität ausufern.
Ich muss sagen, dass ich SCs noch nicht zu 100% beherrsche bzw. weiß, wie man sie optimal einsetze. Doch die Vorteile gegenüber FSMs sind schon sehr früh spürbar gewesen.
Combat
Mit den Erkenntnissen über SCs konnte ich auch neue Einheiten entwerfen, wie einen Bogenschützen und einen Kämpfer. Beide erweitern die Basis-Einheit um die Funktion eines Nahkampf- oder Fernkampf-Angriffs.
Mit damit einher kam auch das Konzept von Schaden und Leben. Beides wurde wieder als eigene Komponente implementiert. Ich habe mich auf ein sehr einfaches Schadensmodell festgelegt, welches Resistenzen, Anfälligkeiten und eine Robustheit festlegt, welche den Schaden beeinflussen können.
Game UI
Die UI hat auch eine einfache Implementierung bekommen. Am oberen Bildschirmrand werden, wie schon von anderen RTS gewohnt, die Ressourcen angezeigt und die Möglichkeit das Menü aufzurufen.
Unten werden Informationen über das aktuell ausgewählte Objekt angezeigt. Dabei habe ich für bestimmte Komponenten eine eigene Sub-UI entworfen, wie z.B. die Resource-Storage-Komponente, welche lediglich dafür zuständig ist, zu speichern, wieviele Ressourcen das Objekt besitzt. Je nachdem was für Komponenten das angewählte Objekt besitzt, werden diese Sub-UIs angezeigt.
Dieses System ermöglicht wieder, besonders abwechslungsreiche Objekte zu erschaffen, ohne dabei Rücksicht auf die UI nehmen zu müssen.
Ausblick
Aktuell existiert noch keine Game Loop, also ein wirkliches Ziel und eine antagonistisches Kraft, welche Spieler:innen davon abhalten möchte. Ich weiß nicht, ob ich mich dem gewachsen fühle, eine vollwertige KI zu entwerfen. Doch zunächst möchte ich zumindest den Game Loop schließen, sodass ein einfaches Spiel mit einem Anfang und Ende dabei raus kommt.
Vermutlich werde ich zunächst mit Wellen an Gegnern arbeiten, welche das eigene Lager angreifen. Die Details werden sich noch zeigen.