Python Tutorial
- jetzt Python programmieren lernen

Pygame Library nutzen zum Spiele programmieren in Python

Pygame ist eine Bibliothek, die für uns die Spieleentwicklung mit Python sehr viel einfacher macht. Diese regelt für uns:

  • Elemente Zeichen wie Rechtecke, Kreise etc.
  • Bitmap-Grafiken anzeigen
  • Animationen von Elementen
  • Einbinden von Tastatur, Maus und Gamepads
  • Kollisionskontrolle
  • Sound abspielen

Pygame importieren/initialisieren

Da es sich um ein Modul handelt (muss auch erst installiert sein) muss dieses geladen und initialisiert werden. Das können wir gleich am Anfang von unserem Python-Programm erledigen:

# Importieren der Pygame-Bibliothek
import pygame

# initialisieren von pygame
pygame.init()

Starten wir nun unser Programm und ist Pygame installiert, erhalten wir als Ausgabe:

pygame 1.9.6

Hello from the pygame community. https://www.pygame.org/contribute.html

Unser Programm macht noch nichts – wir erhalten nur in der Konsole eine kleine Rückmeldung (aus der wir auch die Version der verwendeten Pygame-Library erfahren).

Sollte Pygame noch nicht installiert sein, dann erscheint eine Fehlermeldung. Dann bitte Pygame installieren.

Farben nutzen

Was wäre ein Spiel ohne Farben? Um Farben nutzen zu können, müssen wir diese festlegen. Hierbei hilft nicht, zu sagen wir wollen „orange“ verwenden und gut ist. Nein – Farben werden über die 3 Grundfarben rot, grün und blau festgelegt. Daher auch die Bezeichnung RGB. Dankbarweise fangen auf englisch die 3 Grundfarben mit den gleichen Buchstaben an (red, green, blue).

Aufbau der Farben über dezimal/hexadezimale Zahlen
Aufbau der Farben über dezimal/hexadezimale Zahlen

Zum Festlegen der Farben geben wir jeder dieser 3 Grundfarben einen Wert zwischen 0 und 255. Somit können wir über 16 Millionen verschiedener Farben nutzen. Geben wir dem ersten Wert (der für rot steht) die maximalen 255 und den zweiten und dritten Wert jeweils 0 erhalten wir ein Rot.

Geben wir allen 3 Grundfarben der Werten 255 erhalten wir weiß.

Haben alle 3 Grundfarben der Wert 0 erhalten wir Schwarz.

Mischen wir die Werte lustig, erhalten wir eine der 16,7 Millionen möglichen Farben.

Es gibt zahlreiche Dienste Online, über die man die RGB-Werte herausbekommt (wie beispielsweise https://www.webfx.com/web-design/color-picker/ ). Aber auch jedes Bildbearbeitungsprogramm zeigt Farbwerte als RGB-Werte an (man muss nur wissen, wo man suchen muss). Und darauf achten, dass wir dezimale Werte erhalten, ansonsten siehe weiter unten bei hexadezimalen Werten.

Nachdem die die gewünschte Farbe haben (unser Orange hat z.B. die Werte 255 bei Rot, 140 bei Grün und 0 bei Blau) können wir diese nutzen.

Die Farben werden in Pygame in Form von Tupel (siehe https://www.python-lernen.de/tupel.htm ) genutzt.

Hier als Beispiel (Erklärung von screen.fill() folgt später noch ausführlich).

screen.fill((255,140,0))

Dieses Schreibweise funktioniert zwar, aber macht wenig Spaß, da oft unklar ist, welche Farbe damit gemeint ist. Daher nutzen wir einfach Konstanten. Wie legen also unsere Farben also Konstante fest und nutzen dann den vergebenen Namen:

ORANGE = ( 255, 140, 0)
screen.fill(ORANGE)

So können wir am Anfang von unserem Spiel alle genutzten Farben definieren und haben dann einen übersichtlichen Code:

# genutzte Farbe
ORANGE  = ( 255, 140, 0)
ROT     = ( 255, 0, 0)
GRUEN   = ( 0, 255, 0)
SCHWARZ = ( 0, 0, 0)
WEISS   = ( 255, 255, 255)

Hexadezimale Schreibweise von Farben

Sollen die Farben in hexadezimaler Schreibweise genutzt werden, ist das in Python absolut kein Problem. Hexadezimal zeichnet sich dadurch aus, dass unsere Zahlen nicht von 0 bis 9 gehen, sondern bis 16. Daher benötigen wir ab 9 dann entsprechende Kodierung:

Dezimal Hexadezimal
8 8
9 9
10 A
11 B
12 C
13 D
14 E
15 F

Haben wir also den Maximalwert in Dezimal von 255 wird er als hexadezimale Zahl mit FF angegeben.

Wollen wir hexadezimale Zahlen in Python nutzen, wird vorweg „0x“ angegeben. Also für FF dann „0xFF“.

Unsere Farbdefinition von oben wäre also:

FF8C00

# genutzte Farbe
ORANGE  = ( 0xFF, 0x8C, 0x00)
ROT     = ( 0xFF, 0x00, 0x00)

Für die Nutzung ist es egal, ob man mit dezimalen oder hexadezimalen Zahlen arbeitet

ein Pygame-Fenster öffnen

Um ein Fenster für unser Spiel zu öffnen, benötigen wir die Anweisung pygame.display.set_mode(). Hier wird dann die Breite (erster Wert) und die Höhe (weiter Wert) übergeben.

Unser bisheriger Code:

# Importieren der Pygame-Bibliothek
import pygame

# initialisieren von pygame
pygame.init()

# genutzte Farbe
ORANGE  = ( 255, 140, 0)
ROT     = ( 255, 0, 0)
GRUEN   = ( 0, 255, 0)
SCHWARZ = ( 0, 0, 0)
WEiSS   = ( 255, 255, 255)

# Fenster öffnen
pygame.display.set_mode((640, 480))

Lassen wir nun unser Programm ausführen, kommt für einen Sekundenbruchteil das Fenster und verschwindet wieder. Logisch, da unser Programm ja sofort wieder beendet ist. Es halt alles erledigt und räumt dann ordentlich wie Python ist das angezeigt Fenster wieder auf.

Vielleicht wundert man sich anfangs über „set_mode“. Von der Logik her würde man ja auf irgendwas mit „open_window“ schließen. Das liegt daran, dass die pygame.display-Anweisung deutlich mehr kann außer ein Fenster zu erstellen.

Zusätzlich können wir unserem Fenster noch einen Titel verpassen, der dann später im Fensterkopf angezeigt wird. Dazu nutzen wir wieder unsere Anweisung pygame.display mit pygame.display.set_caption()

Schreiben wir einfach einmal in den Fensterkopf: „Unser erstes Pygame-Spiel“:

# Titel für Fensterkopf
pygame.display.set_caption("Unser erstes Pygame-Spiel")

Störend ist natürlich, dass sich unser gezeichnetes Fenster sofort wieder schließt. Daher wird es Zeit für Benutzeraktionen

mit dem Nutzer interagieren

Wir wollen nun dem Nutzer auch Möglichkeiten zur Interaktion bieten. Im ersten Schritt erstellen wir eine endlos ablaufende while-Schleife, bis der Nutzer den Exit-Button angeklickt hat.

Den Aufbau der Hauptroutine haben wir bereits in den vorherigen Kapiteln bei anderen Spielen kennen gelernt. Daher wird hier nicht nochmals darauf eingegangen. Unsere while-Schleife läuft so lange, wie unsere Variable mit dem Namen „spielaktiv“ auf „True“ gesetzt ist. Sprich vor der while-Schleife führen wir diese Variable ein.

Innerhalb der while-Schleife überprüfen wir, ob ein bestimmtes Ereignis (englisch event) stattgefunden hat wie z.B. das klicken auf den Exit-Button.

Schauen wir unseren bisherigen Code an:

# Importieren der Pygame-Bibliothek
import pygame

# initialisieren von pygame
pygame.init()

# genutzte Farbe
ORANGE  = ( 255, 140, 0)
ROT     = ( 255, 0, 0)
GRUEN   = ( 0, 255, 0)
SCHWARZ = ( 0, 0, 0)
WEiSS   = ( 255, 255, 255)

# Fenster öffnen
pygame.display.set_mode((640, 480))

# Titel für Fensterkopf
pygame.display.set_caption("Unser erstes Pygame-Spiel")

# solange die Variable True ist, soll das Spiel laufen
spielaktiv = True

# Schleife Hauptprogramm
while spielaktiv:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            spielaktiv = False

Die grundlegende Logik und der Ablauf

Um nun noch die Logik hinter unser Hauptprogramm-Schleife zu zeigen, integriere ich Anmerkungen, die später mit dem entsprechenden Code gefüllt werden.

Wichtig ist diese grundlegende Logik. Wer diese verletzt, kann in unnötige Probleme laufen. Wir haben in der Hauptschleife 5 Blöcke. Diese sollten auch nicht bunt gemischt werden.

Die Blöcke der Hauptschleife:

  • Nutzeraktion überprüfen (Tastatur/Maus etc.)
  • Spielelogik berechnen (wenn Figur bewegt wird, Kollision etc.)
  • Zeichnen von Spielfeld/figuren
  • Fenster löschen
  • Inhalt frisch zeichnen/Fenster aktualisieren

Dies sieht in unserem Programm wie folgt aus. Es wurden Platzhalter in Form von Anmerkungen eingebaut:

# Schleife Hauptprogramm
while spielaktiv:
    # Überprüfen, ob Nutzer eine Aktion durchgeführt hat
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            spielaktiv = False

    # Spiellogik hier integrieren

    # Spielfeld/figur(en) zeichnen (davor Spielfeld löschen)

    # Fenster aktualisieren

    # Refresh-Zeiten festlegen

Bei den Refresh-Zeiten wird die Häufigkeit der Fenster-Aktualisierung festgelegt. Diese darf weder zu häufig (bremst den Computer herunter) noch zu selten (Figuren bewegen sich merkwürdig) stattfinden.

Vor dem Zeichnen des Spielfelds und der Spielfigur(en) wird das Fenster gelöscht. Dazu zeichnen wir einfach den kompletten Bereich in der Grundfarbe. Hat unsere Spiel die Hintergrundfarbe Weiß, dann wäre unser Aufruf:

screen.fill(WEISS)

Unser Farbe in der Konstanten WEISS haben wir am Anfang definiert (zur Erinnerung: WEISS = ( 255, 255, 255).

Wichtig ist noch, dass der Zugriff auf screen eingerichtet wurde. Dazu wird beim „Fenster öffnen“ diese Zugriff festgelegt über:

# Fenster öffnen
screen = pygame.display.set_mode((640, 480))

Nach dem Zeichnen müssen wir das Fenster aktualisieren:

pygame.display.flip()

Bildschirmrefreshzeiten einstellen

Um diese Zeiten einzustellen, müssen wird folgende Zuweisung machen

# Bildschirm Aktualisierungen einstellen
clock = pygame.time.Clock()

Bei folgendem Code stellen wir 60 fps ein:

# 60 fps (frames per second)
clock.tick(60)

Wollen wir nur 10 Aktualisierungen pro Sekunden, dann ist die Angabe clock.tick(10)

Und nun der bisherige komplette Code:

# Schleife Hauptprogramm
while spielaktiv:
    # Überprüfen, ob Nutzer eine Aktion durchgeführt hat
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            spielaktiv = False
            print("Spieler hat Quit-Button angeklickt")

    # Spiellogik hier integrieren

    # Spielfeld löschen
    screen.fill(WEISS)

    # Spielfeld/figuren zeichnen

    # Fenster aktualisieren
    pygame.display.flip()

    # Refresh-Zeiten festlegen
    clock.tick(60)

Programm sicher beenden

Und um das Programm sauber zu beenden, wird das Programm über die Anweisung pygame.quit() sicher geschlossen. Wird dies nicht gemacht, kann durchaus das Programm „crashen“ und im Hintergrund weiterlaufen und Prozesse im Computer belegen.

Daher einfach am Ende:

pygame.quit()

Tastatur/Maus abfragen mit Pygames

Aber schauen wir uns noch die weiteren Möglichkeiten für die Spielerinteraktion an. Bisher haben wir nur den Exit-Button kennen gelernt. Genauso können wir die Tastatur abfragen. Erweitern wir unsere event-Anfrage. Bei jeder Aktion wird in der Konsole eine entsprechende Meldung ausgegeben:

# Schleife Hauptprogramm
while spielaktiv:
    # Überprüfen, ob Nutzer eine Aktion durchgeführt hat
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            spielaktiv = False
            print("Spieler hat Quit-Button angeklickt")
        elif event.type == pygame.KEYDOWN:
            print("Spieler hat Taste gedrückt")

Genauso können wir einen Klick mit der Maus abfragen über event.type == pygame.MOUSEBUTTONDOWN

# Schleife Hauptprogramm
while spielaktiv:
    # Überprüfen, ob Nutzer eine Aktion durchgeführt hat
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            spielaktiv = False
            print("Spieler hat Quit-Button angeklickt")
        elif event.type == pygame.KEYDOWN:
            print("Spieler hat Taste gedrückt")
        elif event.type == pygame.MOUSEBUTTONDOWN:
            print("Spieler hast Maus angeklickt")

Und für die meisten Spiele benötigen wir als Steuerung die Pfeiltasten auf der Tastatur. Diese werden über folgende Bezeichnungen angesprochen

  • K_LEFT
  • K_RIGHT
  • K_UP
  • K_DOWN
  • K_SPACE

Hier kommt nun die Besonderheit, dass wir nur dann in die Auswertung gehen, wenn im Allgemeinen eine Taste genutzt wird (und zwar beim herunterdrücken). Wir verschachteln also eine if-Abfrage in den Bereich elif event.type == pygame.KEYDOWN:

# Schleife Hauptprogramm
while spielaktiv:
    # Überprüfen, ob Nutzer eine Aktion durchgeführt hat
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            spielaktiv = False
            print("Spieler hat Quit-Button angeklickt")
        elif event.type == pygame.KEYDOWN:
            print("Spieler hat Taste gedrückt")
            if event.key == pygame.K_RIGHT:
                print("Spieler hat Pfeiltaste rechts gedrückt")
            elif event.key == pygame.K_LEFT:
                print("Spieler hat Pfeiltaste links gedrückt")
            elif event.key == pygame.K_UP:
                print("Spieler hat Pfeiltaste hoch gedrückt")
            elif event.key == pygame.K_DOWN:
                print("Spieler hat Pfeiltaste runter gedrückt")
            elif event.key == pygame.K_SPACE:
                print("Spieler hat Leertaste gedrückt")
        elif event.type == pygame.MOUSEBUTTONDOWN:
            print("Spieler hast Maus angeklickt")

Und weil wir gerade bei den wichtigsten Tasten sind (falls wir 2 Spieler haben), sollten wir auch die üblichen Tasten „w,a,s,d“ abfragen können. Diese Tastenkombination wurde mit dem Ego-Shooter Quake 1996 bekannt. Die Abfrage läuft über das Kürzel pygame.K_a: - sprich Großes K (für Keyboard) und Unterstrich und dann die gewünschte Taste.

# Schleife Hauptprogramm
while spielaktiv:
    # Überprüfen, ob Nutzer eine Aktion durchgeführt hat
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            spielaktiv = False
            print("Spieler hat Quit-Button angeklickt")
        elif event.type == pygame.KEYDOWN:
            print("Spieler hat Taste gedrückt")

            # Taste für Spieler 1
            if event.key == pygame.K_RIGHT:
                print("Spieler hat Pfeiltaste rechts gedrückt")
            elif event.key == pygame.K_LEFT:
                print("Spieler hat Pfeiltaste links gedrückt")
            elif event.key == pygame.K_UP:
                print("Spieler hat Pfeiltaste hoch gedrückt")
            elif event.key == pygame.K_DOWN:
                print("Spieler hat Pfeiltaste runter gedrückt")
            elif event.key == pygame.K_SPACE:
                print("Spieler hat Leertaste gedrückt")

            # Taste für Spieler 2
            elif event.key == pygame.K_w:
                print("Spieler hat Taste w gedrückt")
            elif event.key == pygame.K_a:
                print("Spieler hat Taste a gedrückt")
            elif event.key == pygame.K_s:
                print("Spieler hat Taste s gedrückt")
            elif event.key == pygame.K_d:
                print("Spieler hat Taste d gedrückt")

        elif event.type == pygame.MOUSEBUTTONDOWN:
            print("Spieler hast Maus angeklickt")

Unser bisher entstandener Code komplett:

# Importieren der Pygame-Bibliothek
import pygame

# initialisieren von pygame
pygame.init()

# genutzte Farbe
ORANGE  = ( 255, 140, 0)
ROT     = ( 255, 0, 0)
GRUEN   = ( 0, 255, 0)
SCHWARZ = ( 0, 0, 0)
WEISS   = ( 255, 255, 255)

# Fenster öffnen
screen = pygame.display.set_mode((640, 480))

# Titel für Fensterkopf
pygame.display.set_caption("Unser erstes Pygame-Spiel")

# solange die Variable True ist, soll das Spiel laufen
spielaktiv = True

# Bildschirm Aktualisierungen einstellen
clock = pygame.time.Clock()

# Schleife Hauptprogramm
while spielaktiv:
    # Überprüfen, ob Nutzer eine Aktion durchgeführt hat
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            spielaktiv = False
            print("Spieler hat Quit-Button angeklickt")
        elif event.type == pygame.KEYDOWN:
            print("Spieler hat Taste gedrückt")

            # Taste für Spieler 1
            if event.key == pygame.K_RIGHT:
                print("Spieler hat Pfeiltaste rechts gedrückt")
            elif event.key == pygame.K_LEFT:
                print("Spieler hat Pfeiltaste links gedrückt")
            elif event.key == pygame.K_UP:
                print("Spieler hat Pfeiltaste hoch gedrückt")
            elif event.key == pygame.K_DOWN:
                print("Spieler hat Pfeiltaste runter gedrückt")
            elif event.key == pygame.K_SPACE:
                print("Spieler hat Leertaste gedrückt")

            # Taste für Spieler 2
            elif event.key == pygame.K_w:
                print("Spieler hat Taste w gedrückt")
            elif event.key == pygame.K_a:
                print("Spieler hat Taste a gedrückt")
            elif event.key == pygame.K_s:
                print("Spieler hat Taste s gedrückt")
            elif event.key == pygame.K_d:
                print("Spieler hat Taste d gedrückt")

        elif event.type == pygame.MOUSEBUTTONDOWN:
            print("Spieler hast Maus angeklickt")

    # Spiellogik hier integrieren

    # Spielfeld löschen
    screen.fill(WEISS)

    # Spielfeld/figuren zeichnen

    # Fenster aktualisieren
    pygame.display.flip()

    # Refresh-Zeiten festlegen
    clock.tick(60)

pygame.quit()

Uns somit haben wir unser Template für unsere Spiele. Auf diese Basis können wir aufbauen.