Modulbild

Dein erstes Micro:bit Spiel: Ausweichen!

lock
Bevorstehend

Programmiere ein spannendes Ausweichspiel direkt auf der Micro:bit LED-Matrix.

Ziele dieses Moduls
Keine Ziele hinterlegt.

Du hast die Grundlagen des Micro:bit und seiner Hardware gemeistert – grossartig! Jetzt ist es Zeit, deine Fähigkeiten zu nutzen und ein interaktives Spiel zu programmieren. Wir erschaffen ein Ausweichspiel direkt auf der LED-Matrix deines Micro:bit.

Dieses Spiel wird dir zeigen, wie du mit Tasten, sich wiederholenden Abläufen und variablen Daten ein komplettes Spiel zum Leben erwecken kannst.

Das Spielprinzip: Weiche den fallenden Punkten aus!

Dein Ziel in diesem Spiel ist es, so lange wie möglich zu überleben, indem du fallenden Hindernissen ausweichst.

  • Dein Spieler: Ein heller Punkt in der untersten Reihe der LED-Matrix (Y-Koordinate 4).

  • Hindernisse: Dunklere Punkte, die von der obersten Reihe (Y-Koordinate 0) nach unten fallen.

  • Steuerung:

    • Drücke Taste A, um deinen Spieler nach links zu bewegen.

    • Drücke Taste B, um deinen Spieler nach rechts zu bewegen.

  • Punktestand: Für jede Sekunde, die du überlebst, erhältst du Punkte.

  • Game Over: Wenn dein Spieler einen fallenden Punkt berührt, ist das Spiel vorbei. Dein erzielter Punktestand wird angezeigt, und das Spiel beginnt von Neuem.

Schritt 1: Den Spieler bewegen

Zuerst programmieren wir, wie du deinen Spieler auf der LED-Matrix steuern kannst. Dein Spieler wird ein Punkt sein, der sich auf der untersten Reihe (Y=4) bewegen kann. Die X-Koordinate des Spielers wird standardmässig auf 2 gesetzt (Mitte der 5x5 Matrix).

Variablen definieren:

Bevor wir starten, definieren wir die Startposition deines Spielers. Wir brauchen eine Variable für die X-Koordinate des Spielers und eine für die Y-Koordinate.

  • let x = 2 (Startposition in der Mitte)

  • let y = 4 (unterste Reihe der LED-Matrix)

Block-Programmierung für die Bewegung:

  1. Öffne ein neues Projekt im MakeCode Editor.

  2. Zieh einen wenn Taste A gedrückt-Block aus der Kategorie "Eingabe" in den Arbeitsbereich.

  3. Innerhalb dieses Blocks:

    • Füge einen wenn ... dann ...-Block aus "Logik" hinzu.

    • Setze die Bedingung auf x > 0 (aus "Logik" -> "Vergleichsoperatoren" und "Variablen"). Dies verhindert, dass der Spieler vom Bildschirm fällt.

    • Innerhalb der wenn x > 0-Bedingung:

      • Füge den Block led.unplot(x, y) aus "Leds" hinzu, um den alten Punkt zu löschen.

      • Füge den Block x um -1 ändern aus "Variablen" hinzu, um die X-Koordinate um 1 nach links zu verschieben.

      • Füge den Block led.plot(x, y) aus "Leds" hinzu, um den Spieler an der neuen Position zu zeichnen.

  4. Wiederhole Schritt 2 und 3 für Taste B:

    • Setze die Bedingung auf x < 4.

    • Ändere die X-Koordinate um 1 (für Bewegung nach rechts).

So sieht der Code aus (JavaScript-Ansicht):

// Spieler-Position initialisieren
let y = 4 // Der Spieler bleibt immer auf der untersten Reihe
let x = 2 // Der Spieler startet in der Mitte

input.onButtonPressed(Button.A, function () {
    if (x > 0) { // Wenn der Spieler nicht ganz links ist
        led.unplot(x, y) // Alten Punkt löschen
        x -= 1 // X-Koordinate um 1 reduzieren (nach links)
        led.plot(x, y) // Neuen Punkt zeichnen
    }
})

input.onButtonPressed(Button.B, function () {
    if (x < 4) { // Wenn der Spieler nicht ganz rechts ist
        led.unplot(x, y) // Alten Punkt löschen
        x += 1 // X-Koordinate um 1 erhöhen (nach rechts)
        led.plot(x, y) // Neuen Punkt zeichnen
    }
})

Schritt 2: Hindernisse fallen lassen und Punkte sammeln

Jetzt bauen wir den Kern des Spiels: fallende Hindernisse, Punktezählung und das "Game Over". Wir nutzen eine Liste (Array), um mehrere Hindernisse gleichzeitig zu verwalten.

Zusätzliche Variablen und die "Obstacle"-Klasse:

Füge diese Definitionen am Anfang deines Projekts hinzu (am besten, bevor der input.onButtonPressed-Code kommt):

let score = 0 // Variable für den Punktestand
let obstacles: { x: number, y: number }[] = [] // Eine Liste (Array) für unsere Hindernisse

// Eine einfache "Klasse" für unsere Hindernisse – jedes hat eine X- und Y-Koordinate
// In MakeCode Blöcken ist dies oft implizit oder durch "Sprite"-Blöcke abgedeckt
// Hier definieren wir es explizit für die TypeScript-Ansicht:
class Obstacle {
    x: number
    y: number
    constructor(x: number, y: number) {
        this.x = x
        this.y = y
    }
}

  • score: Zählt, wie viele Runden du überlebt hast.

  • obstacles: Das ist eine Liste, in der wir alle Punkte speichern, die gerade vom oberen Rand fallen. Jeder Punkt in dieser Liste ist ein "Hindernis" mit einer eigenen X- und Y-Koordinate.

Der "Spiel-Loop":

Dies ist der wichtigste Teil des Spiels. Er wird in regelmässigen Abständen (z.B. alle 200 Millisekunden) ausgeführt und aktualisiert das gesamte Spielgeschehen.

  1. Zieh den Block wiederhole alle (ms) aus der Kategorie "Schleifen" (oder "Grundlagen" je nach MakeCode-Version) in den Arbeitsbereich. Setze die Zeit auf 200 ms.

  2. Innerhalb dieses Blocks:

    • score um 1 ändern aus "Variablen".

    • lösche Bildschirm aus "Grundlagen".

    • Hindernisse bewegen und überprüfen (fortgeschritten):

      • Diese Logik ist etwas komplexer, da sie eine Schleife über die obstacles-Liste benötigt, um jedes Hindernis zu bewegen, auf Kollision zu prüfen und eventuell zu entfernen. In MakeCode Blöcken gibt es dafür oft spezialisierte "Sprite"-Blöcke, die diese Arbeit erleichtern. Wenn du diesen Teil lieber als Blöcke umsetzen möchtest, schau in der "Game"-Erweiterung nach Blöcken, die "Sprites" (Spielobjekte) erstellen und bewegen können.

      • Im TypeScript-Code, den du hattest, sieht das so aus:

        for (let i = obstacles.length - 1; i >= 0; i--){ // Gehe alle Hindernisse durch
            let obstacle = obstacles[i]
            obstacle.y = obstacle.y + 1; // Hindernis bewegt sich nach unten
        
            // Kollision prüfen
            if (obstacle.x == x && obstacle.y == y){
                basic.showNumber(score) // Zeige den Punktestand
                score = 0 // Spiel zurücksetzen
            }
        
            // Hindernis entfernen, wenn es unten raus ist
            if (obstacle.y > 4){
                obstacles.removeAt(i)
            }
        }
        
    • Neues Hindernis erzeugen:

      • Füge einen Block hinzu, der eine zufällige Zahl zwischen 0 und 4 generiert (z.B. wähle zufällige Zahl von 0 bis 4 aus "Mathematik"). Speichere diese in einer neuen Variable ox.

      • Erzeuge ein neues Hindernis an den Koordinaten (ox, 0) und füge es zur obstacles-Liste hinzu.

    • Alles neu zeichnen:

      • In einer Schleife (oder mit spezialisierten Game-Blöcken) zeichnest du alle Punkte aus der obstacles-Liste auf den Bildschirm. Nutze led.plotBrightness(x, y, 20) für Hindernisse, damit sie dunkler sind.

      • Zeichne deinen Spieler zuletzt, damit er immer sichtbar ist: led.plotBrightness(x, y, 255).

So sieht der Kern-Loop aus (JavaScript-Ansicht):

loops.everyInterval(200, function () { // Alle 200 Millisekunden:
    score += 1 // Punkte erhöhen
    basic.clearScreen() // Bildschirm löschen

    // Bewege vorhandene Hindernisse und prüfe auf Kollisionen
    for (let i = obstacles.length - 1; i >= 0; i--){
        let obstacle = obstacles[i]
        obstacle.y = obstacle.y + 1; // Hindernis bewegt sich eine Zeile nach unten

        // Kollisionserkennung: Wenn Spieler und Hindernis am gleichen Ort sind
        if (obstacle.x == x && obstacle.y == y){
            basic.showNumber(score) // Zeige den erreichten Punktestand an
            score = 0 // Setze den Punktestand zurück (Spiel ist vorbei, beginnt neu)
        }

        // Hindernis entfernen, wenn es den unteren Rand überschreitet
        if (obstacle.y > 4){
            obstacles.removeAt(i)
        }
    }

    // Neues Hindernis erzeugen
    let ox = randint(0, 4) // Zufällige X-Position (0 bis 4)
    const new_obstacle = new Obstacle(ox, 0) // Neues Hindernis in der obersten Reihe (y=0)
    obstacles.push(new_obstacle) // Zur Liste der Hindernisse hinzufügen

    // Alle aktuellen Elemente auf dem Bildschirm neu zeichnen
    // Zeichne alle Hindernisse (dunkler)
    for (let obstacle2 of obstacles) {
        led.plotBrightness(obstacle2.x, obstacle2.y, 20)
    }
    // Zeichne den Spieler (heller)
    led.plotBrightness(x, y, 255)
})

Dein vollständiger Code zum Kopieren:

// Initialisiere Spielerposition und Punktestand
let score = 0
let y = 4 // Spieler ist immer auf der untersten Reihe
let x = 2 // Spieler startet in der Mitte

// Definiere die Struktur für ein Hindernis (X- und Y-Koordinate)
class Obstacle {
    x: number
    y: number
    constructor(x: number, y: number) {
        this.x = x
        this.y = y
    }
}

// Initialisiere die Liste für fallende Hindernisse
let obstacles: Obstacle[] = []

// Steuerung des Spielers mit Taste A (links bewegen)
input.onButtonPressed(Button.A, function () {
    if (x > 0) { // Nur bewegen, wenn nicht schon ganz links
        led.unplot(x, y) // Alten Spielerpunkt löschen
        x -= 1 // X-Koordinate reduzieren
        led.plot(x, y) // Neuen Spielerpunkt zeichnen
    }
})

// Steuerung des Spielers mit Taste B (rechts bewegen)
input.onButtonPressed(Button.B, function () {
    if (x < 4) { // Nur bewegen, wenn nicht schon ganz rechts
        led.unplot(x, y) // Alten Spielerpunkt löschen
        x += 1 // X-Koordinate erhöhen
        led.plot(x, y) // Neuen Spielerpunkt zeichnen
    }
})

// Der Hauptspiel-Loop, der alle 200 Millisekunden läuft
loops.everyInterval(200, function () {
    score += 1 // Punktestand erhöhen

    // Lösche den gesamten Bildschirm für die neue Zeichnung
    basic.clearScreen()

    // 1. Alle vorhandenen Hindernisse bewegen und auf Kollision prüfen
    // Wir gehen die Liste rückwärts durch, falls wir Elemente entfernen müssen
    for (let i = obstacles.length - 1; i >= 0; i--){
        let obstacle = obstacles[i]
        obstacle.y = obstacle.y + 1; // Hindernis eine Zeile nach unten bewegen

        // Kollision mit dem Spieler?
        if (obstacle.x == x && obstacle.y == y){
            basic.showNumber(score) // Zeige den Endpunktestand
            score = 0 // Punktestand zurücksetzen (Spiel ist vorbei, beginnt neu)
        }

        // Ist das Hindernis aus dem Bild gefallen?
        if (obstacle.y > 4){
            obstacles.removeAt(i) // Dann aus der Liste entfernen
        }
    }

    // 2. Ein neues Hindernis erzeugen
    let ox = randint(0, 4) // Zufällige X-Position für das neue Hindernis (0 bis 4)
    const new_obstacle = new Obstacle(ox, 0) // Neues Hindernis in der obersten Reihe (y=0)
    obstacles.push(new_obstacle) // Zur Liste der Hindernisse hinzufügen

    // 3. Alle aktuellen Elemente auf dem Bildschirm neu zeichnen
    // Zeichne alle Hindernisse (dunkler)
    for (let obstacle2 of obstacles) {
        led.plotBrightness(obstacle2.x, obstacle2.y, 20)
    }
    // Zeichne den Spieler (heller)
    led.plotBrightness(x, y, 255)
})

Experimentiere und Erweitere dein Spiel!

Dieses Spiel ist ein toller Startpunkt. Hier sind ein paar Ideen, wie du es anpassen und noch spannender machen kannst:

  • Schwierigkeitsgrad anpassen:

    • Ändere die Spielgeschwindigkeit, indem du den Wert in loops.everyInterval(200, ...) verkleinerst (schneller) oder vergrösserst (langsamer).

    • Lass mehrere Hindernisse gleichzeitig fallen.

    • Erhöhe die Anzahl der Hindernisse, je höher der Punktestand wird.

  • Lebenspunkte: Gib dem Spieler 3 "Leben". Bei einer Kollision verliert er ein Leben, statt dass das Spiel sofort endet.

  • Soundeffekte: Füge kurze Töne hinzu, wenn der Spieler ausweicht, Punkte sammelt oder das Spiel vorbei ist. Nutze die music-Blöcke.

  • Visuelle Effekte: Lass die LEDs beim "Game Over" blinken oder zeige ein trauriges Gesicht an.

Lass deiner Kreativität freien Lauf und sieh, was für ein Spiel du daraus machen kannst!