Python Tutorial
- jetzt Python programmieren lernen

Kollision zwischen Ball und Mauerstein, der dann verschwindet

In unseren bisherigen Code integrieren wir das Spielverhalten, dass bei Kollision mit dem Ball der Mauerstein verschwindet. Hier der bisher erstellte Code (ein wenig erweitert – es wurde eine „Schritt-für-Schritt“-Funktion eingebaut, damit man in Ruhe die Zahl kontrollieren kann. Bei jedem drücken der Leertaste bewegt sich unser Ball erst weiter):

import pygame, sys, time, random
from pygame.locals import *

# unser Multiplikator 
MULTIPLIKATOR = 20

# Spielfeld erzeugen über Berechnung
fenster = pygame.display.set_mode((20 * MULTIPLIKATOR, 30 * MULTIPLIKATOR))

# Titel für Fensterkopf
pygame.display.set_caption("Breakout in Python")
spielaktiv = True

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

# genutzte Farben
ORANGE  = ( 255, 140,   0)
SCHWARZ = (   0,   0,   0)
WEISS   = ( 255, 255, 255)

# Spielfeld mit Mauersteinen 
karte=[
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
[0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0],
[0,1,1,1,1,1,0,0,1,1,1,1,0,0,1,1,1,1,1,0],
[0,1,1,1,1,1,0,0,1,1,1,1,0,0,1,1,1,1,1,0],
[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,1,1,1,1,1,0,0,1,1,1,1,0,0,1,1,1,1,1,0],
[0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0],
[0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0],
[0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
[0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
]

# 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

# Hintergrundfarbe Fenster
fenster.fill(WEISS)

# Korrekturfaktor berechnen
def kor(zahl):
    zahl = zahl * MULTIPLIKATOR
    return zahl

# Spielelement zeichnen
def element_zeichnen(spalte,reihe):
    pygame.draw.rect(fenster, ORANGE, [kor(spalte)+1, kor(reihe)+1,kor(1)-1,kor(1)-1])

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

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

# Ausgabe Mauersteine im Spielfenster
for x in range(0,20):
    for y in range(0,27):
        if karte[y][x] != 0:
            element_zeichnen(x,y)

naechsterschritt = False

# 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")

        if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
            naechsterschritt = True
            print("Nächster Schritt")

    # 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 trifft Ziegelstein

    if naechsterschritt == True:
        ball_x_alt = ball_x
        ball_y_alt = ball_y
        ball_x += ball_x_richtung
        ball_y += ball_y_richtung
        naechsterschritt = False

    # Ball zeichnen
    element_loeschen(ball_x_alt, ball_y_alt)
    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()

Wir wissen, dass wenn der Ball sich in der Aufwärtsbewegung befindet, die Variable ball_y_richtung dann den Wert -1 hat. Damit müssen wir also überprüfen, ob das Feld oberhalb der aktuellen Ballposition einen Mauerstein in dem Listenobjekt karte eingetragen hat. Ob es das rechte oder linke ist, sagt uns die Variable ball_x_richtung

im nächsten Schritt trifft der Ball den Mauerstein, der dann verschwinden muss
im nächsten Schritt trifft der Ball den Mauerstein, der dann verschwinden muss

Schauen wir uns die Berechnung an. Wir haben folgenden 4 Werte:

  • ball_x
  • ball_y
  • ball_x_richtung
  • ball_y_richtung

Daraus ergibt sich unserer Kontrolle:

    # Ball trifft Ziegelstein
    # Kontrolle auf möglich Kollision
    if ball_y_richtung == -1:
        # Ball ist in Aufwärtsbewegung
        # genau darüber ein Mauerstein?
        if karte[ball_y-1][ball_x] != 0:
            print("trifft Mauerstein rechts oberhalb")
            ball_y_richtung = 1

Nun wird der Ball nach unten abprallen. Wir müssen nur noch den Mauerstein entfernen – und zwar zweimal:

  • der Mauerstein muss vom Bildschirm gelöscht werden
  • der Mauerstein muss aus unserer virtuellen Karte gelöscht werden!

Im ersten Schritt löschen wir den Bereich auf dem Bildschirm und im weiteren Schritt wird in dem Listenobjekt das entsprechende Feld mit 0 gefüllt.

    # Ball trifft Ziegelstein
    # Kontrolle auf möglich Kollision
    if ball_y_richtung == -1:
        # Ball ist in Aufwärtsbewegung
        # genau darüber ein Mauerstein?
        if karte[ball_y-1][ball_x] != 0:
            print("trifft Mauerstein rechts oberhalb")
            # Mauerstein wird gelöscht vom Bildschirm
            element_loeschen(ball_x, ball_y-1)
            # Mauerstein wird gelöscht aus der Liste karte
            karte[ball_y-1][ball_x] = 0
            ball_y_richtung = 1

Soweit so gut – allerdings kann der Ball auch schräg treffen:

Fall: Ball trifft schräg
Fall: Ball trifft schräg

Auch diesen Fall sollen wir berücksichtigen. Hier haben wir eine nicht 100 Prozent saubere Lösung. Einfach selber einmal austüfteln, wie es am besten umgesetzt wird!

    # Ball trifft Ziegelstein
    # Kontrolle auf möglich Kollision
    if ball_y_richtung == -1:
        # Ball ist in Aufwärtsbewegung
        # genau darüber ein Mauerstein?
        if karte[ball_y-1][ball_x] != 0:
            print("trifft Mauerstein rechts oberhalb")
            # Mauerstein wird gelöscht vom Bildschirm
            element_loeschen(ball_x, ball_y-1)
            # Mauerstein wird gelöscht aus der Liste karte
            karte[ball_y-1][ball_x] = 0
            ball_y_richtung = 1

        if ball_x_richtung == 1:
            # Ball bewegt sich nach rechts
            if karte[ball_y-1][ball_x+1] != 0:
                print("trifft Mauerstein rechts oberhalb")
                # Mauerstein wird gelöscht vom Bildschirm
                element_loeschen(ball_x+1, ball_y-1)
                # Mauerstein wird gelöscht aus der Liste karte
                karte[ball_y-1][ball_x+1] = 0
                ball_y_richtung = 1
        else:
            # Ball bewegt sich nach links
            if karte[ball_y-1][ball_x-1] != 0:
                print("trifft Mauerstein links oberhalb")
                # Mauerstein wird gelöscht vom Bildschirm
                element_loeschen(ball_x-1, ball_y-1)
                # Mauerstein wird gelöscht aus der Liste karte
                karte[ball_y-1][ball_x-1] = 0
                ball_y_richtung = 1

Lösung gefunden? Hier ist die Lösung mitsamt der Erweiterung, wenn der Ball auf eine Ecke von einem Mauerstein auftrifft:

    # Ball trifft Mauerstein
    # Kontrolle auf möglich Kollision
    if ball_y_richtung == -1:
        # Ball ist in Aufwärtsbewegung
        # genau darüber ein Mauerstein?
        if karte[ball_y-1][ball_x] != 0:
            print("trifft Mauerstein oberhalb")
            # Mauerstein wird gelöscht vom Bildschirm
            element_loeschen(ball_x, ball_y-1)
            # Mauerstein wird gelöscht aus der Liste karte
            karte[ball_y-1][ball_x] = 0
            ball_y_richtung = 1
        else:
            if ball_x_richtung == 1:
                # Ball bewegt sich nach rechts
                if karte[ball_y-1][ball_x+1] != 0:
                    print("trifft Mauerstein rechts oberhalb")
                    # Mauerstein wird gelöscht vom Bildschirm
                    element_loeschen(ball_x+1, ball_y-1)
                    # Mauerstein wird gelöscht aus der Liste karte
                    karte[ball_y-1][ball_x+1] = 0
                    ball_y_richtung = 1
                    # trifft auf Ecke, also gleich Richtung zurück
                    ball_x_richtung = -1
            else:
                # Ball bewegt sich nach links
                if karte[ball_y-1][ball_x-1] != 0:
                    print("trifft Mauerstein links oberhalb")
                    # Mauerstein wird gelöscht vom Bildschirm
                    element_loeschen(ball_x-1, ball_y-1)
                    # Mauerstein wird gelöscht aus der Liste karte
                    karte[ball_y-1][ball_x-1] = 0
                    ball_y_richtung = 1
                    # trifft auf Ecke, also gleich Richtung zurück
                    ball_x_richtung = +1 

Apropos – wenn das wiederholte Drücken der Leertaste lästig wird, kann Pygame eine Wiederholungsfrequenz mitgeben:

# Bildschirm Aktualisierungen einstellen
clock = pygame.time.Clock()
pygame.key.set_repeat(50,0)

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