Teil 2 Projekt Pygame Zero

Bevor du mit Teil 2 anfängst, erledige alle Aufgaben aus Teil 1.

In den folgenden Aufgaben gebe ich keine genauen Hinweise mehr, wo du Bilder oder Dateien speichern sollst oder wo genau der Code geschrieben wird.

Das Spiel baut aufeinander auf, daher ist es wichtig, dass du nach jeder Codeänderung die Python-Datei script.py ausführst und testest, ob das Spiel tatsächlich wie erwartet funktioniert.

Speichere deine Lösungen weiterhin in der Datei lsg_nachname.txt und achte darauf, dass die Lösungen zu den Aufgaben unter den richtigen Aufgabennummern stehen.

Wichtige Hinweise zu Dateiformaten in Pygame Zero

Es ist sehr wichtig, das Folgende zu verstehen: Jede Datei hat eine Erweiterung, die ihren Typ angibt. Hier sind einige Beispiele:

Pygame Zero unterstützt Bilddateien in den Formaten .png, .gif und .jpg.

Empfehlung: Verwende das PNG-Format. Es bietet eine hohe Bildqualität und unterstützt Transparenz, was besonders für Spiele nützlich ist.

Pygame Zero kann Audiodateien in den Formaten .wav und .ogg laden. Wie schon erwähnt, funktioniert es auf manchen Rechnern überhaupt nicht. Ich suche nach einer Lösung.

Pygame Zero unterstützt das MP3-Format nicht.

Achte darauf, die Dateiformate bewusst auszuwählen, damit dein Spiel optimal funktioniert.

Hintergrundbild hinzufügen

Lade das Bild herunter. Alternativ kannst du selbst nach passenden PNG-Hintergrundbildern suchen (z. B. auf Open Game Art).

Die Datei grass.png hat eine Größe von 800 x 600 Pixeln. Wenn die Höhe oder Breite deines Spielfensters größer als 800 bzw. 600 ist, werden alle Bereiche, die nicht vom Hintergrundbild abgedeckt sind, in Schwarz angezeigt.

Du kannst die Bildgröße mithilfe eines Online-Photo-Editors, z. B. Photopea, anpassen oder Bilder zuschneiden.

  1. Füge ein Hintergrundbild (z. B. grass.png) zu deinem Spiel hinzu. Erstelle einen Actor für das Bild und nenne ihn bg (kurz für background). Zeichne das Hintergrundbild mithilfe der draw-Funktion. Überlege: Brauchst du noch screen.clear()? Begründe, warum oder warum nicht.

Gegner hinzufügen

Jetzt wird es spannender: Wir fügen einen Gegner hinzu.

Lade diese Datei herunter. Alternativ kannst du Pokémon-Sprites hier finden oder einfach googeln. Achte darauf, dass du gezielt nach Bilddateien suchst, die speziell für 2D-Spiele erstellt wurden, damit sie optimal aussehen. Gib dazu Begriffe wie „Pokémon Sprite PNG“ oder „Dragon Sprite PNG“ ein.

Sprites sind ein Fachbegriff aus der Videospielentwicklung und bezeichnen kleine Bilder, die in Videospielen verwendet werden.

  1. Füge einen Gegner zu deinem Spiel hinzu, indem du einen Actor erstellst und ihn enemy nennst. Positioniere den Gegner an einer beliebigen Stelle auf dem Bildschirm und teste, ob der Code wie erwartet funktioniert.

  2. Ergänze den folgenden Code in deinem Spiel:

    def update():
         # anderer Code
         if enemy.x < player.x:
            enemy.x += 1
         if enemy.x > player.x:
            enemy.x -= 1
    

    Teste den Code. Was tut der Gegner, wenn seine x-Koordinate kleiner als die des Spielers ist? Was passiert, wenn die x-Koordinate des Gegners größer als die des Spielers ist?

  3. Der Gegner folgt dem Spieler derzeit nur entlang der x-Achse. Erweitere den Code, damit der Gegner dem Spieler auch entlang der y-Achse folgt.

  4. Lade diese Datei herunter. Dein Code soll ein Geräusch abspielen, wenn der Gegner den Spieler berührt. Nutze die Methode colliderect(), um Kollisionen zu erkennen. Falls die Datei nicht abgespielt werden kann, lasse stattdessen print("hurt") im Terminal ausgeben.

  5. Setze den Punktestand auf null zurück, wenn der Gegner den Spieler berührt.

Weitere Items hinzufügen

Du kannst deinem Spiel zusätzliche Items wie ein Edelstein green gem hinzufügen. Oder z. B. Pokémon-Items, die du hier findest.

  1. Füge ein neues Item zu deinem Spiel hinzu. Lasse es an einer zufälligen Position erscheinen (vgl. Aufg. 17). Schreibe den Code so, dass der Spieler 5 Punkte bekommt, wenn er das Item berührt, und dass das Item danach an einer neuen zufälligen Position erscheint.

Timer hinzufügen

Ein Timer misst die Spielzeit und kann später verwendet werden, um verschiedene Schwierigkeitsstufen zu steuern.

  1. Erstelle eine timer Variable (vgl. Aufg. 19).
    Erhöhe ihren Wert in der update-Funktion mit:

    timer += 1 / 60
    

    Zeige den Wert auf dem Bildschirm an.
    Warum verwenden wir += 1/ 60 statt += 1?
    Erkläre den Unterschied.

  2. Der Timer zeigt aktuell lange Dezimalzahlen an.
    Ersetze str(timer) durch:

    str(round(timer, 2))
    

    Was macht die Funktion round()?
    Was bedeutet die Zahl 2 im Argument?
    Was passiert, wenn du nur round(timer) schreibst?

Mehrere Items mit einer Liste

Jetzt sollen mehrere Items zufällig auf dem Bildschirm erscheinen. Dies ist etwas anspruchsvoller zu programmieren, da wir Listen verwenden, um die Items zu verwalten.

Füge folgende Codezeile außerhalb der draw- und update-Funktionen ein:

items = []

Lade dieses Bild herunter oder suche selbst nach einem passenden Bild.

Erweitere die update-Funktion mit folgendem Code, um zufällig neue Items zu erstellen und sie zu verwalten:

def update():
    # anderer Code
    
    if len(items) < 3 and random.randint(0, 100) == 0:
        item = Actor("candy")
        item.x = random.randint(0, WIDTH) 
        item.y = random.randint(0, HEIGHT)  
        items.append(item) 

    for x in items[:]: # Statt nur for x in items
        if x.colliderect(player):
            score += 5  
            items.remove(x) 
            print("Candy collected!")

Ergänze diesen Code in der draw-Funktion, um alle Items auf dem Bildschirm darzustellen:

def draw():
	# anderer Code
	for x in items:
	    x.draw()

Teste den Code, um sicherzustellen, dass er ohne Fehlermeldungen läuft. Achte dabei immer auf die richtige Einrückung.

  1. Was macht die Bedingung len(items) < 3 in der if-Anweisung? Was bedeutet len? Was passiert, wenn du len(items) < 3 durch len(items) < 10 oder len(items) < 20 ersetzt?

  2. Was prüft random.randint(0, 100) == 0 in der if-Anweisung? Was passiert, wenn du stattdessen random.randint(0, 20) == 0 schreibst? Erscheinen die Items häufiger? Warum?

  3. Erkläre die folgenden Codezeilen:

     item.x = random.randint(0, WIDTH)
     item.y = random.randint(0, HEIGHT)
    

    Was machen diese Zeilen, und warum sind sie nötig?

  4. Erkläre die folgende Codezeile:

    items.append(item)
    

    Was macht diese Zeile, und wie verändert sie die Liste items?

  5. Aus technischen Gründen, auf die ich hier nicht näher eingehen werde, müssen wir in der for-Schleife for x in items[:] schreiben, anstatt nur for x in items.
    Erkläre, was im Code innerhalb der for-Schleife passiert.

  6. Erkläre die folgenden Zeilen:

    for x in items: 
        x.draw()
    

    Was bewirken diese Zeilen? Würde sich etwas ändern, wenn wir anstelle von x die Variablen y oder bobo verwenden?


Wenn du mit den obigen Aufgaben fertig bist, erweitere dein Spiel selbst weiter. Schreibe deinen Code jedoch in eine separate Datei test.py, damit der Basiscode in der Datei script.py, in der du die Aufgaben machst, unverändert für zukünftige Aufgaben bleibt.

Lass dich von der Webseite A Posteriori inspirieren!