Pong in Python mit PyGame

Dieser Beitrag erklärt Schritt für Schritt die Vorangehensweise um ein Pong Spiel mit Python zu entwickeln.

Benötigt wird die Bibliothek pygame, welche mit pip installiert werden kann.

Als erstes muss das entsprechende Modul importiert werden. Zusätzlich wird math zur Berechnung und random benötigt

import pygame
import math
import random

Nun wird pygame initialisiert und eine clock erstellt, welches die Bildwiederholfrequenz des Spiels steuert und die Bewegung des Puks.

pygame.init()
clock = pygame.time.Clock()

Als nächstes ist es Zeit ein Spielfenster zu erstellen. Alternativ kann der Titel des Fensters definiert werden. In diesem Falle hat das Fenster eine Größe von 1280×720 und den Titel PyPong 2.0

#Resolution
RESOLUTION    = (1280, 720)
WIDTH, HEIGHT = RESOLUTION

#Screen
screen = pygame.display.set_mode(RESOLUTION)
pygame.display.set_caption("PyPong 2.0")

Eine GameLoop ist essentiell. Sie kann folgendermaßen erstellt werden.

#Main Loop
cancel = False

while not cancel:
    # DO STUFF

In der GameLoop werden nun die FPS definiert und alle Objekte im Spiel aktualisiert. Dies sollte dazu führen, dass das Fenster nicht unmittelbar nach dem Starten des Programms abbricht und das man Objekte visuell darstellen kann.

#Clear screen
screen.fill(WHITE)

#Drawing code
    
#Update screen content
pygame.display.flip()

#Frames per second
clock.tick(60)

WHITE stellt in diesem Falle die Farbe Weiß da. Folgende Farben werden im Laufe noch benötigt (RGB Format)

#Color
RED   = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE  = (0, 0, 255)

Nun müssen nach und nach relevante Events initialisiert werden. Zum Beispiel, ob der Benutzer das Spiel beenden möchte

for event in pygame.event.get():
        if event.type == pygame.QUIT:
            cancel = True
            pygame.quit()

Weitere Events werden noch folgen.

Es ist Zeit, die Paddles zu erstellen. Jedes Paddle besitzt eine X und Y Position, wobei die X Position optional durch eine allgemeine Konstante ersetzt werden kann, da diese absolut ist und nicht vom Benutzer verändert werden kann. height kann ebenfalls durch eine Konstante ersetzt werden. Zudem besitzt jedes Paddle für X und Y eine Variable, welche definiert, ob sich das Paddle bewegen kann (Ansonsten könne das Paddle aus dem Fenster raus bewegt werden) Der MovementFactor legt fest, wie schnell sich das Paddle bewegt.

#Rect
left_rect_posX  = 50
left_rect_posY  = 50

right_rect_posX = 1220
right_rect_posY = 50

left_rect_HEIGHT   = 150
right_rect_HEIGHT  = 150

#Rect movement factor
rmf = 10
left_rect_can_move_upwards    = True
left_rect_can_move_downwards  = True
right_rect_can_move_upwards   = True
right_rect_can_move_downwards = True

Um das Paddle steuern zu können, wird eine InputMap benötigt. Diese speichert die momentan gedrückten Tasten. (W, S, UP, DOWN)

#Input map
inputMap = [False, False, False, False]

Mit Events werden die entsprechenden Inputs des Benutzers erfasst und in der InputMap gespeichert

       if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_DOWN:
                inputMap[0] = True
            if event.key == pygame.K_UP:
                inputMap[1] = True
            if event.key == pygame.K_s:
                inputMap[2] = True
            if event.key == pygame.K_w:
                inputMap[3] = True

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_DOWN:
                inputMap[0] = False
            if event.key == pygame.K_UP:
                inputMap[1] = False
            if event.key == pygame.K_s:
                inputMap[2] = False
            if event.key == pygame.K_w:
                inputMap[3] = False

Nun müssen die Paddles nur noch basierend auf den UserInput bewegt werden. Es muss zusätzlich noch überprüft werden, dass die Paddles sich nicht außerhalb des Spielfelds bewegen werden können

    #Game logic
    if right_rect_posY < 0 - right_rect_HEIGHT / 2:
        right_rect_can_move_upwards   = False
    else:
        right_rect_can_move_upwards   = True
    if right_rect_posY > HEIGHT - right_rect_HEIGHT / 2:
        right_rect_can_move_downwards = False
    else:
        right_rect_can_move_downwards = True
    if left_rect_posY < 0 - left_rect_HEIGHT / 2:
        left_rect_can_move_upwards    = False
    else:
        left_rect_can_move_upwards    = True
    if left_rect_posY > HEIGHT - left_rect_HEIGHT / 2:
        left_rect_can_move_downwards  = False
    else:
        left_rect_can_move_downwards  = True


    if right_rect_can_move_downwards:
        if inputMap[0]: right_rect_posY += rmf
    if right_rect_can_move_upwards:
        if inputMap[1]: right_rect_posY -= rmf
    if left_rect_can_move_downwards:
        if inputMap[2]: left_rect_posY  += rmf
    if left_rect_can_move_upwards:
        if inputMap[3]: left_rect_posY  -= rmf

Nun ist es Zeit den Puck zu erstellen. Der Puck besitzt eine X und Y Position und einen MovementFactor

#Circle
circle_start_posX = int(WIDTH / 2)
circle_start_posY = int(HEIGHT / 2)

circle_posY = circle_start_posY
circle_posX = circle_start_posX

#Circle movement factor
cmfX = 450
cmfY = 450

Um den Puck zum bewegen zu bringen, muss eine Richtung bestimmt werden und die X, sowohl als auch die Y-Position durch eine lineare Funktion aktualisiert werden.

    #Circle movement
    circle_time_passed = clock.tick(60)
    circle_time_sec = circle_time_passed / 1000.0
    circle_posX += cmfX * circle_time_sec
    circle_posY += cmfY * circle_time_sec

Jetzt muss noch die Kollision des Pucks berechnet werden

    #Circle collision
    if circle_posY > HEIGHT or circle_posY < 0:
        cmfY = -cmfY
    if circle_posX > right_rect_posX or circle_posX < left_rect_posX:
        if circle_posY > right_rect_posY and circle_posY < right_rect_posY + right_rect_HEIGHT:
            cmfX = -cmfX
        if circle_posY > left_rect_posY and circle_posY < left_rect_posY + left_rect_HEIGHT:
            cmfX = -cmfX

Damit wäre das Pong Spiel fast fertig. Es muss nur noch überprüft werden, ob ein Spieler einen Punkt erziehlt hat

    # Endgame
    if circle_posX > WIDTH:
	score_left += 1
        circle_posX = circle_start_posX
        circle_posY = circle_start_posY

    if circle_posX < 0:
	score_right += 1
        circle_posX = circle_start_posX
        circle_posY = circle_start_posY

Der Score wird zuguterletzt noch auf dem Display angezeigt

#Font
score_font = pygame.font.SysFont("Clear Sans Regular", 30)

#Score
score_left  = 0
score_right = 0

Source code: https://github.com/IntenceYT/PyPong/

Scroll to Top