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:
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.
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
<html lang="en"> <head> <meta charset="utf-8"> <title>Abenteuer</title> </head> <body> Mein Abenteuerspiel </body></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
xbody { background-color: black; color: white;}
Damit das sichtbar wird, muss man noch die Datei index.html ändern und diese Zeile einfügen:
<link rel="stylesheet" href="style.css">
xxxxxxxxxx<html lang="en"> <head> <meta charset="utf-8"> <title>Abenteuer</title> <link rel="stylesheet" href="style.css"> </head> <body> Mein Abenteuerspiel </body></html>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:
xxxxxxxxxx<html lang="en"> <head> <meta charset="utf-8"> <title>Abenteuer</title> <link rel="stylesheet" href="style.css"> </head> <body> <h1>Mein Abenteuerspiel</h1> </body></html>H1 sind dabei die größten Überschriften. H2 Unterüberschriften, H3 noch kleiner usw.
Und unter der Überschrift kommt ein Paragraf mit Text:
xxxxxxxxxx<html lang="en"> <head> <meta charset="utf-8"> <title>title</title> <link rel="stylesheet" href="style.css"> </head> <body> <h1>Mein Abenteuerspiel</h1> <p id="output"> Willkommen zu meinem Abenteuerspiel! Tippe 'schaue' und drücke Enter, um dich umzusehen.<br /> </p> </body></html>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:
xxxxxxxxxxbody { background-color: black; color: white;}p{ color: lightgreen;}h1{ color: orange;}So das sieht gut aus. Damit wir Befehle ausführen könne brauchen wir ein Eingabefeld:
Datei index.html:
xxxxxxxxxx<html lang="en"> <head> <meta charset="utf-8"> <title>Abenteuer</title> <link rel="stylesheet" href="style.css"> </head> <body> <h1>Mein Abenteuerspiel</h1> <p id="output"> Willkommen zu meinem Abenteuerspiel! Tippe 'schaue' und drücke Enter, um dich umzusehen.<br /> </p> <input type="text" id="input" /> </body></html>Damit wir Ein- und Ausgaben auf dem Browser darstellen können, kennzeichnen wir den Paragraphen und das Eingabefeld mit eindeutigen Identifikationsnamen (id=...):
xxxxxxxxxx<html lang="en"> <head> <meta charset="utf-8"> <title>Abenteuer</title> <link rel="stylesheet" href="style.css"> <script src="script.js"></script> <script src="adventure.js"></script> </head> <body> <h1>Mein Abenteuerspiel</h1> <p id="output"> Willkommen zu meinem Abenteuerspiel!<br /> </p> <input type="text" id="input" /> </body></html>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
xxxxxxxxxxlet log = console.log
console.log = function (message) { let logger = document.getElementById('output') logger.innerHTML += message + '<br />'}
function input(txt){ let inputField=document.getElementById("input") //extract with regex two space separated words let matches=inputField.value.match(/^\s*(\p{Letter}+)\s*(\p{Letter}*)\s*$/u) try { eval(matches[1]+"(\""+matches[2]+"\")")
} catch (e) { console.log("?") if (e instanceof SyntaxError) { log(e.message) } }
inputField.value="" //scroll to bottom of page window.scrollTo(0, document.body.scrollHeight)}
window.onload = function() { document.getElementById("input").addEventListener("keydown", function(event) { if (event.key === 'Enter') { input() } })}
function createArray(length) { var arr = new Array(length || 0), i = length
if (arguments.length > 1) { var args = Array.prototype.slice.call(arguments, 1) while(i--) arr[length-1 - i] = createArray.apply(this, args) }
return arr}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.
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
xxxxxxxxxxlet xmaxlet ymaxlet deutet an dass wir jetzt eine Variable deklarieren.
danach können wir den Wert setzen mit
xxxxxxxxxxlet xmaxxmax=10let ymaxymax=10das kann man auch kompakter schreiben mit:
xxxxxxxxxxlet xmax=10let ymax=10
wir können die Werte uns im Browser anzeigen lassen indem wir ein
console.log("Xmax="+xmax)
hinzufügen:
xxxxxxxxxxlet xmax=10let ymax=10console.log("Xmax="+xmax)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:
xxxxxxxxxxlet xmax=10let ymax=10
let arr=[]arr[0]="Erstes"arr[1]="Zweites"arr[2]="Zweites"console.log("Größe von arr:" arr.length)Wenn wir alle Elemente auflisten wollen, dann geht das einzeln so:
xxxxxxxxxxlet xmax=10let ymax=10
let arr=[]arr[0]="Erstes"arr[1]="Zweites"arr[2]="Zweites"console.log("Größe von arr:" arr.length)console.log(arr[0])console.log(arr[1])console.log(arr[2])
Sehr mühselig, wenn man damit hunderte Elemente ausgeben will. Deshalb gibt es die for Schleife:
xxxxxxxxxxlet xmax=10let ymax=10
let arr=[]arr[0]="Erstes"arr[1]="Zweites"arr[3]="Zweites"console.log("Größe von arr:" arr.length)for(let el of arr){ console.log(el)}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:
xxxxxxxxxxlet xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)Dann müssen wir noch angeben, wo wir im Spielfeld stehen. Wir wählen die Koordinaten x=5 und y=5:
xxxxxxxxxxlet xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)
let x=5let 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:
xxxxxxxxxxlet xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)
let x=5let y=5
ort[5][5] = "Startpunkt"beschreibung[5][5] = "Du stehst am Startpunkt deiner Reise."ort[5][6] = "Seeufer"beschreibung[5][6] = "Du stehst am Ufer eines ruhigen Sees." ort[4][5] = "Schloss"beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen."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:
xxxxxxxxxx<p> Normaler Text <b>fetter Text</b></p>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:
xxxxxxxxxxfuntion schauer(){ }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:
xxxxxxxxxxlet xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)
let x=5let y=5
ort[5][5] = "Startpunkt"beschreibung[5][5] = "Du stehst am Startpunkt deiner Reise."ort[5][6] = "Seeufer"beschreibung[5][6] = "Du stehst am Ufer eines ruhigen Sees." ort[4][5] = "Schloss"beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen."
function schaue(){ console.log("<b>" + ort[x][y] + "</b>" ) console.log(beschreibung[x][y])}Gib mal schaue in das Eingabefeld ein... und teste ob alles funktioniert.
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:
xxxxxxxxxx if(x==0){ console.log("x ist null")}else console.log("x ist nicht gleich null")}
Beachte, dass man bei der Bedingung das Gleichheitszeichen zweimal eingibt ==.
Das Gegenteil von Gleich ist Ungleich und das gibt man mittels != ein.
Versuchs mal
xxxxxxxxxx
if(x!=5){ console.log("x ist nicht gleich 5}else console.log("x ist gleich 5")}
Wenn man mehrere Bedingungen überprüfen will, kann man if Befehle verschachteln:
xxxxxxxxxx.
if(x==5){ if(y==5){ console.log("sowohl x als auch ist 5") } }Oder man kann "wenn x gleich 0 ist und y gleich null ist", schreiben. Dazu verwendet man ein doppeltes Und-Zeichen &&:
xxxxxxxxxxif(x==5 && y==5){ console.log("sowohl x als auch ist 5") }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:
xxxxxxxxxxif(x==5 || y==5){ console.log("x oder y ist 5") }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:
xxxxxxxxxxlet xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)
let x=5let y=5
ort[5][5] = "Startpunkt"beschreibung[5][5] = "Du stehst am Startpunkt deiner Reise."ort[5][6] = "Seeufer"beschreibung[5][6] = "Du stehst am Ufer eines ruhigen Sees." ort[4][5] = "Schloss"beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen."
function schaue(){ console.log("<b>" + ort[x][y] + "</b>" ) console.log(beschreibung[x][y])}
function n(){ if(y+1<ymax && ort[x][y+1]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y+1 schaue() }}function s(){ if(y-1>=0 && ort[x][y-1]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y-1 schaue() } }function o(){ if( x+1<xmax && ort[x+1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x+1 schaue() }}function w(){ if(x-1>=0 && ort[x-1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x-1 schaue() }}
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:
xxxxxxxxxxlet xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)
let gegenstaende=createArray(xmax,ymax,0)let besitz=[]
ort[5][5] = "Startpunkt"beschreibung[5][5] = "Du stehst am Startpunkt deiner Reise."ort[5][6] = "Seeufer"gegenstaende[5][6].push("Schlüssel")gegenstaende[5][6].push("Apfel")beschreibung[5][6] = "Du stehst am Ufer eines ruhigen Sees." ort[4][5] = "Schloss"beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen."
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:
xxxxxxxxxxfunction nimm(gegenstand){ console.log(gegenstand)}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:
xxxxxxxxxx
for(let [i,gegenstand] of gegenstaende[5][6].entries() ){ console.log("i:"+i+" "+gegenstand)}damit solltest du es hinbekommen. Versuchs erst selbst und dann spicke hier:
xxxxxxxxxxlet x=5let y=5 let xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)
let gegenstaende=createArray(xmax,ymax,0)let besitz=[]
ort[5][5] = "Startpunkt"beschreibung[5][5] = "Du stehst am Startpunkt deiner Reise."ort[5][6] = "Seeufer"gegenstaende[5][6].push("Schlüssel")gegenstaende[5][6].push("Apfel")beschreibung[5][6] = "Du stehst am Ufer eines ruhigen Sees." ort[4][5] = "Schloss"beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen."
function schaue(){ console.log("<b>" + ort[x][y] + "</b>" ) console.log(beschreibung[x][y]) if(gegenstaende[x][y][0]!==undefined){ console.log("Hier liegen einige Gegenstände herum:") for(let gegenstand of gegenstaende[x][y]){ console.log("- "+gegenstand) } }}
function n(){ if(y+1<ymax && ort[x][y+1]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y+1 schaue() }}function s(){ if(y-1>=0 && ort[x][y-1]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y-1 schaue() } }function o(){ if( x+1<xmax && ort[x+1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x+1 schaue() }}function w(){ if(x-1>=0 && ort[x-1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x-1 schaue() }}
///////////////////////////////////////////////////function nimm(gegenstand2){ if(gegenstaende[x][y].length!=0){ for(let [i,gegenstand] of gegenstaende[x][y].entries() ){ if(gegenstand2.toLowerCase()==gegenstand.toLowerCase() ){ console.log(gegenstand+" aufgenommen") besitz.push(gegenstand) gegenstaende[x][y].splice(i, 1) return } } } console.log("So etwas gibt es hier nicht.")}
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.
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:
xxxxxxxxxxlet xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)let gegenstaende=createArray(xmax,ymax,0)
let besitz=[]let x=5let y=5
ort[5][5] = "Startpunkt"beschreibung[5][5] = "Du stehst am Startpunkt deiner Reise."ort[5][6] = "Seeufer"gegenstaende[5][6].push("Schlüssel")gegenstaende[5][6].push("Apfel")beschreibung[5][6] = "Du stehst am Ufer eines ruhigen Sees." ort[4][5] = "Schloss"beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen."
function schaue(){ console.log("<b>" + ort[x][y] + "</b>" ) console.log(beschreibung[x][y]) if(gegenstaende[x][y][0]!==undefined){ console.log("Hier liegen einige Gegenstände herum:") for(let gegenstand of gegenstaende[x][y]){ console.log("- "+gegenstand) } }}
function n(){ if(y+1<ymax && ort[x][y+1]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y+1 schaue() }}function s(){ if(y-1>=0 && ort[x][y-1]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y-1 schaue() } }function o(){ if( x+1<xmax && ort[x+1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x+1 schaue() }}function w(){ if(x-1>=0 && ort[x-1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x-1 schaue() }}
function nimm(gegenstand2){ if(gegenstaende[x][y].length!=0){ for(let [i,gegenstand] of gegenstaende[x][y].entries() ){ if(gegenstand2.toLowerCase()==gegenstand.toLowerCase() ){ console.log(gegenstand+" aufgenommen") besitz.push(gegenstand) gegenstaende[x][y].splice(i, 1) return } } } console.log("So etwas gibt es hier nicht.")}
function tasche(){ console.log("<b>Du hast folgende Gegenstände bei dir:</b>") for(let gegenstand of besitz){ console.log("- "+gegenstand) }}
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:
xxxxxxxxxxlet xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)let gegenstaende=createArray(xmax,ymax,0)
let besitz=[]let x=5let y=5
ort[5][5] = "Startpunkt"beschreibung[5][5] = "Du stehst am Startpunkt deiner Reise."ort[5][6] = "Seeufer"gegenstaende[5][6].push("Schlüssel")gegenstaende[5][6].push("Apfel")beschreibung[5][6] = "Du stehst am Ufer eines ruhigen Sees." ort[4][5] = "Schloss"beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen."
function schaue(){ console.log("<b>" + ort[x][y] + "</b>" ) console.log(beschreibung[x][y]) if(gegenstaende[x][y][0]!==undefined){ console.log("Hier liegen einige Gegenstände herum:") for(let gegenstand of gegenstaende[x][y]){ console.log("- "+gegenstand) } }}
function n(){ if(y+1<ymax && ort[x][y+1]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y+1 schaue() }}function s(){ if(y-1>=0 && ort[x][y-1]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y-1 schaue() } }function o(){ if( x+1<xmax && ort[x+1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x+1 schaue() }}function w(){ if(x-1>=0 && ort[x-1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x-1 schaue() }}function nimm(gegenstand2){ if(gegenstaende[x][y].length!=0){ for(let [i,gegenstand] of gegenstaende[x][y].entries() ){ if(gegenstand2.toLowerCase()==gegenstand.toLowerCase() ){ console.log(gegenstand+" aufgenommen") besitz.push(gegenstand) gegenstaende[x][y].splice(i, 1) return } } } console.log("So etwas gibt es hier nicht.")}
function tasche(){ console.log("<b>Du hast folgende Gegenstände bei dir:</b>") for(let gegenstand of besitz){ console.log("- "+gegenstand) }}
function gib(gegenstand2){ if(besitz.length!=0){ for(let [i,gegenstand] of besitz.entries() ){ if(gegenstand2.toLowerCase()==gegenstand.toLowerCase() ){ console.log(gegenstand+" abgelegt.") gegenstaende[x][y].push(gegenstand) besitz.splice(i, 1) return } } } console.log("So etwas gibt es hier nicht.")}
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:
xxxxxxxxxxlet xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)let gegenstaende=createArray(xmax,ymax,0)
let besitz=[]let x=5let y=5
ort[5][5] = "Startpunkt"beschreibung[5][5] = "Du stehst am Startpunkt deiner Reise."ort[5][6] = "Seeufer"gegenstaende[5][6].push("Schlüssel")gegenstaende[5][6].push("Apfel")beschreibung[5][6] = "Du stehst am Ufer eines ruhigen Sees." ort[4][5] = "Schloss"beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen."ort[2][5] = "Höhle"beschreibung[2][5] = "Du hast es geschafft!"
function schaue(){ if(ort[x][y]=="Schloss"){ if(gegenstaende[x][y].includes("Schlüssel")){ console.log("Du benutzt den Schlüssel, um das Tor zu öffnen.") beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist offen." ort[3][5]="offen" }else{ beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen." ort[3][5]=undefined } } console.log("<b>" + ort[x][y] + "</b>" ) console.log(beschreibung[x][y]) if(gegenstaende[x][y].length>0){ console.log("Hier liegen einige Gegenstände herum:") for(let gegenstand of gegenstaende[x][y]){ console.log("- "+gegenstand) } }}
function n(){ if(y+1<ymax && ort[x][y+1]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y+1 if(ort[x][y]=="offen") n() else schaue() }}function s(){ if(y-1>=0 && ort[x][y-1]===undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y-1 if(ort[x][y]=="offen") n() else schaue() } }function o(){ if(x+1<xmax && ort[x+1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x+1 if(ort[x][y]=="offen") o() else schaue() }}function w(){ if(x-1>=0 && ort[x-1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x-1 if(ort[x][y]=="offen") w() else schaue() }}
function nimm(gegenstand2){ if(gegenstaende[x][y].length>0){ for(let [i,gegenstand] of gegenstaende[x][y].entries() ){ if(gegenstand2.toLowerCase()==gegenstand.toLowerCase() ){ console.log(gegenstand+" aufgenommen") besitz.push(gegenstand) gegenstaende[x][y].splice(i, 1) schaue() return } } } console.log("So etwas gibt es hier nicht.")}
function tasche(){ console.log("<b>Du hast folgende Gegenstände bei dir:</b>") for(let gegenstand of besitz){ console.log("- "+gegenstand) }}
function gib(gegenstand2){ if(besitz.length>0){ for(let [i,gegenstand] of besitz.entries() ){ if(gegenstand2.toLowerCase()==gegenstand.toLowerCase() ){ console.log(gegenstand+" abgelegt.") gegenstaende[x][y].push(gegenstand) besitz.splice(i, 1) schaue() return } } } console.log("So etwas gibt es hier nicht.")}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
xxxxxxxxxxlet xmax=10let ymax=10let ort=createArray(xmax,ymax)let beschreibung=createArray(xmax,ymax)let gegenstaende=createArray(xmax,ymax,0)
let besitz=[]let x=5let y=5
ort[5][5] = "Startpunkt"beschreibung[5][5] = "Du stehst am Startpunkt deiner Reise."ort[5][6] = "Seeufer"gegenstaende[5][6].push("Schlüssel")gegenstaende[5][6].push("Apfel")beschreibung[5][6] = "Du stehst am Ufer eines ruhigen Sees." ort[4][5] = "Schloss"beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen."ort[2][5] = "Höhle"beschreibung[2][5] = "Du hast es geschafft!"
function schaue(){ if(ort[x][y]=="Schloss"){ if(gegenstaende[x][y].includes("Schlüssel")){ console.log("Du benutzt den Schlüssel, um das Tor zu öffnen.") beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist offen." ort[3][5]="offen" }else{ beschreibung[4][5] = "Ein altes Schloss mit hohen Türmen und dicken Mauern. Das Tor ist verschlossen." ort[3][5]=undefined } } console.log("<b>" + ort[x][y] + "</b>" ) console.log(beschreibung[x][y]) if(gegenstaende[x][y].length>0){ console.log("Folgende Genenstände kannst du nehmen (nimm...): ") for(let gegenstand of gegenstaende[x][y]){ console.log("- "+gegenstand) } } let richtungen="Mögliche Richtungen: " if(y+1<ymax && ort[x][y+1]!=undefined){ richtungen=richtungen+"n " } if(y>0 && ort[x][y-1]!=undefined){ richtungen=richtungen+"s " } if(x>0 && ort[x-1][y]!=undefined){ richtungen=richtungen+"w " } if(x+1<xmax && ort[x+1][y]!=undefined){ richtungen=richtungen+"o " } console.log(richtungen)}
function n(){ if(y+1<ymax && ort[x][y+1]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y+1 if(ort[x][y]=="offen") n() else schaue() }}function s(){ if(y-1>=0 && ort[x][y-1]===undefined){ console.log("Du kannst hier nicht hin gehen") }else{ y=y-1 if(ort[x][y]=="offen") n() else schaue() } }function o(){ if(x+1<xmax && ort[x+1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x+1 if(ort[x][y]=="offen") o() else schaue() }}function w(){ if(x-1>=0 && ort[x-1][y]==undefined){ console.log("Du kannst hier nicht hin gehen") }else{ x=x-1 if(ort[x][y]=="offen") w() else schaue() }}
function nimm(gegenstand2){ if(gegenstaende[x][y].length>0){ for(let [i,gegenstand] of gegenstaende[x][y].entries() ){ if(gegenstand2.toLowerCase()==gegenstand.toLowerCase() ){ console.log(gegenstand+" in Tasche gelegt. Verwende 'tasche', um reinzuschauen.") besitz.push(gegenstand) gegenstaende[x][y].splice(i, 1) schaue() return } } } console.log("So etwas gibt es hier nicht.")}
function tasche(){ console.log("<b>Du hast folgende Gegenstände bei dir (verwende gib... um sie abzulegen oder zu verwenden):</b>") for(let gegenstand of besitz){ console.log("- "+gegenstand) }}
function gib(gegenstand2){ if(besitz.length>0){ for(let [i,gegenstand] of besitz.entries() ){ if(gegenstand2.toLowerCase()==gegenstand.toLowerCase() ){ console.log(gegenstand+" abgelegt.") gegenstaende[x][y].push(gegenstand) besitz.splice(i, 1) schaue() return } } } console.log("So etwas gibt es hier nicht.")}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.
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.
Siehe hierzu die ersten vier Kapitel meiner Anleitung: https://kiliansinger.github.io/codetricks/