JavaScript Adventure-game-tutorial

Wir wollen ein einfaches Textadventure programmieren, das man beliebig erweitern kann. Ich werde euch Schritt für Schritt erklären wie man das macht. Es sind keinerlei Vorkenntnisse erforderlich. Das Ergebnis kann man hier schon mal testen:

Abenteuerspiel

Vorbereitung

Um dieses Tutorial durchführen zu können braucht man nur einen Texteditor und einen Browser mit dem man die Datei öffnen kann. Etwas komfortabler kann man die Entwicklung mit einem Code-Editor durchführen. Am Schluss dieses Tutorials verlinke ich auf eine Anleitung, die beschreibt, wie einen Code-Editor einrichtet und wie man seine eigene Webseite erstellen kann, um z.B. sein Spiel allen verfügbar zu machen.

Eine leere HTML Seite

HTML ist die Sprache, welche der Webbrowser versteht. Sie beschreibt, wie die Webseite aussehen soll. Wir machen nämlich ein Abenteuerspiel, das ihr auf einer Webseite hochladen könnt.

HTML verwendet hierzu sogenannte Tags, das ist Englisch und heißt Markierung. Ein wichtiger Tag ist der body-Tag. Zwischen dem öffnenden Tag <body> und dem schließenden Tag </body> steht der Text unserer Webseite.

Eine minimale Webseite hat den folgenden Inhalt:

Datei: index.html

Wir lassen die Webseite etwas abenteuerlicher mit schwarzem Hintergrund und weißer Schrift erscheinen. Dazu brauchen wir einen Stylesheet. Hier definieren wir die Farben für alles, was im body-Tag steht. background-color ist die Hintergrundfarbe und color die Vordergrundfarbe. Wir müssen die Farben auf Englisch schreiben. Beachtet die geschweiften Klammern, die bekommt man auf der deutschen Tastatur durch Herunterdrücken der Alt Gr Taste und nachfolgendem antippen der 7 und 9 Tasten.

Datei: style.css

Damit das sichtbar wird, muss man noch die Datei index.html ändern und diese Zeile einfügen:

<link rel="stylesheet" href="style.css">

Außer dem body Tag könne wir auch andere Tags verwenden z.B. für Überschriften. Überschrift heißt auf Englisch "Heading" und der dazugehörende Tag ist daher <h1>. Damit sieht das noch besser aus:

H1 sind dabei die größten Überschriften. H2 Unterüberschriften, H3 noch kleiner usw.

Und unter der Überschrift kommt ein Paragraf mit Text:

Ist euch das <br/> aufgefallen. Das tanzt aus der Reihe, weil es kein öffnendes und schließendes Tag dazu gibt. Wenn der Schrägstrich am Schluss ist, dann ist es ein Tag was alleine verwendet werden kann. <br/> steht für break und heißt auf Deutsch brechen. Hier bricht also die Zeile, so dass eine neue Zeile begonnen wird.

Das sieht doch schon spannend aus...

Vielleicht den Paragrafen noch in hellgrün und die Überschrift in grau.

Ändere hierzu die Datei: style.css wie folgt:

So das sieht gut aus. Damit wir Befehle ausführen könne brauchen wir ein Eingabefeld:

Datei index.html:

Jetzt kommt code hinzu

Damit wir Ein- und Ausgaben auf dem Browser darstellen können, kennzeichnen wir den Paragraphen und das Eingabefeld mit eindeutigen Identifikationsnamen (id=...):

Da unsere Webseite noch nichts macht, müssen wir noch paar Programme in JavaScript schreiben.

Den folgenden Code gebe ich euch, damit ihr euch nicht um den Kleinkram kümmern müsst:

Datei: script.js

Der code sorgt dafür, dass die Befehle, die ihr eingebt, ausgeführt werden können. Ihr könnt anstatt nimm("Schlüssel") dann im Eingabefeld einfach: nimm schlüssel eingeben. Außerdem definieren wir den console.log Befehl um, damit ihr damit nicht in die normalerweise versteckte Browserkonsole schreibt, sondern in euer Ausgabefeld.

Der erste Befehl "schaue"

Jetzt wird's spannend: Wir schreiben den ersten Befehl, den der Spieler eingeben kann.

Erzeuge eine neue Datei namens: adventure.js

Im Folgenden arbeiten wir nur noch an dieser Datei.

Als erstes brauchen wir Variablen. Die können z.B. Zahlen speichern. Dann muss man nicht immer wieder die gleiche Zahl eintippen. Wir verwenden Variablen für die maximale Größe unseres Spielfeldes:

Datei: adventure.js

let deutet an dass wir jetzt eine Variable deklarieren.

danach können wir den Wert setzen mit

das kann man auch kompakter schreiben mit:

 

wir können die Werte uns im Browser anzeigen lassen indem wir ein

console.log("Xmax="+xmax)

hinzufügen:

Zwischen den Anführungszeichen steht sogenannter String. Ein String ist eine Zeichenkette also einen oder mehrere Buchstaben.

Wir speichern unser Spielfeld in Arrays, das sind Speicherfelder, die haben eine Art Hausnummer. Man fängt hierbei immer bei 0 an zu zählen. Ein Array mit namen arr mit 3 Einträgen erzeugt man, indem man erst ein leeres Array mitlet arr=[] erzeugt:

Wenn wir alle Elemente auflisten wollen, dann geht das einzeln so:

 

Sehr mühselig, wenn man damit hunderte Elemente ausgeben will. Deshalb gibt es die for Schleife:

Wir wollen aber mindestens in einer zweidimensionalen Welt spielen, daher wird unser Spielfeld in einem zweidimensionalen Array wie mit einer Landkarte gespeichert. Hierzu könnt ihr createArray aus der script.js Datei verwenden, der ihr die Anzahl der Elemente in jeder Dimension übergibt. Wir wollen ein Feld mit 10x10 Feldern:

Dann müssen wir noch angeben, wo wir im Spielfeld stehen. Wir wählen die Koordinaten x=5 und y=5:

Jetzt können wir die Welt aufbauen. Wenn wir Felder undefiniert lassen, dann sind das Bereiche, die nicht zugänglich sind. Hier eine einfache Welt:

Ihr seht wir haben den Text in Anführungszeichen geschrieben, das ist wichtig.

Nun schreiben wir die erste Funktion namens: schaue.

Eine Funktion fasst mehrere Befehle zusammen. Wir wollen sowohl den Titel aus ort darstellen als auch die Beschreibung. Verwende hierzu console.log(...) und setze einmal ort[x][y] und dann beschreibung[x][y] ein. Wenn du den Titel fett dargestellt haben willst, muss man in HTML folgendes schreiben:

Wir können das auch aus unserem Programm machen, in dem wir Strings zusammenfügen:

"<b>" + ort[x][y] + "</b>"

Eine Funktion wird durch das Schlüsselwort function eingeleitet gefolgt vom Namen und dann von (). Die Befehle, die dann Ausgeführt werden, wenn ich die Funktion mittels schaue() ausführe werden in geschweiften Klammern zusammengefasst. Hier eine leere Funktion:

Versuche die Funktion zu deinem Code hinzuzufügen und gebe in ihr den Titel fett und die Beschreibung normal aus. Wenn du nicht weiter kommst, hier ist der code:

Gib mal schaue in das Eingabefeld ein... und teste ob alles funktioniert.

Rumlaufen

Um sich auf dem Spielfeld zu bewegen, führen wir neue Befehle ein: n,s,w,o für Norden, Süden, Westen, Osten. Dabei soll man nicht aus dem Spielfeld fallen, d.h. x und y müssen nach der Änderung immer größer oder gleich null sein und immer kleiner als xmax bzw. ymax sein, um das zu prüfen brauchen wir eine wenn-sonst Abfrage. Auf Englisch heißt wenn if und sonst else.

Wir testen das mal. Füge ganz unten im code hinzu:

Beachte, dass man bei der Bedingung das Gleichheitszeichen zweimal eingibt ==.

Das Gegenteil von Gleich ist Ungleich und das gibt man mittels != ein.

Versuchs mal

Wenn man mehrere Bedingungen überprüfen will, kann man if Befehle verschachteln:

Oder man kann "wenn x gleich 0 ist und y gleich null ist", schreiben. Dazu verwendet man ein doppeltes Und-Zeichen &&:

Es gibt auch ein Oder-Zeichen ||. Damit kann man eine Bedingung machen die `wahr ist, wenn z.B. x=5 oder y=5. Für | muss man auf der deutschen Tastatur musst du hierzu die rechte Alt Gr und die Taste links von dem Y drücken. Versuchs mal aus:

Du siehst der Computer versteht x=5 oder y=5 anders als wir Menschen. Für ihn ist das auch wahr, wenn beide gleich 5 sind.

Lass uns jetzt den Code für den Norden, Süden, Westen, Osten schreiben (4 neue Befehle n,s,w,o).

Unsere Bedingungen sind, dass es diesen Raum gibt. Wenn wir in JavaScript eine Variable (z.B.: a) und auch Einträge in einem Array nicht definieren so kann man das überprüfen. In diesem Fall ist a==undefined wahr.

Zusätzlich dürfen wir nicht das Spielfeld verlassen müssen also die Array-Grenzen einhalten.

Wenn man nach Norden geht, muss man prüfen, ob y nach der Erhöhung kleiner als ymax ist:

y+1<ymax.

Wenn man nach Süden geht muss man überprüfen ob y nach der Erniedrigung größer gleich null ist:

y-1>=0

Versuchs mal selbst zu schreiben. Hierbei ist zu beachten, dass man erst die Grenzen überprüft. also z.B. x-1>=0, und dann ort[x-1][y]!=undefined testet. Denn wäre x=0, dann würde ort[-1][y]!=undefined zu einem Fehler führen. x-1>=0 && ort[x-1][y]==undefined ist aber erlaubt, da falls x-1>=0 falsch ist, der zweite Ausdruck nicht mehr ausgeführt wird. Wir Menschen machen das übrigens genauso. Ein Beispiel: Man darf nur über die Fußgängerampel, wenn diese grün ist und kein Rettungsfahrzeug mit Sirene die Straße kreuzt. Wenn der erste Ausdruck falsch ist, die Ampel also rot ist, dann brauche ich mich auch nicht nach einem Rettungsfahrzeug umsehen.

Hier ist die Lösung:

 

Jetzt kann man nehmen

Das Spiel ist langweilig, wenn man nicht Sachen nehmen und geben kann. Hierzu brauchen wir für jeden Raum ein Array, das die Gegenstände angibt, und ein einfaches Array für unseren Besitz. Versuche das erst selbst, dann schaue hier:

Die nimm Funktion muss jetzt erst überprüfen, ob der Gegenstand im Raum ist und ihn dann in unser Array eintragen. Dazu brauchen wir was Neues,nämlich einen Parameter, der der Funktion übergeben wird. Das ist in unserem Fall ein String z.B. "Schlüssel". Wir wollen also in der Funktion z.B. die Variable gegenstand verwenden, um herauszufinden, was wir nehmen wollen. Eine leere Funktion, die einfach nur ausgibt, was wir nehmen wollen sieht so aus:

Wir brauchen noch weitere Befehle um eine richtige Funktion für den Befehl nimm zu programmieren. Zum Hinzufügen von Elementen kann man den Befehl push nehmen und mit arr.splice(i, 1) kann man das i-te Element von einem Array mit dem Namen arr entfernen. Um die Nummer des Elements mit der for schleife zu bekommen kann man folgendes eingeben, versuch's mal aus:

damit solltest du es hinbekommen. Versuchs erst selbst und dann spicke hier:

Hier gibt es einen neuen Befehl return. Dieser Befehl beendet die Schleife sofort und beendet die Funktion, d.h. console.log("So etwas gibt es hier nicht.") wird nicht mehr aufgerufen, wenn der return Befehl zuvor ausgeführt wurde.

Und in seine Tasche schauen

Wir wollen natürlich wissen, was in unserer Tasche ist. Daher versuche mal, den Befehl tasche zu programmieren. Hier kannst du spicken, wenn du Probleme damit hast:

 

Jetzt kann man legen nehmen und rumlaufen

Das Ablegen von Gegenständen mit dem Befehl gib soll jetzt programmiert werden. Hierzu muss der Gegenstand aus deinem besitz entfernen und in den aktuellen ort gelegt werden. Versuche es selbst zu schreiben. Hier ist das Ergebnis:

 

Türen und Gänge

Ein Abenteuerspiel braucht natürlich verschlossene Türen und Geheimgänge, die nur dann sichtbar werden, wenn man einen richtigen Gegenstand in einen Raum legt oder der Person im Raum gibt.

Wir können dann Mauern durch undefinierte Felder in ort und beschreibung erreichen.

Wir machen offene Zugänge zu einem anderen Raum einfach als Räume mit Namen "offen", diese wollen wir dann einfach überspringen und gleich in den nächsten Raum gehen.

Das ist jetzt etwas schwieriger. Wir müssen dafür sorgen, dass zwischen dem Ort "Schloss" und dem Ort der hinter der verschlossenen Tür sich verbirgt, ein weiter Ort liegt, der undefiniert ist. Wenn man dann den Schlüssel im richtigen Raum ablegt, erst dann soll das undefinierte Feld zwischen den beiden Räumen definiert werden. Wir nehmen den String "offen", um kennzuzeichnen, dass wir diesen Raum nicht beschreiben wollen sondern gleich zum nächsten weiter gehen wollen. Keine Sorge, wenn dir das zu komplex erscheint, denn hier ist die fertige Spiel-Logik, welche in der Funktion schaue programmiert werden kann. Wir haben auch n, s, w, o etwas abgeändert, damit wir Räume, welche den Titel "offen" tragen überspringen. Hier das funktionsfertige Programm:

Die finale version von adventure.js

Wir haben die Text Passagen noch so verändert, dass der Benutzer ein paar Tipps über die Befehle bekommt und die Richtungen angezeigt, wohin er gehen kann:

Hier ist die fertige Datei: adventure.js

Tipps beim Aufbau einer Welt

Platziere den Startpunkt mit let x=... und let y=.. bei genügend großen Zahlen. Sonst kannst du die Welt nach Westen und Süden nicht weit erweitern. Wähle also z.B. 50.

Bei Räumen mit Wänden, muss man die Mauern mit berücksichtigen, indem man undefinierte Felder dafür verwendet. Daher zeichne deine Welt am besten auf Karo Papier.

Erweiterungsideen

Füge noch Etagen nach oben und unten hinzu.

Da es keine negativen Einträge in einem Array geben darf, musst du dazu bei

ort[5][5][5] = "Startpunkt"

anfangen.

nach unten geht es dann mit

ort[5][5][4] = "offen"

ort[5][5][3] = "Keller"

Platziert den Keller aber nicht auf ort[5][5][4], denn sonst kann man von jedem Ort in die tiefe Etage gelangen.

Erweitere die Befehle:

z.B: h für "hoch" und r für "runter".

Du kannst auch den Befehl sage einführen, um z.B. Zaubersprüche zu sagen.

Deiner Fantasie sind keine Grenzen gesetzt. Auch Bilder kannst du einfügen.

Das geht mit:

<img src="bild.jpg" alt="Beschreibung des Bildes" width="100" height="50">

Denke daran die Beschreibung des Bildes nicht zu vergessen, schließlich sollen auch Menschen mit Sehbehinderungen in der Lage sein, dein Spiel zu spielen.

Visual studio code editor optimal einrichten und eine eigene Webseite

Siehe hierzu die ersten vier Kapitel meiner Anleitung: https://kiliansinger.github.io/codetricks/