Gruppenkollisionen und verschiedene Fensterausgaben¶
Lernziele
- Mehrer Sprite Objekte der gleichen Sorte erstellen
- Gruppenkollisionen
- Verschiedene Bildschirme anzeigen lassen
- Event Tastendruck und Taste loslassen
Einführung¶
Als Vorlage dient das folgende Programm. Lade es herunter und starte es.
Es finden sich eine Maus, welche mit den Pfeiltasten bewegt werden kann, eine Münze und etwas Text auf dem Spielfenster. Beim Endprogramm liegen dann mehrere Münzen herum, welche von der Maus eingesammelt werden sollen. Nachdem die Maus alle Münzen eingesammelt hat, soll ein Endbildschirm erscheinen, welcher das Ende des Spiels anzeigt. Um dies alles zu implementieren, gehen wir die folgenden Schritte durch.
Mehrer Sprite Objekte der gleichen Sorte erstellen¶
Zuerst sollen mehr als nur eine Münze auf dem Bildschirm erscheinen, z.B. 6 Münzen. Dies wird im Abschnitt "Globale Variabeln initialisieren" durchgeführt.
Für die eine Münze wird aktuell einfach die Variable munze verwendet.
Wenn wir nun aber insgesamt 6 Münzen oder auch mehr erstellen wollen,
macht es keinen Sinn dafür 6 verschienden Variablen
(z.B. munze1, munze2, munze3,...) zu gebrauchen.
Eine Liste, hier eine Sprite-Group,
ist für unseren Fall die ideale Datenstruktur.
- Passe den Wert der Variable
anzahl_munzenauf die gewünschte Anzahl Münzen an. - Erstelle gleich danach eine neue Sprite Gruppe und speichere sie
z.B. unter dem Namen
all_munzen. -
In einer
4. Nachdem alle Münzen erstellt worden sind, müssen sich der Gruppefor-Schleife sollen nunanzahl_munzenMünzen erstellt werden und der Gruppeall_munzenhinzugefügt werden. Dies kann wie folgt in derfor-Schleife gemacht werden:all_spriteshinzuefügt werden, damit sie dann auch auf dem Bildschirm dargestellt werden. Dies geht ganz einfach mittels 5. Teste das Programm.
Gruppenkollisionen¶
Jetzt schicken wir die Maus auf Münzenjagd.
Um Kollisionen zwischen Sprites festzustellen findest du in der
Pygame Dokumentation
eine ganze Liste an verschiedenen Kollisionfunktionen.
Im letzten Kapitel haben wir die beiden Funktionen
collide_rect() und collide_mask() kennengelernt.
Dabei konnte eine Berührung zwischen zwei Sprites festgestellt werden.
Da wir nun aber eine ganze Liste (hier alle Münzen in der Liste all_munzen)
auf Berührung mit der Maus überprüfen müssen,
eigenen sich dafür andere Funktionen viel besser.
-
Welche Collide-Funktionen in der Pygame Dokumentation würdest du für unsere Situation als geeignet betrachten?
Lösung
spritecollide()passt perfekt für unsere Sitauation.Beschreibung der Funktion:
Find sprites in a group that intersect another sprite.
-
Verwende diese Kollisionsfunktion in unserer globalen Funktion
is_a_collision(). Implementiere deren Funktionalität. Hier ein paar Erklärungen.Erklärung der Parameter:
-
sprite: Mit welchem Sprite Objekt soll eine Kollision festgestellt werden?In unserem Code wäre das
maus. -
group: Die Liste der Sprite Objekte mit der eine Kollision mitspritefestgestellt werden soll.In unserem Code wäre das
all_munzen. -
dokill: Soll bei einer Kollision das Sprite Objekte ausgroupaus dem Spiel entfernt werden?Bei uns lautet die Antwort "ja" (also
True), da die Münze, welche die Maus berührt, nach einer Berührung nicht mehr auf dem Bildschirm erscheinen soll. -
collided = None: Welche Kollisionsüberprüfung soll verwendet werden?Wir wollen bei einer Pixelkollision eine Berührung feststellen und d.h. in unserem Code
collided = py.sprite.collide_mask.
Als Rückgabeparameter erhalten wir eine Liste mit allen Sprites aus
group, mit denen eine Kollision festgestellt wurde. Wenn diese Liste also nicht leer ist, hat unsere Maus eine Münze berührt. -
-
Teste, ob die globale Funktion
is_a_collision()funktioniert. Falls bei einer Berührung der Maus mit einer Münze das Spiel beendet wird, so funktioniert sie. -
Ändere das Programm nun so ab, dass bei einer Berührung der Maus mit einer Münze nicht das Programm beendet wird, sondern sich der Zähler im Text auf dem Bildschrim A"nzahl verbleibende Münzen" entsprechend anpasst.
Hinweis: Mit
len(all_munzen)können wir die Anzahl der übrigen Münzen im Spiel abfragen. -
Wurden alle Münzen eingesammelt, so soll das Programm beendet werden.
Endbildschirm¶
Bei einem "normalen" Spiel ist es üblich, dass z.B. vor dem eigentlichen Spielbeginn ein Startbild erscheint, mit gewissen Instruktionen. Bei Spielende könnte auch ein entsprechendes Fenster erscheinen, welches uns über das Ende des Spiels informiert. Ein solches Verhalten wollen wir nun in unserem Spiel implementieren.
Es gibt gewiss unzählige Methoden, um einen solchen Fensterwechsel zu implementieren. Hier wird eine vorgestellt.
-
Definieren im Abschnitt "Globale Variabeln initialisieren" eine neue Variable
which_window, deren Wert bestimmt, auf welchem Bildschirm wir uns befinden.0: Bildschirm während des Spiels1: Endschirm, erscheint wenn alle Muenzen eingesammelt wurden
-
Schaue dir im Programmcode die "Hauptschleife" an und überlege dir, welche Codezeilen auch beim Endbildschirm ausgeführt werden sollen und welche nicht.
Setze alle Zeilen, welche nur beim Spielbildschirm ausgeführt werden sollen, in einen
if-Block. Hierif which_window == 0:. Wenn du das Programm ausführst, sollte alles noch genau gleich ablaufen.Hinweis
Die beiden Codeblöcke
########################################## # Events abfragen ########################################## for event in py.event.get(): # Wird das Fenster geschlossen, soll # auch das Spiel beendet werden if event.type == py.QUIT: game_is_running = Falseund
gehören nicht in den
if-Block und sollten somit immer ausgeführt werden. -
Erweitere den
if which_window == 0:Block mit einemelse-Block, in welchem die Darstellung des Endbildschirms implementiert werden soll. Dieser könnte so aussehen. -
Teste die Implementation deines Endbildschirms, indem du
which_windowvor der Hauptschleife auf1setzt. Setze für diesen Test einen beliebigen Wert für die Endzeit. -
Setze
which_windowwieder auf0.Ergänze nun den
if which_window == 0:Block so, dass, nachdem alle Münzen eingesammelt wurden, der Endbildschirm erscheint.
Tastendruck¶
Wir bauen noch eine kleine Zusatzfunktion ein. Das Programm kann ja nur durch Schliessen des Fensters beendet werden. Zusätzlich soll dies auch durch Drücken der ESC-Taste geschehen, jedoch erst dann, wenn die ESC-Taste losgelassen wird.
Ergänze im for event in py.event.get(): Block,
das if Statement um die folgende Funktionalität:
Der Befehl event.type == py.KEYUP sorgt dafür,
dass das Programm erst beim Loslassen der ESC-Taste beendet wird.


