Challenge 12: Labyrinth

Challenge

Diese Challenge ist die Herausforderndste von allen und erfordert ein Verständnis von allen bisherigen Challenges zusammen. Es werden alle möglichen Elemente wie Bedingungen, Schleifen, Arrays und Variablen gebraucht und miteinander kombiniert. 

Es geht darum, ein Labyrinthartiges Spielfeld zu bauen, in welchem man eine Spielfigur bewegen kann. Dabei kann man sowohl nach links und rechts als auch nach oben und unten gehen. Durch Wände kommt man nicht hindurch.

Makecode

Programmierfunktion

  • Variablen
  • Events abfragen
  • Arrays
  • Zweidimensionale Arrays
  • While-Schleifen
  • For-Schleifen mit Zähler
  • Verschachtelte For-Schleifen
  • Funktionen

Spiellogik

Zu Beginn werden alle Variablen definiert und initialisiert. 

  • Eine Variable die das Array für das angezeigte Labyrinth speichert. In dieses werden später die Sprites der Wände und deren aktuelle Position gespeichert.
  • Jeweils eine Variable, um die x- und y-Koordinate der Kamera zu speichern. Diese befindet sich anfangs auf (0/0).
  • Zuletzt eine Sprite-Variable, welche den Spieler darstellen soll. Dieser kann auf einer beliebigen freien Stelle im Labyrinth starten. Zur besseren Sichtbarkeit kann man das Sprite blinken lassen

Innerhalb des „on-start“ Blocks sollen ebenfalls noch zwei Funktionen aufgerufen werden. Die erste Funktion soll das Array für das eigentliche Labyrinth erstellen und befüllen. Es ist zwar prinzipiell mögliche diese Funktion mit den Blöcken von MakeCode zu erstellen, jedoch ist es weitaus einfacher es mit Hilfe von JavaScript zu tun, da man hier auch gleich das Layout des Labyrinths sehen kann. Vom Prinzip her funktioniert das Coden genauso wie die Block-Variante. Durch das Wort „function“ weiß das Programm, dass es sich um eine Funktion handelt. Diese hat einen Namen und bekommt keine Variablen übergeben, weswegen die runden Klammern leer sind. Der auszuführende Code steht innerhalb der geschweiften Klammern. Die Variable für das Labyrinth-Array speichert ein selbst erstelltes Labyrinth. Ein Array wird durch eckige Klammern dargestellt. 

Um das Labyrinth sinnvoll speichern zu können benötigt man ein sogenanntes „zweidimensionales Array“. Das bedeutet nichts anderes als ein Array, welches mehrere Arrays speichert. Diese Struktur kann man sich jetzt wie ein Schachbrett oder eine Tabelle vorstellen, welche Reihen und Spalten besitzen. Innerhalb eines inneren Arrays werden die verschiedenen möglichen Elemente des Labyrinths gespeichert. Eine 0 bedeutet die Zelle ist leer, bzw. hier kann der Spieler laufen, eine 1 steht für eine Wand, durch die der Spieler nicht vorbeikommt. 

Für diese Challenge soll ein quadratisches Spielfeld erstellt werden, welches jeweils 15 Zellen lang und breit ist. Das bedeutet man benötigt 16 Arrays – 1 Äußeres und 15 Innere, wobei letztere ebenfalls 15 Werte für die einzelnen Zellen speichern. Das Spielfeld soll rundherum eine Wand besitzen damit man dieses nicht verlassen kann, ansonsten sind der Gestaltung des Labyrinthaufbaus keine Grenzen gesetzt. 

Da bis jetzt noch nicht gecodet wurde und das Ganze trotz der Erklärung noch schwer vorzustellen ist hier nachfolgend ein Screenshot wie das in etwa aussehen sollte:

Die zweite Funktion dient dazu den aktuellen Kamerabereich darzustellen. Diese wird unter anderem zu Beginn aufgerufen, damit anfangs ebenfalls schon Wände vorhanden sind. Ab hier kann wieder normal mit den Blöcken gearbeitet werden.

Da der micro:bit nur aus einem 5×5 Display besteht lässt dementsprechend auch nur solch ein Ausschnitt aus dem Labyrinth darstellen. Die Kameraposition ist immer in der oberen linken Ecke und deckt die 5 Zellen nach rechts und nach unten ab. Um die insgesamt 25 Zellen aus diesem Bereich abzufragen und deren Inhalt zu erfahren benötigt man eine verschachtelte For-Schleife mit Zähler. Dieser Zähler soll bei beiden von 0-4 zählen (also 5 Mal durchlaufen). So wird Reihe für Reihe, Zelle für Zelle jeder Inhalt abgefragt. In einer If-Abfrage wird überprüft ob in einer Zelle eine 1 steht, also ob sich dort eine Wand befindet. Dazu verschachtelt man zwei Mal ein „get value at“ Befehl. Der Äußere addiert die aktuelle x-Koordinate der Kamera zu dem Wert der inneren Zähler-Variable. Mit dieser Abfrage erhält man eines der 15 Arrays. Der Innere Befehl beinhaltet dann die Variable für das Labyrinth-Array und als Index wird nun die y-Koordinate mit dem Wert der äußeren Zähler-Variable addiert. So bekommt man einen der 15 Werte innerhalb des Arrays. Wenn also die Kamera auf (0/0) steht werden insgesamt die Werte von 0-4 abgefragt. Da in der oberen linken Ecke des Labyrinths eine Wand ist soll auch in diesem Fall ein Sprite erstellt werden. Als x-Koordinate dient allein der Wert der inneren Zähler-Variable und als y-Koordinate der Wert der äußeren-Zählervariable. Damit diese später wieder gelöscht werden können, wenn sich die Kamera weiterbewegt und sich dadurch die relative Position der Wände verändert, werden die Sprites dem Array hinzugefügt, welches man im Startblock erstellt hat. Dieses dient allein dazu alle derzeitigen Sprites mit deren Position zu speichern.

Innerhalb der zweiten Funktion oberhalb der verschachtelten For-Schleife benötigt man für das Löschen eine While-Schleife. Diese soll, solange die Länge des Sprite-Arrays größer als 0 ist, also sich darin auch Sprites befinden, das vorderste Sprite in dem Arrays löschen (auf Index 0). Wenn also schon Wände gezeichnet wurde, werden sie so gelöscht und in der verschachtelten For-Schleife die neuen Positionen der Wände ermittelt.

Das Spielfeld ist soweit also gezeichnet, jetzt geht es an die Steuerung. Da man die Spielfigur in vier Richtungen steuern kann (links, rechts, oben, unten), man aber nur zwei Tasten zur Verfügung hat, muss man ein wenig tricksen. Zu Beginn läuft man mit seiner Figur horizontal, also von links nach rechts. Durch das gleichzeitige Drücken der „A“- und „B“-Taste soll die Richtung geändert werden auf vertikal, also oben und unten.

Man benötigt eine neue Variable, welche entweder True oder False beinhaltet (Standardmäßig sind Variablen immer False). Wenn man beide Tasten drückt, wird überprüft, ob diese Variable auf True steht. Wenn ja, wird sie auf False gesetzt, wenn nein auf True. So lässt sich bei jedem gleichzeitigen Drücken zwischen den beiden Zuständen hin und her wechseln.

Wenn die „A“-Taste gedrückt wird, soll zuerst abgeprüft werden ob die vorherige Variable auf True steht. True bedeutet die Richtung ist derzeit auf vertikal geschaltet. Innerhalb des True-Fall-Blocks wird nun die Bewegung nach oben geregelt. Grundlegend wird dieser Block sowohl im Else-Fall als auch bei der „B“-Taste jeweils genauso aussehen, es müssen lediglich die Koordinaten getauscht oder die Vorzeichen umgekehrt werden.

Es gibt zwei Arten von Bewegung. Die Bewegung des Spielers und die Bewegung der Kamera. Grundsätzlich soll der Spieler immer mittig stehen also auf x=2 und/oder y=2. Andererseits soll die Kamera nie außerhalb der Wände sein. Befindet sich der Spieler wird die Kamera solange bewegt in die gewünschte Richtung bis der der Rand an der Seite des Displays auftaucht. Ab da bewegt sich dann nicht mehr die Kamera, sondern der Spieler solange bis er ebenfalls auf die Randmauer trifft. Bewegt man sich von der Wand weg bewegt sich der Spieler solange bis er wieder mittig ist und dann die Kamera.

Um sich um 1 nach oben zu bewegen. Sei es durch die Kamera oder den Spieler, muss die Zelle oberhalb des Spielers betretbar sein, also eine 0 in dem Array gespeichert sein. Die Abfrage dafür sieht ähnlich aus wie bei der Funktion zum Erstellen der Wände mit den zwei verschachtelten „get value at“-Blöcken. Statt der Zähler-Variablen kann man nun die x- und y-Koordinate des Spielers einsetzen jeweils addiert zu den entsprechenden Koordinaten der Kamera. Ebenfalls muss man noch je nach Bewegungsrichtung eine Anpassung vornehmen. In diesem Fall mit der Bewegung nach oben muss man von der Summe der beiden y-Koordinaten noch 1 abziehen. Je nach Fall muss man noch 1 addieren oder das Ganze bei der x-Koordinate tun.

Sollte nun die untersuchte Zelle eine 0 enthalten bedeutet das, es kann sich bewegt werden. Nun muss noch abgefragt werden ob zum einen die y-Koordinate der Kamera größer als 0 ist, sie sich also nicht am Rand befindet, und der Spieler sich auf y=2 befindet. Sind beide Bedingungen wahr soll die Kamera um -1 in y-Richtung bewegt werden, also nach oben. Ist auch nur eine der beiden Bedingungen falsch soll im Else-Fall der Spieler bewegt werden. 

Dies muss nurnoch für die restlichen Bewegungen analog übernommen werden und das Grundspiel ist fertig.

Wir wünschen viel Spaß beim Lösen unserer letzten Challenge! Wie es geht, zeigen wir morgen auf diesem Blog.

Challenge Master

Ich bin der Challenge Master. Hinter mir verbergen sich die Auszubildenden von Proact Deutschland. Gemeinsam füllen wir diesen Blog mit verschiedenen Projekten, um euch das Coden beizubringen.

 
Kommentare

Noch keine Kommentare vorhanden.

Hinterlassen Sie einen Kommentar