Kollision mit dem Paddle
Um das Paddle mit dem Ball kollidieren zu lassen, brauchen wir nur ein paar wenige Zeilen.
Zuerst fügen wir dem Ball eine neue Methode hits_paddle()
hinzu. Dort verwenden wir auf Zeile 55
anschliessend eine sehr praktische Funktion, welche uns Pygame für Sprite-Objekte zur Verfügung stellt: pygame.sprite.spritecollide()
. Sie prüft, ob ein Sprite S mit einer Gruppe von Sprites G kollidiert. Wenn S mindestens eines der Sprites in G berührt, dann ist das Resultat True
, ansonsten False
.
Als erstes Argument übergeben wir dort also das Sprite, welches wir auf eine Kollision prüfen wollen. In unserem Fall ist das self
, also das Objekt der Ball
-Klasse, welche ja von der pygame.sprite.Sprite
-Klasse erbt und somit selbst auch ein Sprite ist.
Als zweites Argument übergeben wir die Sprite-Gruppe, gegen welche wir das erste Sprite prüfen wollen. Hierzu verwenden wir die paddles
-Gruppe — also die Gruppe "aller Paddles". Ja, es gibt natürlich nur ein Paddle. Diese Gruppe hat demnach auch nur ein einziges Element. Das macht aber nichts: Pygame verlangt einzig, dass das zweite Argument eine Sprite-Gruppe sein muss. Wir sehen später bei den Blocks noch einen Fall, wo eine solche Gruppe mehrere Sprites enthält.
Als drittes Argument übergeben wir noch False
. Würden wir hier True
übergeben, dann würde Pygame alle Sprites in der Sprite-Gruppe killen (also entfernen), die zum Zeitpunkt dieses Aufrufs von einer Kollision mit dem Ball betroffen sind. Bei den Blocks wird dieses Verhalten später noch nützlich sein. Das Paddle soll aber natürlich nicht verschwinden, wenn es den Ball trift. Also übergeben wir False
.
Zum Schluss müssen wir diese hits_paddle()
-Abfrage natürlich noch verwenden. Wir tun das auf Zeile 100
. Wenn hier True
zurückgegeben wird, dann drehen wir einfach die y-Richtung des Balls, mit der Methode flip_y_direction()
, die wir bereits in einem vorherigen Schritt erstellt haben.
import pygame
# Spiel initialisieren
pygame.init()
# Einstellungen für das Fenster
window_width = 800
window_height = 600
# Hintergrundfarbe festlegen
background_color = pygame.color.Color("black")
# Einstellungen für das Paddle
paddle_y = 540
paddle_speed = 3
# Pygame-Fenster vorbereiten
pygame.display.set_caption("Breakout 👾")
screen = pygame.display.set_mode([window_width, window_height])
# Zugriff auf die Uhr -> damit können wir die Geschwindigkeit des Spiels anpassen
clock = pygame.time.Clock()
class Ball(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
ball_image = pygame.image.load("sprites/58-Breakout-Tiles.png")
self.image = pygame.transform.scale(ball_image, (50, 50))
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.direction = (-1, -2)
def move(self):
new_x = self.rect.center[0] + self.direction[0]
new_y = self.rect.center[1] + self.direction[1]
self.rect.center = (new_x, new_y)
def flip_x_direction(self):
new_x_direction = self.direction[0] * -1
new_y_direction = self.direction[1]
self.direction = (new_x_direction, new_y_direction)
def flip_y_direction(self):
new_x_direction = self.direction[0]
new_y_direction = self.direction[1] * -1
self.direction = (new_x_direction, new_y_direction)
def hits_top_of_window(self):
return self.rect.top <= 0
def hits_side_of_window(self):
return self.rect.left <= 0 or self.rect.right >= window_width
def hits_paddle(self):
return pygame.sprite.spritecollide(self, paddles, False)
class Paddle(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
paddle_image = pygame.image.load("sprites/49-Breakout-Tiles.png")
self.image = pygame.transform.scale(paddle_image, (150, 40))
self.rect = self.image.get_rect()
self.rect.center = (x, y)
def left(self):
new_x = self.rect.center[0] - paddle_speed
new_y = self.rect.center[1]
self.rect.center = (new_x, new_y)
def right(self):
new_x = self.rect.center[0] + paddle_speed
new_y = self.rect.center[1]
self.rect.center = (new_x, new_y)
ball = Ball(500, 300)
balls = pygame.sprite.Group()
balls.add(ball)
paddle = Paddle(window_width / 2, paddle_y)
paddles = pygame.sprite.Group(paddle)
run = True
while run:
clock.tick(100)
screen.fill(background_color)
ball.move()
balls.update()
balls.draw(screen)
paddles.update()
paddles.draw(screen)
if ball.hits_top_of_window():
ball.flip_y_direction()
if ball.hits_side_of_window():
ball.flip_x_direction()
if ball.hits_paddle():
ball.flip_y_direction()
pygame.display.flip()
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_LEFT]:
paddle.left()
if keys_pressed[pygame.K_RIGHT]:
paddle.right()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
Das war's! Nun können wir den Ball im Spiel halten. Im nächsten Schritt sorgen wir dafür, dass wir damit auch etwas treffen können.