Birthday Sale! Up to 40% off unlimited courses & creative assets Birthday Sale! Save up to 40%!
Advertisement
  1. Game Development
  2. Roguelike
Gamedevelopment

Wie können Sie Ihr erstes Roguelike machen?

by
Difficulty:IntermediateLength:LongLanguages:

German (Deutsch) translation by Valentina (you can also view the original English article)

Roguelikes standen in letzter Zeit im Rampenlicht, mit Spielen wie Dungeons of Dredmor, Spelunky, The Binding of Isaac und FTL, die ein breites Publikum erreichten und von der Kritik hoch gelobt wurden. Roguelike-Elemente, die seit langem von Hardcore-Spielern in einer winzigen Nische genossen werden, tragen jetzt dazu bei, vielen bestehenden Genres mehr Tiefe und Wiederspielbarkeit zu verleihen.

Wayfarer a 3D roguelike currently in development
Wayfarer, ein 3D-Roguelike, das derzeit entwickelt wird.

In diesem Tutorial erfahren Sie, wie Sie mit JavaScript und der HTML 5-Game-Engine Phaser ein traditionelles Roguelike erstellen. Am Ende haben Sie ein voll funktionsfähiges, einfaches Roguelike-Spiel, das in Ihrem Browser gespielt werden kann! (Für unsere Zwecke wird ein traditionelles Roguelike als ein zufälliger, rundenbasierter Einzelspieler-Dungeon-Crawler mit Permadeath definiert.)

Click to play the game
Klicken Sie, um das Spiel zu spielen.

Hinweis: Obwohl der Code in diesem Tutorial JavaScript, HTML und Phaser verwendet, sollten Sie in fast jeder anderen Codierungssprache und Spiel-Engine dieselbe Technik und dieselben Konzepte verwenden können.


Fertig werden

Für dieses Tutorial benötigen Sie einen Texteditor und einen Browser. Ich verwende Notepad++ und bevorzuge Google Chrome für seine umfangreichen Entwickler-Werkzeugs, aber der Arbetsablauf ist mit jedem von Ihnen ausgewählten Texteditor und Browser nahezu identisch.

Sie sollten dann die Quelldateien herunterladen und mit dem init-Ordner beginnen. Dies enthält Phaser und die grundlegenden HTML- und JS-Dateien für unser Spiel. Wir werden unseren Spielcode in die aktuell leere Datei rl.js schreiben.

Die Datei index.html lädt einfach Phaser und unsere oben genannte Spielcode-Datei:


Initialisierung und Definitionen

Vorerst werden wir ASCII-Grafiken für unser Roguelike verwenden - in Zukunft könnten wir diese durch Bitmap-Grafiken ersetzen, aber im Moment erleichtert die Verwendung von einfachem ASCII unser Leben.

Definieren wir einige Konstanten für die Schriftgröße, die Abmessungen unserer Karte (d.h. die Ebene) und wie viele Akteure darin erscheinen:

Lassen Sie uns auch Phaser initialisieren und auf Tastatur-Key-Up-Ereignisse warten, da wir ein rundenbasiertes Spiel erstellen und für jeden Tastendruck einmal handeln möchten:

Da Standard-Monospace-Schriftarten in der Regel etwa 60% so breit wie hoch sind, haben wir die Leinwandgröße auf 0.6 * the font size * the number of columns. Wir sagen Phaser auch, dass es unsere create()- Funktion sofort nach Abschluss der Initialisierung aufrufen soll. Zu diesem Zeitpunkt initialisieren wir die Tastatursteuerelemente.

Sie können das Spiel bisher hier ansehen - nicht, dass es viel zu sehen gibt!


Die Karte

Die Kachelkarte stellt unseren Spielbereich dar: eine diskrete (im Gegensatz zu einer kontinuierlichen) 2D-Anordnung von Kacheln oder Zellen, die jeweils durch ein ASCII-Zeichen dargestellt werden, das entweder eine Wand (#: Blockbewegung) oder einen Boden (.: blockiert nicht die Bewegung):

Verwenden wir die einfachste Form der prozeduralen Generierung, um unsere Karten zu erstellen: zufällig entscheiden, welche Zelle eine Wand und welche einen Boden enthalten soll:

Dies sollte uns eine Karte geben, auf der 80% der Zellen Wände und der Rest Böden sind.

Wir initialisieren die neue Karte für unser Spiel in der Funktion create(), unmittelbar nachdem wir die Listener für Tastaturereignisse eingerichtet haben:

Sie können die Demo hier ansehen - auch hier gibt es nichts zu sehen, da wir die Karte noch nicht gerendert haben.


Der Bildschirm

Es ist Zeit, unsere Karte zu zeichnen! Unser Bildschirm besteht aus einem 2D-Array von Textelementen, die jeweils ein einzelnes Zeichen enthalten:

Durch das Zeichnen der Karte wird der Inhalt des Bildschirms mit den Werten der Karte gefüllt, da beide einfache ASCII-Zeichen sind:

Bevor wir die Karte zeichnen, müssen wir den Bildschirm initialisieren. Wir kehren zu unserer Funktion create() zurück:

Sie sollten jetzt eine zufällige Karte sehen, wenn Sie das Projekt ausführen.

Click to view the game so far
Klicken Sie hier, um das bisherige Spiel anzuzeigen.

Akteure

Als nächstes folgen die Akteure: unser Spielercharakter und die Feinde, die sie besiegen müssen. Jeder Akteur ist ein Objekt mit drei Feldern: x und y für seine Position in der Karte und hp für seine Trefferpunkte.

Wir behalten alle Akteure im actorList-Array (das erste Element ist der Player). Wir behalten auch ein assoziatives Array mit den Standorten der Akteur als Schlüssel für die schnelle Suche bei, damit wir nicht die gesamte Liste der Akteur durchlaufen müssen, um herauszufinden, welcher Akteur einen bestimmten Ort einnimmt. Dies wird uns helfen, wenn wir die Bewegung und den Kampf codieren.

Wir erstellen alle unsere Akteure und weisen jedem eine zufällige freie Position in der Karte zu:

Es ist Zeit, die Akteure zu zeigen! Wir werden alle Feinde als e und den Spielercharakter als Anzahl der Trefferpunkte zeichnen:

Wir verwenden die Funktionen, die wir gerade geschrieben haben, um alle Akteure in unserer Funktion create() zu initialisieren und zu zeichnen:

Wir können jetzt sehen, wie sich unser Spielercharakter und unsere Feinde in der Ebene ausbreiten!

Click to view the game so far
Klicken Sie hier, um das bisherige Spiel anzuzeigen.

Blockierende und begehbare Fliesen

Wir müssen sicherstellen, dass unsere Akteur nicht vom Bildschirm und durch Wände rennen. Fügen wir also diese einfache Überprüfung hinzu, um zu sehen, in welche Richtungen ein bestimmter Schauspieler gehen kann:


Bewegung und Kampf

Wir sind endlich zu einer Interaktion gekommen: Bewegung und Kampf! Da bei klassischen Roguelikes der Basisangriff durch den Wechsel zu einem anderen Akteur ausgelöst wird, behandeln wir beide an derselben Stelle, unserer moveTo()-Funktion, die einen Akteur und eine Richtung nimmt (die Richtung ist der gewünschte Unterschied in x und y zu der Position, in die der Akteur eintritt):

Grundsätzlich:

  1. Wir stellen sicher, dass der Akteur versucht, eine gültige Position einzunehmen.
  2. Wenn sich ein anderer Akteur in dieser Position befindet, greifen wir ihn an (und töten ihn, wenn seine HP-Zahl 0 erreicht).
  3. Wenn es keinen anderen Akteur in der neuen Position gibt, ziehen wir dorthin.

Beachten Sie, dass wir auch eine einfache Siegesmeldung anzeigen, sobald der letzte Feind getötet wurde, und false oder true zurückgeben, je nachdem, ob wir einen gültigen Zug ausgeführt haben oder nicht.

Kehren wir nun zu unserer Funktion onKeyUp() zurück und ändern Sie sie so, dass wir jedes Mal, wenn der Benutzer eine Taste drückt, die Positionen des vorherigen Akteurs vom Bildschirm löschen (indem Sie die Karte oben zeichnen) und den Spielercharakter auf den neuen verschieben Ort, und zeichnen Sie dann die Akteure neu:

Wir werden bald die Variable acted verwenden, um zu wissen, ob die Feinde nach jeder Spielereingabe handeln sollen.

Click to view the game so far
Klicken Sie hier, um das bisherige Spiel anzuzeigen.

Grundlegende künstliche Intelligenz

Jetzt, da sich unser Spielercharakter bewegt und angreift, können wir die Chancen ausgleichen, indem wir die Feinde dazu bringen, gemäß einer sehr einfachen Wegfindung zu handeln, solange der Spieler sechs Schritte oder weniger von ihnen entfernt ist. (Wenn der Spieler weiter entfernt ist, geht der Feind zufällig.)

Beachten Sie, dass es unserem Angriffscode egal ist, wen der Akteur angreift. Dies bedeutet, dass sich die Feinde gegenseitig angreifen, wenn Sie sie genau richtig ausrichten, während sie versuchen, den Spielercharakter im Doom-Stil zu verfolgen!

Wir haben auch eine Game-Over-Nachricht hinzugefügt, die angezeigt wird, wenn einer der Feinde den Spieler tötet.

Jetzt müssen die Feinde nur noch jedes Mal handeln, wenn sich der Spieler bewegt. Dazu müssen Sie am Ende unserer onKeyUp()-Funktionen Folgendes hinzufügen, bevor Sie die Akteure in ihre neue Position ziehen:

Click to view the game so far
Klicken Sie hier, um das bisherige Spiel anzuzeigen.

Bonus: Haxe Version

Ich habe dieses Tutorial ursprünglich in einem Haxe geschrieben, einer großartigen Multi-Plattform-Sprache, die (unter anderem) mit JavaScript kompiliert wird. Obwohl ich die obige Version von Hand übersetzt habe, um sicherzustellen, dass wir eigenwilliges JavaScript erhalten. Wenn Sie wie ich Haxe JavaScript vorziehen, finden Sie die Haxe-Version im Ordner haxe des Quelldownloads.

Sie müssen zuerst den Haxe-Compiler installieren und können den gewünschten Texteditor verwenden und den Haxe-Code kompilieren, indem Sie haxe build.hxml aufrufen oder auf die Datei build.hxml doppelklicken. Ich habe auch ein FlashDevelop-Projekt eingefügt, wenn Sie eine nette IDE einem Texteditor und einer Befehlszeile vorziehen. Öffnen Sie einfach rl.hxproj und drücken Sie F5, um zu starten.


Zusammenfassung

Das ist es! Wir haben jetzt ein ganz einfaches Roguelike mit zufälliger Kartengenerierung, Bewegung, Kampf, KI und sowohl Gewinn- als auch Verlustbedingungen.

Hier sind einige Ideen für neue Funktionen, die Sie Ihrem Spiel hinzufügen können:

  • mehrere Ebenen
  • Einschalten
  • Inventar
  • Verbrauchsmaterial
  • Ausrüstung

Genießen Sie!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.