Python Tutorial
- jetzt Python programmieren lernen

Breakout-Ball im Spiel zeichnen und bewegen

Als Nächstes wollen wir unseren Ball für unser Breakout-Spiel zeichnen. Hierbei werden wird wieder unsere bisher verwendete Größe nutzen. Der Ball wird eine Größe von 20 auf 20 Pixel haben.

Auch für das Zeichnen des Balls erstellen wir eine Funktion mit dem Namen ball_zeichnen():

def ball_zeichnen(x,y):
    pygame.draw.ellipse(fenster, SCHWARZ, [kor(x), kor(y),kor(1), kor(1)], 0)

Unser Ball benötigt eine Position in unserem Fenster. Dazu erstellen wir 2 Variablen: ball_x und ball_y. Diese könnten wir zwar per Zufall setzen, der Einfachheit halber setzen wir diese für den Anfang einfach fix:

# Spielball Variablen
ball_x = 10
ball_y = 23

Der Ball hat noch eine Bewegungsrichtung, die durch 2 Variablen gespeichert wird. Die verwendeten Variablen sind: ball_x_richtung und ball_y_richtung.

Dabei können diese Variablen positiv wie negativ sein und somit sind alle 4 Bewegungsrichtungen abgedeckt:

ball_x_richtung ball_y_richtung Bewegungsrichtung
1 1 rechts unten
1 -1 rechts oben
-1 1 links unten
-1 -1 links oben

Der Ball muss sich immer schräg bewegen, da bei einer geraden Bewegung das Abprallen vom Schläger denn Ball exakt in die Richtung zurückwerfen würde, woher er gerade kam (was für das Spiel nicht besonders sinnvoll wäre).

Wir ergänzen unsere Variablen:

# Spielball Variablen
ball_x = 10
ball_y = 23
ball_x_richtung = 1
ball_y_richtung = 1

Wer mehr Zufall an der ersten Position haben möchte, versieht einfach der Position ball_x mit einer zufälligen Zahl zwischen 3 und 16 (ganz an den Rand macht am Anfang auch nicht wirklich Sinn, daher der Abstand zwischen 0 und 3 und im oberen Bereich):

# Spielball Variablen
ball_x = random.randint(3,16)
ball_y = 23
ball_x_richtung = 1
ball_y_richtung = 1

Innerhalb unserer Hauptprogramm-Schleife zeichnen wir nun den Ball:

# Schleife Hauptprogramm
while spielaktiv:
    # Überprüfen, ob Nutzer eine Aktion durchgeführt hat
    for event in pygame.event.get():
        if event.type == pygame.QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            spielaktiv = False
            print("Spieler hat beendet")

    # Ball zeichnen
    ball_zeichnen(ball_x, ball_y)

Keine Bewegung vom Ball macht natürlich wenig Spaß in einem Spiel. Daher werden wir denn Ball pro Durchgang über unsere 2 Variablen ball_x_richtung und ball_y_richtung weiterbewegen.

    ball_x += ball_x_richtung
    ball_y += ball_y_richtung

    # Ball zeichnen
    ball_zeichnen(ball_x, ball_y)

Während dem Entwickeln unseres Breakout-Spiels ist diese Bewegung nun ein wenig schnell. Daher schalten wir auf Zeitlupe um. Unsere Refresh-Zeit ist zu schnell – also schalten wir die Zeitlupe ein über clock.tick(3).

Jetzt sieht man schön, wie unser Ball in Zeitlupe am Rand aus dem Bildschirmfenster verschwindet und zusätzlich eine Spur hinterlässt.

Ball flüchtet aus Bildschirmfenster
Ball flüchtet aus Bildschirmfenster

Zur Kontrolle lassen wir uns in der Konsole die aktuelle Position ausgeben:

    # Ball zeichnen
    ball_zeichnen(ball_x, ball_y)
    print("Ballposition X=", ball_x, " / Y = ", ball_y)

Wir sehen in der Konsole, dass ab einer Position von Y=30 der Ball als Nächstes unten verschwindet. Solange wir noch keinen Schläger haben, soll der Ball im Spiel bleiben. Daher ändern wir die Y-Richtung des Balls, sobald er die untere Bildschirmkante erreicht.

    # Spiellogik
    if ball_x >= 19:
        ball_x_richtung = -1

    ball_x += ball_x_richtung
    ball_y += ball_y_richtung

    # Ball zeichnen
    ball_zeichnen(ball_x, ball_y)
    print("Ballposition X=", ball_x, " / Y = ", ball_y)

Aber bevor unser Ball an allen 4 Seiten abprallt, müssen wir alle 4 Seiten kontrollieren. Auch das kommt an den Punkt innerhalb der Hauptschleife bei der Spiellogik (genaugenommen Bewegungslogik).

Ball prallt an allen 4 Seiten ab
Ball prallt an allen 4 Seiten ab
# Schleife Hauptprogramm
while spielaktiv:
    # Überprüfen, ob Nutzer eine Aktion durchgeführt hat
    for event in pygame.event.get():
        if event.type == pygame.QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            spielaktiv = False
            print("Spieler hat beendet")

    # Spiellogik
    if ball_x <= 0:
        ball_x_richtung = 1
    if ball_x >= 19:
        ball_x_richtung = -1
    if ball_y <= 0:
        ball_y_richtung *= -1
    if ball_y >= 29:
        ball_y_richtung *= -1

    ball_x += ball_x_richtung
    ball_y += ball_y_richtung

    # Ball zeichnen
    ball_zeichnen(ball_x, ball_y)
    print("Ballposition X=", ball_x, " / Y = ", ball_y)

    # Fenster aktualisieren
    pygame.display.flip()

    # Refresh-Zeiten festlegen
    clock.tick(3)

pygame.quit()

Nun wollen wir die Felder löschen, wo der Ball sich davor befunden hat. Dazu zeichnen wir einfach ein weißes Viereck an die alte Position. Würden wir es mit der Trennung zwischen Spiellogik und Ausgabelogik (Ball zeichnen etc.) nicht genau nehmen, würden wir keine weiteren Variablen benötigen. Wir wollen aber so nachvollziehbar wie möglich programmieren und daher trennen wir. Es gibt 2 neue Variablen, in der die alte Position des Balls gespeichert werden.

# Spielball Variablen
ball_x = random.randint(3,16)
ball_y = 23
ball_x_richtung = 1
ball_y_richtung = 1
ball_x_alt = 0
ball_y_alt = 0

In diesen Variablen werden bei jedem Durchgang die alten Positionen gespeichert, bevor die Positionen neu gesetzt werden:

    ball_x_alt = ball_x
    ball_y_alt = ball_y
    ball_x += ball_x_richtung
    ball_y += ball_y_richtung

    # Ball zeichnen
    ball_zeichnen(ball_x, ball_y)

Und nun müssen wir nur noch die alte Position löschen. Dazu erstellen wir uns eine Funktion element_loeschen(). Diese ist ähnlich der Zeichenfunktion für unsere Mauersteine (nur mit Weiß als Farbe):

def element_loeschen(spalte,reihe):
    pygame.draw.rect(fenster, WEISS, [kor(spalte), kor(reihe),kor(1),kor(1)])

Diese Funktion zum Löschen des Inhalts an der alten Bildschirmposition wird vor dem Zeichnen der neuen Ballposition aufgerufen:

    # Ball zeichnen
    element_loeschen(ball_x_alt, ball_y_alt)
    ball_zeichnen(ball_x, ball_y)

Wir haben ein interessantes Ergebnis:

Ball prallt an Mauersteinen nicht ab, sondern hinterlässt eine Schneise
Ball prallt an Mauersteinen nicht ab, sondern hinterlässt eine Schneise

Weiterempfehlen • Social Bookmarks • Vielen Dank

Bitte unterstützen Sie dieses Projekt

Sie können dieses Projekt in verschiedenen Formen unterstützen - wir würden uns freuen und es würde uns für weitere Inhalte motivieren :).

Empfehlen Sie es weiter - wir freuen uns immer über Links und Facebook-Empfehlungen.

Das neue E-Book zum Kurs gibt es zum Kaufen.

Sie können uns auch eine Spende über PayPal zukommen lassen.

Bestellen Sie Bücher über folgenden Link bei Amazon:
Bücher über Python

Vielen Dank für Ihre Unterstützung