Mit Verzweigungen können Code-Blöcke nur unter bestimmten Bedingungen ausgeführt werden. Eine Bedingung ist ein Ausdruck der True oder False ergibt.

# Bedingungen

Um zu entscheiden, ob ein Code-Block ausgeführt werden soll, wird immer eine Bedingung überprüft. Dies kann ein mathematischer Ausdruck sein.

  • Zahlen können mit den Vergleichsoperatoren <, >, >=, <=, == und != verglichen werden.
  • Variablen vom Typ bool haben den Wert True oder False
  • Zudem gibt es Unterprogramme welche eine Wahrheitswert zurückliefern
x > 12                   # True wenn x grösser als 12
y <= HEIGHT              # True wenn y kleiner oder gleich wie HEIGHT 

keyboard.a               # True wenn die Taste "A" gedrückt ist

zorg.collidepoint(pos)   # True wenn die Koordinaten "pos" auf den Actor "zorg" fallen
1
2
3
4
5
6

# Wenn-dann (if)

Alien prallt am linken Rand ab

Wenn Bedingung wahr, dann mache dies

if True/False:
   mach_etwas()
   
mach_weiter()
1
2
3
4
Zeile 1
True/False wird ersetzt mit Ausdruck der True oder False ergibt
Zeile 2
mach_etwas() wird ersetzt mit beliebigem Code.
Wird nur ausgeführt wenn der obige Ausdruck True ergibt.
Ist eingerückt.
Zeile 4
mach_weiter() wird ersetzt mit Code der immer ausgeführt wird.
Ist nicht mehr eingerückt.

# Beispiel

Unser Alien besitzt eine konstante horizontale Geschwindigkeit vx und eine vertikale Geschwindigkeit vy die durch die Beschleunigung GRAVITATION verändert wird. Mit drei if können die Situationen abgefangen werden, wenn der Alien den unteren, den linken oder den rechten Rand berührt:

def update(dt):
    zorg.vy = zorg.vy + dt * GRAVITATION
    zorg.y = zorg.y + dt * zorg.vy
    zorg.x = zorg.x + dt * zorg.vx

    if zorg.bottom > HEIGHT:
        zorg.bottom = HEIGHT
        zorg.vy = -zorg.vy
        
    if zorg.left > WIDTH:
        zorg.right = 0
        
    if zorg.right < 0:
        zorg.left = WIDTH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ab Zeile 6
Wenn die Füsse des Aliens das Fenster verlassen, dann wird die vertikale Geschwindigkeit «gespiegelt» – der Alien springt am unteren Rand ab. Zur Sicherheit wird der Alien zusätzlich auf den untersten Punkt gesetzt.
ab Zeile 10
Wenn der linke Rand des Aliens rechts aus dem Bild verschwindet, dann wird er auf den linken Rand des Fensters gesetzt
ab Zeile 13
Wenn der rechte Rand des Aliens links aus dem Bild verschwindet, dann wird er auf den rechten Rand des Fensters gesetzt

Aufgabe

Baue eine Überprüfung ein, so dass der Alien das Fenster nicht mehr verlassen kann. Du kannst entweder ein wrap machen («links raus» heisst «rechts wieder rein») oder einfach ein Block, so dass er am Rand nicht mehr weiter kann.

# Wenn-dann-sonst-wenn-dann (if-elif)

Alien-Steuerung

Wenn Bedingung wahr, dann mache dies, sonst wenn andere Bedingung wahr, dann mache das

if True/False:
   mach_dies()
elif True/False:
   mach_das()
elif True/False:
   mach_jenes()
   
mach_weiter()
1
2
3
4
5
6
7
8

# Beispiel: Tastatur-Steuerung

Wir wollen unseren Alien mit den drei Tasten , und SPACE steuern: Rechts und links setzt die horizontale Geschwindigkeit auf einen festen Wert. Die Leertaste erhöht die vertikale Geschwindigkeit nach oben.

def on_key_down(key):
    if key == keys.RIGHT:
        zorg.vx = SPEED
    elif key == keys.LEFT:
        zorg.vx = -SPEED
    elif key == keys.SPACE:
        zorg.vy = zorg.vy - 10 
1
2
3
4
5
6
7

Aufgabe

Baue eine Tastatursteuerung ein. Überlege dir folgende Punkte:

  • Welche Tasten möchtest du verwenden?
  • Was soll ein Tastendruck machen?

# Wenn-dann-sonst (if-else)

oder auch: Wenn-dann-sonst-wenn-dann-sonst-wenn-dann-…-sonst (if-elif-else)

Alien mit Mausklick treffen

Wenn Bedingung wahr, dann mache dies, sonst mach das

if True/False:
   mache_dies()
else:
   mache_das()
1
2
3
4

# Beispiel

Wir könnten z.B. überprüfen, ob bei einem Mausklick, ein Actor getroffen wird oder nicht:

def on_mouse_down(pos):
    if zorg.collidepoint(pos):
        print("Treffer!")
    else:
        print("Daneben!")
1
2
3
4
5
Zeile 1
Wir definieren das Unterprogramm das bei einem Mausklick aufgerufen werden soll.
Zeile 2
collidepoint liefert True, wenn der Actor zorg mit den Mauskoordinaten pos «kollidiert» – also die Mauskoordinaten im Bereich des Aliens liegen.

Aufgabe

Versuche auch eine Maussteuerung einzubauen. Was könnte man damit erreichen?

# Zusammenfassung if in Python

Alles zusammen lässt sich nun kombinieren zu:

if True/False:
   mache_dies()
elif True/False:
   mache_das()
else:
   mache_jenes()
1
2
3
4
5
6

Hinweis

  • Die If-Struktur in Python startet zwingend mit einem if.
  • Dann folgen 0-∞ elif.
  • Am Schluss kann ein else stehen.

# Ereignisse in Pygame-Zero

Hierbei handelt es sich um spezielle Unterprogramme, die von Pygame-Zero automatisch aufgerufen werden, wenn ein entsprechendes Ereignis eintritt. Als Argumente erhalten wir Details zum Ereignis (Mauskoordinaten, welche Maus-Taste wurde gedrückt, welche Keyboard-Taste wurde getippt, …). Anhand dieser Details können wir entscheiden wie sich das Ereignis auf unser Spiel auswirkt.

# Tastatur

Bei den Tastatur-Ereignissen entscheidet man zwischen Taste runterdrücken und wieder loslassen. Beide von den Ereignissen aufgerufene Unterprogramme erhalten als Argument die gedrückte Taste:

def on_key_down(key):
    print(key, "wurde runtergedrückt")
    
def on_key_up(key):
    print(key, "wurde losgelassen")
1
2
3
4
5

Die komplette Liste der überprüfbaren Tasten findet man hier:
https://pygame-zero.readthedocs.io/en/stable/hooks.html#buttons-and-keys (opens new window)

# Maus

Die Ereignisse der Maus werden in drei Unterprogrammen zusammengefasst: «Maustaste heruntergedrückt», «Maustaste losgelassen» und «Maus verschoben»:

def on_mouse_down(pos, button):
    print("Mouse button", button, "clicked at", pos)
    
def on_mouse_up(pos, button):
    print("Mouse button", button, "released at", pos)    
    
def on_mouse_move(pos, rel, buttons):    
    print("Mouse moved", button, "released at", pos, "relative distance", rel)    
1
2
3
4
5
6
7
8

Bei allen drei Unterprogrammen können ein, mehrere und auch alle Argumente weggelassen werden!

# Clock

Ein weiteres wichtiges Ereignis sind gestellte Timer. So können wir irgendwann einen Timer starten. Wenn dieser abläuft, wird ein Unterprogramm aufgerufen:

def on_mouse_down(pos):
    if zorg.collidepoint(pos):
        zorg_hurt()
        clock.schedule_unique(zorg_normal, 1)
    else:
        print("Daneben!")

def zorg_hurt():
    zorg.image = "alien_hurt"
    
def zorg_normal():
    zorg.image = "alien"    
1
2
3
4
5
6
7
8
9
10
11
12

Solche Timer setzen wir mit clock.schedule. Als Argument geben wir den Namen des Unterprogrammes an (ohne Klammern! – wir rufen es ja noch nicht auf) und die Dauer des Timers in Sekunden.

clock kennt neben schedule noch zwei weitere Befehle:

  • schedule_unique – Event nur ein mal auslösen
  • schedule_interval – Event immer wieder in zeitgleichen Abständen aufrufen
  • unschedule – ein Event deaktivieren (nur 1. Argument)

# komplettes Beispiel

Wenn wir alle Teile dies

"""
Autor: S. Forster
Datum: 11.12.2019
Beschreibung: Alien lässt sich steuern mit Gravitation
"""

WIDTH = 600
HEIGHT = 500
SPEED = 80

zorg = Actor('alien')
zorg.x = 100
zorg.y = 100
zorg.vx = SPEED
zorg.vy = 0

BROWN = 120,102,102
EARTHBLUE = 12,23,200
MARSRED = 200,23,20
GRAVITATION = 20
GROUND = Rect((0, HEIGHT-60), (WIDTH, 60))

def zorg_hurt():
    zorg.image = "alien_hurt"
    
def zorg_normal():
    zorg.image = "alien"

def draw():
    screen.clear()
    screen.draw.filled_circle((120,20), 30, MARSRED)
    screen.draw.filled_circle((480,320), 180, EARTHBLUE)
    screen.draw.filled_rect(GROUND, BROWN)
    zorg.draw()
    
def update(dt):
    zorg.vy = zorg.vy + dt * GRAVITATION
    zorg.y = zorg.y + dt * zorg.vy
    zorg.x = zorg.x + dt * zorg.vx

    if zorg.bottom > HEIGHT:
        zorg.bottom = HEIGHT
        zorg.vy = -zorg.vy
        
    if zorg.left > WIDTH:
        zorg.right = 0
        
    if zorg.right < 0:
        zorg.left = WIDTH
    
    
def on_key_down(key):
    if key == keys.RIGHT:
        zorg.vx = SPEED
    elif key == keys.LEFT:
        zorg.vx = -SPEED
    elif key == keys.SPACE:
        zorg.vy = zorg.vy - 10 
    else:
        print("Die Taste", key, "ist nicht belegt ;-)")
        
def on_mouse_down(pos, button):
    if zorg.collidepoint(pos):
        zorg_hurt()
        clock.schedule_unique(zorg_normal, 1)
    else:
        print("Daneben!")   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

# Weitere Steuerungsmöglichkeiten

Die Keyboard-Tasten können auch im Game-Loop abgefragt werden. Dies kann man verwenden um Steuerung zu programmieren, die nicht auf einzelne Ereignisse reagieren. Z.B. bei einem Jump & Run à la Mario würde der Sprung als Ereignis programmiert, die Seitwärtsbewegung aber im Game-Loop abgefragt werden.

Mehrere Tasten können gleichzeitig gedrückt sein!

def update(dt):
    ...
    if keyboard.right:
        zorg.vx = zorg.vx + 1
    if keyboard.left:
        zorg.vx = zorg.vx - 1
    if keyboard.space:
        zorg.vy = zorg.vy - 2 
    ...
1
2
3
4
5
6
7
8
9

keyboard.right ist sozusagen eine Variable. Sie kann True oder False sein, je nachdem ob die Taste momentan gedrückt ist oder nicht.

Aufgabe

Schaffst du es, die Steuerungen zu kombinieren und das Alien wie bei einem Jump & Run herumrennen zu lassen?

Letzte Änderung: 11.12.2019, 10:25:44