Aussehen
Ein Spiel bauen đ â
Bis hierher hast du Programme geschrieben, die etwas ausrechnen und dann fertig sind. Ein Spiel ist anders: Es hört nicht auf. Es zeichnet ein Bild, wartet einen Sechzigstel einer Sekunde, rechnet weiter, zeichnet das nĂ€chste Bild â sechzigmal pro Sekunde, bis jemand das Fenster schlieĂt.
Genau diese Schleife nimmt dir Pygame Zero ab. Du schreibst nur noch, was in jedem Bild passieren soll.

Eine Ente bringt ihre fĂŒnf KĂŒken ĂŒber den Teich. Auf dem Wasser fahren Boote. Wer erwischt wird, muss zurĂŒck und noch einmal los.
Das bauen wir in neun Stufen. Nach jeder Stufe lĂ€uft dein Spiel â du kannst also jederzeit aufhören, weiterspielen oder etwas anderes daraus machen. Der vollstĂ€ndige Quelltext steht auf dieser Seite, du musst nichts herunterladen, um mitzulesen.
Was du brauchst â
Du brauchst einen Editor auf deinem Rechner â Thonny ist dafĂŒr gemacht â und ein zusĂ€tzliches Modul. Module sind fertige Lösungen von anderen Leuten, und man installiert sie einmal:
pip install pgzeroIn Thonny geht das auch ohne Konsole: Werkzeuge â Verwalte Pakete, dort pgzero suchen und installieren.
Modul
Ein Modul ist eine Sammlung fertiger Funktionen, die jemand anderes geschrieben hat. import holt sie in dein Programm. Fast alles, was Python kann, kommt aus Modulen â und die allermeisten davon musst du erst installieren.
Die drei Bilder â
Ab Stufe 4 brauchst du diese drei Bilder. Rechtsklick auf ein Bild â âBild speichern unter", und zwar in einen Ordner namens images direkt neben deinem Programm. Der Ordner muss genau so heiĂen, sonst findet Pygame Zero die Bilder nicht.
| Bild | Dateiname |
|---|---|
ente.png | |
kueken.png | |
boot.png |
Die drei Bilder sind fĂŒr dieses Buch gezeichnet worden. Du darfst sie behalten, verĂ€ndern und in deinen eigenen Spielen benutzen.
Am Ende sieht dein Ordner so aus:
mein-spiel/
âââ spiel.py
âââ images/
âââ ente.png
âââ kueken.png
âââ boot.pngAlles auf einmal herunterladen
Wer die drei Bilder nicht einzeln speichern mag, bekommt hier den fertigen Ordner: das Spiel im Stand von Stufe 9, mit allen Bildern und einer Kurzanleitung.
Zum Mitbauen ist das nicht gedacht â darin ist ja schon alles fertig. Praktisch ist es, wenn du sehen willst, wie es laufen soll, oder wenn bei dir etwas klemmt und du vergleichen möchtest.
Stufe 1: Ein Fenster â
python
import pgzrun
WIDTH = 800
HEIGHT = 600
def draw():
screen.fill((74, 144, 180))
pgzrun.go()Sechs Zeilen, und schon lĂ€uft ein Spiel â es passiert nur noch nichts darin.
WIDTH und HEIGHT schreibt man groĂ, weil sie sich nie Ă€ndern. Pygame Zero liest sie aus und baut danach das Fenster.
Die Funktion draw() rufst du nirgends auf. Das macht Pygame Zero, sechzigmal pro Sekunde. Du legst nur fest, was drinsteht. Die drei Zahlen sind eine Farbe: Rot, GrĂŒn, Blau, jeweils von 0 bis 255. (74, 144, 180) ist ein tiefes Teichblau.
Test
FĂŒhre das Programm aus. Es muss sich ein blaues Fenster öffnen. SchlieĂe es wieder â Programme mit pgzrun.go() laufen sonst weiter.
Eine andere Farbe?
Probier (20, 40, 90) fĂŒr einen nĂ€chtlichen Teich oder (120, 190, 200) fĂŒr ein Schwimmbad. Farben zum Aussuchen findest du mit jedem FarbwĂ€hler im Netz, zum Beispiel bei w3schools.
Stufe 2: Ufer und Ente â
Noch ohne Bilder â Pygame Zero kann selbst zeichnen.
python
import pgzrun
WIDTH = 800
HEIGHT = 600
# Farben bekommen Namen, damit man den Teich an einer Stelle umfÀrben kann.
WATER = (74, 144, 180)
SHORE = (110, 170, 90)
# Solange die Ente ein Punkt ist, ist sie nichts weiter als zwei Zahlen.
duck_x = 400
duck_y = 565
def draw():
screen.fill(WATER)
screen.draw.filled_rect(Rect(0, 0, 800, 70), SHORE)
screen.draw.filled_rect(Rect(0, 530, 800, 70), SHORE)
screen.draw.filled_circle((duck_x, duck_y), 22, (255, 255, 255))
pgzrun.go()Schau dir den Aufruf genau an, der das obere Ufer zeichnet:
python
screen.draw.filled_rect(Rect(0, 0, 800, 70), SHORE)Er bekommt zwei Dinge: ein Rechteck und eine Farbe. Und das Rechteck selbst besteht wieder aus vier Zahlen:
- 0 â wie weit rechts die linke Kante liegt
- 0 â wie weit unten die obere Kante liegt
- 800 â wie breit
- 70 â wie hoch
Englische Namen, deutsche Kommentare
Die Namen im Programm sind englisch â duck, boat, WATER. Fast aller Code, den du je lesen wirst, ist so benannt, und du gewöhnst dich am besten sofort daran. Die Kommentare dagegen schreibst du auf Deutsch: Sie sollen erklĂ€ren, warum etwas so gebaut ist, und das denkst du nun einmal auf Deutsch.
Nur die Bilddateien behalten ihre deutschen Namen â sie heiĂen eben so, wie sie heiĂen.
Wichtig ist die zweite Zahl: y wÀchst nach unten. Der Punkt (0, 0) ist die obere linke Ecke, nicht die untere. Das ist bei fast allen Bildschirmen so und der Grund, warum das untere Ufer bei y = 530 anfÀngt und nicht bei 0.
Test
Du solltest zwei grĂŒne Ufer sehen und einen weiĂen Punkt unten in der Mitte. Der Punkt ist vorerst die Ente.
Verschiebe sie: Ăndere duck_x auf 100 und fĂŒhre das Programm noch einmal aus.
Stufe 3: Die Ente bewegt sich â
Bisher gab es nur draw(). Jetzt kommt die zweite Funktion dazu, und der Unterschied zwischen beiden ist das Wichtigste an diesem ganzen Kapitel.
python
import pgzrun
WIDTH = 800
HEIGHT = 600
# Farben bekommen Namen, damit man den Teich an einer Stelle umfÀrben kann.
WATER = (74, 144, 180)
SHORE = (110, 170, 90)
# Solange die Ente ein Punkt ist, ist sie nichts weiter als zwei Zahlen.
duck_x = 400
duck_y = 565
def update():
global duck_x, duck_y
if keyboard.left:
duck_x = duck_x - 4
if keyboard.right:
duck_x = duck_x + 4
if keyboard.up:
duck_y = duck_y - 4
if keyboard.down:
duck_y = duck_y + 4
def draw():
screen.fill(WATER)
screen.draw.filled_rect(Rect(0, 0, 800, 70), SHORE)
screen.draw.filled_rect(Rect(0, 530, 800, 70), SHORE)
screen.draw.filled_circle((duck_x, duck_y), 22, (255, 255, 255))
pgzrun.go()draw und update
update() rechnet, draw() zeichnet. Beide werden sechzigmal pro Sekunde aufgerufen, erst update, dann draw.
In update() gehört alles hin, was sich verĂ€ndert: Bewegungen, TastendrĂŒcke, ZusammenstöĂe, Punkte. In draw() gehört nur hin, wie der aktuelle Zustand aussieht â dort wird nichts verĂ€ndert.
Wer beides vermischt, bekommt Spiele, die auf schnellen Rechnern schneller laufen als auf langsamen. Halte die zwei sauber getrennt.
keyboard.left ist wahr, solange die linke Pfeiltaste gedrĂŒckt ist â also in jedem Bild neu. Deshalb schleicht die Ente gleichmĂ€Ăig und hĂŒpft nicht.
Das global brauchst du, weil duck_x auĂerhalb der Funktion angelegt wurde. Ohne diese Zeile wĂŒrde Python beim ersten duck_x = ... eine neue, eigene Variable in der Funktion anlegen, und drauĂen bliebe alles beim Alten. In der nĂ€chsten Stufe wirst du es wieder los.
Test
FĂŒhre das Programm aus und steuere die Ente mit den Pfeiltasten ĂŒber den Teich. Sie darf dabei ruhig aus dem Bild laufen â das reparieren wir spĂ€ter.
Stufe 4: Aus Formen werden Bilder â
Jetzt brauchst du den images-Ordner von oben.
python
import pgzrun
WIDTH = 800
HEIGHT = 600
# Farben bekommen Namen, damit man den Teich an einer Stelle umfÀrben kann.
WATER = (74, 144, 180)
SHORE = (110, 170, 90)
# Der Name in Actor(...) ist der Dateiname: Die Bilder heiĂen deutsch, der Code englisch.
duck = Actor("ente")
duck.pos = (400, 565)
def update():
if keyboard.left:
duck.x = duck.x - 4
if keyboard.right:
duck.x = duck.x + 4
if keyboard.up:
duck.y = duck.y - 4
if keyboard.down:
duck.y = duck.y + 4
def draw():
screen.fill(WATER)
screen.draw.filled_rect(Rect(0, 0, 800, 70), SHORE)
screen.draw.filled_rect(Rect(0, 530, 800, 70), SHORE)
duck.draw()
pgzrun.go()Actor("ente") sucht die Datei images/ente.png â ohne Ordner, ohne Endung, nur der Name.
Actor
Ein Actor ist ein Objekt mit einem Bild. Er hat Attribute wie x, y, pos und angle, und er kann sich mit draw() selbst zeichnen. Ăndere x, und beim nĂ€chsten Bild steht er woanders.
Das ist genau die Klasse aus dem Objekte-Kapitel â nur hat sie diesmal jemand anderes geschrieben.
Zwei Zeilen sind verschwunden, und das ist kein Zufall: global ist weg. Vorher hast du der Variablen duck_x einen neuen Wert zugewiesen â dafĂŒr braucht Python die Erlaubnis. Jetzt Ă€nderst du nur ein Attribut innerhalb des Objekts. Die Variable duck zeigt weiterhin auf dieselbe Ente, also gibt es nichts zu erlauben.
Test
Die weiĂe Ente muss jetzt als Bild ĂŒber den Teich schwimmen. Wenn stattdessen eine Fehlermeldung mit images/ente.png kommt, heiĂt der Ordner falsch oder liegt an der falschen Stelle.
Eine eigene Ente?
Nimm ein beliebiges PNG mit durchsichtigem Hintergrund, leg es in den images-Ordner und schreib seinen Namen in Actor(...). Ein Frosch tut es auch.
Stufe 5: Ein Boot fĂ€hrt â
Das Boot bewegt sich, ohne dass jemand eine Taste drĂŒckt. Der Trick ist derselbe wie bei der Spirale im Variablen-Kapitel: In jedem Bild wird eine Zahl ein StĂŒck gröĂer.
Neu sind nur diese Zeilen:
python
boat = Actor("boot")
boat.pos = (0, 280)python
boat.x = boat.x + 3
if boat.x > 880:
boat.x = -80Und in draw(), vor der Ente, damit sie im Vordergrund bleibt:
python
boat.draw()Das Ganze zusammen:
python
import pgzrun
WIDTH = 800
HEIGHT = 600
# Farben bekommen Namen, damit man den Teich an einer Stelle umfÀrben kann.
WATER = (74, 144, 180)
SHORE = (110, 170, 90)
# Der Name in Actor(...) ist der Dateiname: Die Bilder heiĂen deutsch, der Code englisch.
duck = Actor("ente")
duck.pos = (400, 565)
boat = Actor("boot")
boat.pos = (0, 280)
def update():
if keyboard.left:
duck.x = duck.x - 4
if keyboard.right:
duck.x = duck.x + 4
if keyboard.up:
duck.y = duck.y - 4
if keyboard.down:
duck.y = duck.y + 4
boat.x = boat.x + 3
if boat.x > 880:
boat.x = -80
def draw():
screen.fill(WATER)
screen.draw.filled_rect(Rect(0, 0, 800, 70), SHORE)
screen.draw.filled_rect(Rect(0, 530, 800, 70), SHORE)
boat.draw()
duck.draw()
pgzrun.go()Warum 880 und â80? Das Boot ist 120 Pixel breit, boat.x ist seine Mitte. Bei 880 ist es also gerade vollstĂ€ndig rechts hinausgefahren, bei â80 steht es vollstĂ€ndig links auĂerhalb. Setzte man es schon bei 800 zurĂŒck, wĂŒrde es sichtbar verschwinden.
Test
Ein Boot muss von links nach rechts fahren und danach wieder von vorn anfangen. Ăndere die 3 in eine 8 und schau, was passiert. Ăndere sie in eine 0,5 â geht das?
Stufe 6: ZusammenstoĂ â
python
# ZurĂŒck an den Start â das wird gleich an mehreren Stellen gebraucht.
def back_to_start():
duck.pos = (400, 565)und in update(), hinter der Bootsbewegung:
python
if duck.colliderect(boat):
back_to_start()colliderect prĂŒft, ob sich die beiden Bilder ĂŒberlappen. Genauer: ob sich ihre Rechtecke ĂŒberlappen â auch die durchsichtigen Ecken zĂ€hlen mit. Deshalb wirkt die Ente manchmal etwas empfindlich. Fast alle Spiele rechnen so, weil es viel schneller geht als eine genaue PrĂŒfung.
Dass das ZurĂŒcksetzen in einer eigenen Funktion steht, ist kein Zufall: Ab Stufe 8 brauchst du es an zwei Stellen, und dann willst du es nur einmal geschrieben haben.
Das ganze Programm bis hierher
python
import pgzrun
WIDTH = 800
HEIGHT = 600
# Farben bekommen Namen, damit man den Teich an einer Stelle umfÀrben kann.
WATER = (74, 144, 180)
SHORE = (110, 170, 90)
# Der Name in Actor(...) ist der Dateiname: Die Bilder heiĂen deutsch, der Code englisch.
duck = Actor("ente")
duck.pos = (400, 565)
boat = Actor("boot")
boat.pos = (0, 280)
# ZurĂŒck an den Start â das wird gleich an mehreren Stellen gebraucht.
def back_to_start():
duck.pos = (400, 565)
def update():
if keyboard.left:
duck.x = duck.x - 4
if keyboard.right:
duck.x = duck.x + 4
if keyboard.up:
duck.y = duck.y - 4
if keyboard.down:
duck.y = duck.y + 4
boat.x = boat.x + 3
if boat.x > 880:
boat.x = -80
if duck.colliderect(boat):
back_to_start()
def draw():
screen.fill(WATER)
screen.draw.filled_rect(Rect(0, 0, 800, 70), SHORE)
screen.draw.filled_rect(Rect(0, 530, 800, 70), SHORE)
boat.draw()
duck.draw()
pgzrun.go()Test
Fahr absichtlich in das Boot. Die Ente muss unten wieder auftauchen.
Stufe 7: Viele Boote â
Ein Boot ist noch kein Hindernis. Drei sind eins â und drei Boote schreibt man nicht dreimal hin.
python
def new_boat(x, y, speed):
boat = Actor("boot")
boat.pos = (x, y)
boat.speed = speed # jedes Boot bekommt sein eigenes Tempo
return boat
boats = [
new_boat(100, 140, 2),
new_boat(500, 280, 4),
new_boat(300, 420, 3)
]boat.speed = speed ist der interessante Teil: Ein Actor darf zusĂ€tzliche Attribute bekommen, die es vorher nicht gab. Jedes Boot merkt sich damit sein eigenes Tempo â genau wie jedes Pferd im Objekte-Kapitel seine eigene Farbe hatte.
In update() und in draw() lĂ€ufst du jetzt ĂŒber die Liste:
python
for boat in boats:
boat.x = boat.x + boat.speed
if boat.x > 880:
boat.x = -80
if duck.colliderect(boat):
back_to_start()python
for boat in boats:
boat.draw()Das Bemerkenswerte: Ob drei Boote in der Liste stehen oder dreiĂig, Ă€ndert am Programm keine einzige Zeile. Das ist die Liste aus dem Listen-Kapitel â diesmal mit Objekten darin statt mit Zahlen.
Das ganze Programm bis hierher
python
import pgzrun
WIDTH = 800
HEIGHT = 600
# Farben bekommen Namen, damit man den Teich an einer Stelle umfÀrben kann.
WATER = (74, 144, 180)
SHORE = (110, 170, 90)
# Der Name in Actor(...) ist der Dateiname: Die Bilder heiĂen deutsch, der Code englisch.
duck = Actor("ente")
duck.pos = (400, 565)
def new_boat(x, y, speed):
boat = Actor("boot")
boat.pos = (x, y)
boat.speed = speed # jedes Boot bekommt sein eigenes Tempo
return boat
boats = [
new_boat(100, 140, 2),
new_boat(500, 280, 4),
new_boat(300, 420, 3)
]
# ZurĂŒck an den Start â das wird gleich an mehreren Stellen gebraucht.
def back_to_start():
duck.pos = (400, 565)
def update():
if keyboard.left:
duck.x = duck.x - 4
if keyboard.right:
duck.x = duck.x + 4
if keyboard.up:
duck.y = duck.y - 4
if keyboard.down:
duck.y = duck.y + 4
for boat in boats:
boat.x = boat.x + boat.speed
if boat.x > 880:
boat.x = -80
if duck.colliderect(boat):
back_to_start()
def draw():
screen.fill(WATER)
screen.draw.filled_rect(Rect(0, 0, 800, 70), SHORE)
screen.draw.filled_rect(Rect(0, 530, 800, 70), SHORE)
for boat in boats:
boat.draw()
duck.draw()
pgzrun.go()Test
Drei Boote in drei Bahnen, jedes in seinem Tempo. FĂŒge ein viertes hinzu und finde ein Tempo, bei dem das Spiel gerade noch schaffbar ist.
Stufe 8: KĂŒken zĂ€hlen und gewinnen â
Bisher kann man nicht verlieren, aber auch nicht gewinnen. Das Ă€ndert sich jetzt â hier ist das vollstĂ€ndige Spiel:
python
import pgzrun
WIDTH = 800
HEIGHT = 600
# Farben bekommen Namen, damit man den Teich an einer Stelle umfÀrben kann.
WATER = (74, 144, 180)
SHORE = (110, 170, 90)
# Der Name in Actor(...) ist der Dateiname: Die Bilder heiĂen deutsch, der Code englisch.
duck = Actor("ente")
duck.pos = (400, 565)
chick = Actor("kueken")
saved = 0
def new_boat(x, y, speed):
boat = Actor("boot")
boat.pos = (x, y)
boat.speed = speed # jedes Boot bekommt sein eigenes Tempo
return boat
boats = [
new_boat(100, 140, 2),
new_boat(500, 280, 4),
new_boat(300, 420, 3)
]
# ZurĂŒck an den Start â das wird gleich an mehreren Stellen gebraucht.
def back_to_start():
duck.pos = (400, 565)
def update():
global saved
if saved == 5:
return # Spielende: ab hier wird nicht mehr gerechnet, nur noch gezeichnet.
if keyboard.left:
duck.x = duck.x - 4
if keyboard.right:
duck.x = duck.x + 4
if keyboard.up:
duck.y = duck.y - 4
if keyboard.down:
duck.y = duck.y + 4
for boat in boats:
boat.x = boat.x + boat.speed
if boat.x > 880:
boat.x = -80
if duck.colliderect(boat):
back_to_start()
if duck.y < 70:
saved = saved + 1
back_to_start()
def draw():
screen.fill(WATER)
screen.draw.filled_rect(Rect(0, 0, 800, 70), SHORE)
screen.draw.filled_rect(Rect(0, 530, 800, 70), SHORE)
# Ein einziges KĂŒken-Objekt wird mehrfach hingesetzt und gezeichnet.
for i in range(saved):
chick.pos = (60 + i * 70, 35)
chick.draw()
for boat in boats:
boat.draw()
duck.draw()
screen.draw.text("Gerettet: " + str(saved) + " von 5",
(20, 550), fontsize=36, color=(255, 255, 255))
if saved == 5:
screen.draw.text("Alle KĂŒken sind drĂŒben!", center=(400, 300),
fontsize=64, color=(255, 255, 255))
pgzrun.go()Drei Stellen lohnen einen zweiten Blick.
Das return ganz oben in update(). Sind alle fĂŒnf KĂŒken drĂŒben, bricht die Funktion sofort ab: keine Bewegung, keine Boote, kein ZĂ€hlen. Gezeichnet wird trotzdem weiter â das Bild bleibt einfach stehen. Ein Spielende, in drei Zeilen.
Die Schleife ĂŒber range(saved). Sie zeichnet ein einziges KĂŒken-Objekt an mehreren Stellen hintereinander: hinsetzen, zeichnen, weitersetzen, zeichnen. FĂŒr ein Bild, das sich nicht bewegt, braucht man keine fĂŒnf Objekte.
saved braucht wieder global. Anders als duck.x ist es eine gewöhnliche Zahl, und die wird beim ZÀhlen neu zugewiesen. Genau der Unterschied aus Stufe 4.
Test
Spiel eine Runde durch. FĂŒnf KĂŒken mĂŒssen oben ankommen, dann steht die Meldung im Bild.
Stufe 9: Leben im Teich â
Das Spiel ist fertig. Diese Stufe verĂ€ndert nichts daran â sie lĂ€sst es nur besser aussehen.
Ein echtes Wellenmodell wĂ€re viel Arbeit. FĂŒnfzig helle Punkte, die langsam nach rechts wandern, sehen aus dieser Entfernung aber genauso gut aus. Effekte sind fast nie Physik.
python
import random
# FĂŒnfzig helle Punkte reichen als bewegtes Wasser.
waves = []
for i in range(50):
waves.append([random.randint(0, 800), random.randint(80, 520)])In update():
python
for wave in waves:
wave[0] = wave[0] + 1
if wave[0] > 800:
wave[0] = 0Und in draw() direkt nach screen.fill(WATER), damit die Punkte auf dem Wasser liegen und nicht auf den Booten:
python
for wave in waves:
screen.draw.filled_circle((wave[0], wave[1]), 2, (108, 168, 202))Jede Welle ist eine Liste aus zwei Zahlen: wave[0] ist x, wave[1] ist y. Eine Liste von Listen â mehr braucht es nicht.
Das ganze Programm bis hierher
python
import pgzrun
import random
WIDTH = 800
HEIGHT = 600
# Farben bekommen Namen, damit man den Teich an einer Stelle umfÀrben kann.
WATER = (74, 144, 180)
SHORE = (110, 170, 90)
# Der Name in Actor(...) ist der Dateiname: Die Bilder heiĂen deutsch, der Code englisch.
duck = Actor("ente")
duck.pos = (400, 565)
chick = Actor("kueken")
saved = 0
# FĂŒnfzig helle Punkte reichen als bewegtes Wasser.
waves = []
for i in range(50):
waves.append([random.randint(0, 800), random.randint(80, 520)])
def new_boat(x, y, speed):
boat = Actor("boot")
boat.pos = (x, y)
boat.speed = speed # jedes Boot bekommt sein eigenes Tempo
return boat
boats = [
new_boat(100, 140, 2),
new_boat(500, 280, 4),
new_boat(300, 420, 3)
]
# ZurĂŒck an den Start â das wird gleich an mehreren Stellen gebraucht.
def back_to_start():
duck.pos = (400, 565)
def update():
global saved
if saved == 5:
return # Spielende: ab hier wird nicht mehr gerechnet, nur noch gezeichnet.
if keyboard.left:
duck.x = duck.x - 4
if keyboard.right:
duck.x = duck.x + 4
if keyboard.up:
duck.y = duck.y - 4
if keyboard.down:
duck.y = duck.y + 4
for boat in boats:
boat.x = boat.x + boat.speed
if boat.x > 880:
boat.x = -80
if duck.colliderect(boat):
back_to_start()
for wave in waves:
wave[0] = wave[0] + 1
if wave[0] > 800:
wave[0] = 0
if duck.y < 70:
saved = saved + 1
back_to_start()
def draw():
screen.fill(WATER)
for wave in waves:
screen.draw.filled_circle((wave[0], wave[1]), 2, (108, 168, 202))
screen.draw.filled_rect(Rect(0, 0, 800, 70), SHORE)
screen.draw.filled_rect(Rect(0, 530, 800, 70), SHORE)
# Ein einziges KĂŒken-Objekt wird mehrfach hingesetzt und gezeichnet.
for i in range(saved):
chick.pos = (60 + i * 70, 35)
chick.draw()
for boat in boats:
boat.draw()
duck.draw()
screen.draw.text("Gerettet: " + str(saved) + " von 5",
(20, 550), fontsize=36, color=(255, 255, 255))
if saved == 5:
screen.draw.text("Alle KĂŒken sind drĂŒben!", center=(400, 300),
fontsize=64, color=(255, 255, 255))
pgzrun.go()Test
Der Teich muss jetzt leicht in Bewegung sein. Wenn es zu unruhig wirkt, nimm 20 Wellen statt 50 oder lass sie nur jedes zweite Bild wandern.
Kurzes Quiz â
Beantworte aus dem Kopf, dann sieh nach.
Warum steht die Bewegung in update() und nicht in draw()?
Weil draw() nur den aktuellen Zustand zeichnen soll. VerĂ€ndert man dort etwas, hĂ€ngt das Spielgeschehen davon ab, wie oft gezeichnet wird â und das ist auf jedem Rechner anders.
Warum braucht saved ein global, duck.x aber nicht?
saved = saved + 1 weist der Variablen einen neuen Wert zu. duck.x = ... verÀndert ein Attribut im Objekt; die Variable duck selbst bleibt dieselbe.
Wo mĂŒssen Bilddateien liegen?
In einem Ordner images direkt neben dem Programm. Actor("boot") findet damit images/boot.png.
Warum wird das Boot vor der Ente gezeichnet?
Weil spĂ€ter Gezeichnetes oben liegt. Zeichnete man das Boot zuletzt, wĂŒrde die Ente darunter verschwinden.
Challenge đđ â
Kein Lösungsweg, nur Ziele. Such dir aus, was dich reizt.
- Rand. Die Ente soll das Fenster nicht verlassen können.
- Leben. Drei ZusammenstöĂe, dann ist das Spiel vorbei. Zeig die verbleibenden Leben an.
- Schwerer werden. Nach jedem geretteten KĂŒken werden alle Boote ein bisschen schneller.
- Gegenverkehr. Ein Boot fĂ€hrt von rechts nach links. Du brauchst dafĂŒr ein zweites Bild â oder einen Trick mit
boat.angle. - Strömung. Im Wasser treibt die Ente langsam nach rechts ab, auf dem Ufer nicht.
- Seerosen. Sichere Felder, auf denen kein Boot fahren kann.
- Ton.
sounds.platsch.play()spieltsounds/platsch.wav. Freie GerÀusche findest du bei freesound.org.
Ein eigenes Spiel đđđ â
Du hast jetzt alles beisammen, was die meisten 2D-Spiele ausmacht: ein Fenster, eine Spielfigur, Steuerung, bewegte Gegner, ZusammenstöĂe, Punkte und ein Spielende. Was fehlt, ist nur noch eine Idee.
Fang klein an. Ein Spiel, das in zwei SĂ€tzen erklĂ€rt ist, wird meistens fertig; eines mit einer Weltkarte und drei Endgegnern nicht. Schreib zuerst auf, was man tun muss, um zu gewinnen â und dann, was einen daran hindert. Mehr braucht ein Spiel nicht.
Die vollstĂ€ndige Anleitung zu Pygame Zero, mit allem, was hier nicht vorkam â Töne, Musik, Zeitsteuerung, Animationen:
https://pygame-zero.readthedocs.io/de/latest/