Erstelle ein Labyrinthspiel mit Pygame

PythonPythonBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Projekt werden wir ein Labyrinthspiel mit der Pygame-Bibliothek in Python erstellen. Beim Spiel muss ein Spieler durch ein Labyrinth navigieren, um Lebensmittel zu sammeln, während er die Mauern vermeidet. Wir werden den Entwicklungsprozess in mehrere Schritte unterteilen, um ihn einfacher zu verstehen und zu folgen.

👀 Vorschau

Vorschaubild des Labyrinthspiels

🎯 Aufgaben

In diesem Projekt lernst du:

  • Wie man die Spielumgebung mit Pygame einrichtet
  • Wie man das Labyrinth mit Zellen und Mauern erstellt
  • Wie man Lebensmittel für den Spieler hinzufügt, die er sammeln kann
  • Wie man die Spielerbewegung und die Kollisionserkennung implementiert
  • Wie man die Spiellogik behandelt, einschließlich der Punktzahl und der Spielende-Bedingungen
  • Wie man den Spielerrekord verfolgt
  • Wie man Spielstatistiken wie Zeit, Punktzahl und Rekord auf dem Bildschirm anzeigt

🏆 Errungenschaften

Nach Abschluss dieses Projekts wirst du in der Lage sein:

  • Die Pygame-Bibliothek für die Spielentwicklung zu verwenden
  • Konzepte der objektorientierten Programmierung anwenden, um Spielelemente zu erstellen
  • Algorithmisches Denken und Problemlösefähigkeiten für die Labyrinthgenerierung demonstrieren
  • Ereignisverarbeitung und Spielerinput behandeln
  • Kollisionserkennung und Bewegungmechaniken in einer Spielumgebung implementieren
  • Dateiverarbeitung zur Speicherung und Abrufung von Spielrekorden verwalten
  • Spielstatistiken und Informationen auf dem Bildschirm anzeigen

Einrichten der Umgebung

Zunächst erstellen wir die Projekt-Dateien für das Labyrinthspiel.

cd ~/project
touch maze.py
sudo pip install pygame

In diesem Schritt richten wir die Pygame-Umgebung ein und definieren Konstanten.

import pygame
from random import choice, randrange

## Konstanten für die Bildschirmdimensionen und die Kachelgröße
RES = WIDTH, HEIGHT = 1202, 902
TILE = 100
cols, rows = WIDTH // TILE, HEIGHT // TILE

## Der Rest Ihres Codes wird hier stehen...

In diesem Schritt:

  • Wir importieren die erforderlichen Bibliotheken (Pygame und random).
  • Wir definieren Konstanten für die Bildschirmdimensionen und die Kachelgröße.
  • Pygame wird initialisiert, und das Spielfenster wird eingerichtet.
  • Wir laden Hintergrundbilder für das Spiel.
✨ Lösung prüfen und üben

Erstellen der Cell-Klasse

In diesem Schritt definieren wir die Cell-Klasse, um Labyrinthzellen zu repräsentieren.

## Definiere eine Klasse, um Zellen im Labyrinth zu repräsentieren
class Cell:
    def __init__(self, x, y):
        self.x, self.y = x, y
        ## Mauern repräsentieren die Grenzen der Zelle
        self.walls = {"top": True, "right": True, "bottom": True, "left": True}
        self.visited = False
        self.thickness = 4

    ## Zeichne die Mauern der Zelle
    def draw(self, sc):
        x, y = self.x * TILE, self.y * TILE
        if self.walls["top"]:
            pygame.draw.line(
                sc, pygame.Color("darkorange"), (x, y), (x + TILE, y), self.thickness
            )
        if self.walls["right"]:
            pygame.draw.line(
                sc,
                pygame.Color("darkorange"),
                (x + TILE, y),
                (x + TILE, y + TILE),
                self.thickness,
            )
        if self.walls["bottom"]:
            pygame.draw.line(
                sc,
                pygame.Color("darkorange"),
                (x + TILE, y + TILE),
                (x, y + TILE),
                self.thickness,
            )
        if self.walls["left"]:
            pygame.draw.line(
                sc, pygame.Color("darkorange"), (x, y + TILE), (x, y), self.thickness
            )

    ## Hole die Rechtecke, die jede Mauer der Zelle repräsentieren
    def get_rects(self):
        rects = []
        x, y = self.x * TILE, self.y * TILE
        if self.walls["top"]:
            rects.append(pygame.Rect((x, y), (TILE, self.thickness)))
        if self.walls["right"]:
            rects.append(pygame.Rect((x + TILE, y), (self.thickness, TILE)))
        if self.walls["bottom"]:
            rects.append(pygame.Rect((x, y + TILE), (TILE, self.thickness)))
        if self.walls["left"]:
            rects.append(pygame.Rect((x, y), (self.thickness, TILE)))
        return rects

    ## Überprüfe, ob eine Nachbarzelle existiert
    def check_cell(self, x, y):
        find_index = lambda x, y: x + y * cols
        if x < 0 or x > cols - 1 or y < 0 or y > rows - 1:
            return False
        return self.grid_cells[find_index(x, y)]

    ## Hole nicht besuchte Nachbarzellen
    def check_neighbors(self, grid_cells):
        self.grid_cells = grid_cells
        neighbors = []
        top = self.check_cell(self.x, self.y - 1)
        right = self.check_cell(self.x + 1, self.y)
        bottom = self.check_cell(self.x, self.y + 1)
        left = self.check_cell(self.x - 1, self.y)
        if top and not top.visited:
            neighbors.append(top)
        if right and not right.visited:
            neighbors.append(right)
        if bottom and not bottom.visited:
            neighbors.append(bottom)
        if left and not left.visited:
            neighbors.append(left)
        return choice(neighbors) if neighbors else False

## Der Rest Ihres Codes wird hier stehen...

In diesem Schritt:

  • Wir definieren die Cell-Klasse mit ihren Eigenschaften und Methoden zum Zeichnen von Mauern und zum Überprüfen von Nachbarn.
✨ Lösung prüfen und üben

Entfernen von Mauern und Generieren des Labyrinths

In diesem Schritt erstellen wir Funktionen, um Mauern zu entfernen und das Labyrinth zu generieren.

## Funktion, um Mauern zwischen zwei angrenzenden Zellen zu entfernen
def remove_walls(current, next):
    dx = current.x - next.x
    if dx == 1:
        current.walls["left"] = False
        next.walls["right"] = False
    elif dx == -1:
        current.walls["right"] = False
        next.walls["left"] = False
    dy = current.y - next.y
    if dy == 1:
        current.walls["top"] = False
        next.walls["bottom"] = False
    elif dy == -1:
        current.walls["bottom"] = False
        next.walls["top"] = False


## Funktion, um das Labyrinth zu generieren
def generate_maze():
    grid_cells = [Cell(col, row) for row in range(rows) for col in range(cols)]
    current_cell = grid_cells[0]
    array = []
    break_count = 1

    while break_count!= len(grid_cells):
        current_cell.visited = True
        next_cell = current_cell.check_neighbors(grid_cells)
        if next_cell:
            next_cell.visited = True
            break_count += 1
            array.append(current_cell)
            remove_walls(current_cell, next_cell)
            current_cell = next_cell
        elif array:
            current_cell = array.pop()
    return grid_cells

## Der Rest Ihres Codes wird hier stehen...

In diesem Schritt:

  • Wir definieren die remove_walls-Funktion, um Mauern zwischen angrenzenden Zellen zu entfernen.
  • Wir erstellen die generate_maze-Funktion, um das Labyrinth mit einem Tiefensuche-Algorithmus zu generieren.
✨ Lösung prüfen und üben

Hinzufügen von Essen zum Spiel

In diesem Schritt erstellen wir eine Food-Klasse, um Lebensmittel zu unserem Spiel hinzuzufügen.

## Klasse, um Lebensmittel im Spiel zu repräsentieren
class Food:
    def __init__(self):
        ## Lade das Lebensmittel-Bild
        self.img = pygame.image.load("img/food.png").convert_alpha()
        self.img = pygame.transform.scale(self.img, (TILE - 10, TILE - 10))
        self.rect = self.img.get_rect()
        self.set_pos()

    ## Setze die Position des Lebensmittels zufällig
    def set_pos(self):
        self.rect.topleft = randrange(cols) * TILE + 5, randrange(rows) * TILE + 5

    ## Zeichne das Lebensmittel auf dem Bildschirm
    def draw(self):
        game_surface.blit(self.img, self.rect)

## Der Rest Ihres Codes wird hier stehen...

In diesem Schritt:

  • Wir definieren die Food-Klasse mit Methoden zum Setzen der Position und Zeichnen von Lebensmitteln.
✨ Lösung prüfen und üben

Spielerbewegung und Kollisionserkennung

In diesem Schritt richten wir die Spielersteuerung, -bewegung und -kollisionserkennung ein.

## Überprüfe, ob der Spieler mit Mauern kollidiert
def is_collide(x, y):
    tmp_rect = player_rect.move(x, y)
    if tmp_rect.collidelist(walls_collide_list) == -1:
        return False
    return True

## Der Rest Ihres Codes wird hier stehen...

In diesem Schritt:

  • Wir definieren die is_collide-Funktion, um zu überprüfen, ob der Spieler mit Mauern kollidiert.
✨ Lösung prüfen und üben

Spielablauf und Punktestand

In diesem Schritt implementieren wir die Spielablauflogik, einschließlich Essen von Lebensmitteln und Punktestand.

## Überprüfe, ob der Spieler Lebensmittel gegessen hat
def eat_food():
    for food in food_list:
        if player_rect.collidepoint(food.rect.center):
            food.set_pos()
            return True
    return False


## Überprüfe, ob das Spiel vorbei ist (Zeit abgelaufen)
def is_game_over():
    global time, score, record, FPS
    if time < 0:
        pygame.time.wait(700)
        player_rect.center = TILE // 2, TILE // 2
        [food.set_pos() for food in food_list]
        set_record(record, score)
        record = get_record()
        time, score, FPS = 60, 0, 60

## Der Rest Ihres Codes wird hier stehen...

In diesem Schritt:

  • Wir definieren die eat_food-Funktion, um zu überprüfen, ob der Spieler Lebensmittel gegessen hat.
  • Wir erstellen die is_game_over-Funktion, um zu überprüfen, ob das Spiel vorbei ist, wenn die Zeit abgelaufen ist.
✨ Lösung prüfen und üben

Verwaltung von Rekorden

In diesem Schritt implementieren wir die Aufzeichnung von Ergebnissen für das Spiel.

## Funktion, um den aktuellen Rekord aus einer Datei zu erhalten
def get_record():
    try:
        with open("record") as f:
            return f.readline()
    except FileNotFoundError:
        with open("record", "w") as f:
            f.write("0")
            return "0"

## Funktion, um den Rekord in einer Datei festzulegen und zu aktualisieren
def set_record(record, score):
    rec = max(int(record), score)
    with open("record", "w") as f:
        f.write(str(rec))

## Der Rest Ihres Codes wird hier stehen...

In diesem Schritt:

  • Wir definieren Funktionen, um den aktuellen Rekord aus einer Datei abzurufen und zu aktualisieren.
✨ Lösung prüfen und üben

Spielinitialisierung

In diesem Schritt führen wir die Spielinitialisierungstasks aus.

## Initialisiere Pygame und stelle das Spielfenster ein
FPS = 60
pygame.init()
game_surface = pygame.Surface(RES)
surface = pygame.display.set_mode((WIDTH + 300, HEIGHT))
clock = pygame.time.Clock()

## Lade Hintergrundbilder
bg_game = pygame.image.load("img/bg_1.jpg").convert()
bg = pygame.image.load("img/bg_main.jpg").convert()

## Generiere das Labyrinth
maze = generate_maze()

## Spieler-Einstellungen
player_speed = 5
player_img = pygame.image.load("img/0.png").convert_alpha()
player_img = pygame.transform.scale(
    player_img, (TILE - 2 * maze[0].thickness, TILE - 2 * maze[0].thickness)
)
player_rect = player_img.get_rect()
player_rect.center = TILE // 2, TILE // 2
directions = {
    "a": (-player_speed, 0),
    "d": (player_speed, 0),
    "w": (0, -player_speed),
    "s": (0, player_speed),
}
keys = {"a": pygame.K_LEFT, "d": pygame.K_RIGHT, "w": pygame.K_UP, "s": pygame.K_DOWN}
direction = (0, 0)

## Lebensmittel-Einstellungen
food_list = [Food() for i in range(3)]

## Erstelle eine Liste von Rechtecken, die die Mauern für die Kollisionserkennung repräsentieren
walls_collide_list = sum([cell.get_rects() for cell in maze], [])

## Timer, Punktestand und Rekord
pygame.time.set_timer(pygame.USEREVENT, 1000)
time = 60
score = 0
record = get_record()

## Schriftarten
font = pygame.font.SysFont("Impact", 150)
text_font = pygame.font.SysFont("Impact", 80)

## Der Rest Ihres Codes wird hier stehen...

In diesem Schritt:

  • Wir führen verschiedene Initialisierungstasks aus, einschließlich des Einrichtens von Pygame, des Ladens von Bildern, der Generierung des Labyrinths und der Initialisierung von Variablen, die mit Spieler und Lebensmitteln zusammenhängen.
✨ Lösung prüfen und üben

Hauptspielschleife

In diesem Schritt richten wir die Hauptspielschleife ein und zeichnen die Spiel-Elemente.

## Hauptspielschleife
while True:
    ## Zeichne Hintergrundbilder
    surface.blit(bg, (WIDTH, 0))
    surface.blit(game_surface, (0, 0))
    game_surface.blit(bg_game, (0, 0))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        if event.type == pygame.USEREVENT:
            time -= 1

    ## Verarbeite Spielersteuerungen und Bewegung
    pressed_key = pygame.key.get_pressed()
    for key, key_value in keys.items():
        if pressed_key[key_value] and not is_collide(*directions[key]):
            direction = directions[key]
            break
    if not is_collide(*direction):
        player_rect.move_ip(direction)

    ## Zeichne das Labyrinth
    [cell.draw(game_surface) for cell in maze]

    ## Spielablauf: Überprüfe, ob der Spieler Lebensmittel gegessen hat und ob das Spiel vorbei ist
    if eat_food():
        FPS += 10
        score += 1
    is_game_over()

    ## Zeichne den Spieler
    game_surface.blit(player_img, player_rect)

    ## Zeichne Lebensmittelgegenstände
    [food.draw() for food in food_list]

    ## Der Rest Ihres Codes wird hier stehen...

In diesem Schritt:

  • Wir richten die Hauptspielschleife ein, die Ereignisse, Spielerbewegung und Spielrendern behandelt.
✨ Lösung prüfen und üben

Anzeige von Spielstatistiken

In diesem Schritt werden wir Spielstatistiken auf dem Bildschirm anzeigen.

    ## Zeichne Spielstatistiken
    surface.blit(
        text_font.render("ZEIT", True, pygame.Color("cyan"), True), (WIDTH + 70, 30)
    )
    surface.blit(font.render(f"{time}", True, pygame.Color("cyan")), (WIDTH + 70, 130))
    surface.blit(
        text_font.render("Punkte:", True, pygame.Color("forestgreen"), True),
        (WIDTH + 50, 350),
    )
    surface.blit(
        font.render(f"{score}", True, pygame.Color("forestgreen")), (WIDTH + 70, 430)
    )
    surface.blit(
        text_font.render("Rekord:", True, pygame.Color("magenta"), True),
        (WIDTH + 30, 620),
    )
    surface.blit(
        font.render(f"{record}", True, pygame.Color("magenta")), (WIDTH + 70, 700)
    )

    pygame.display.flip()
    clock.tick(FPS)

In diesem Schritt:

  • Wir verwenden Schriftarten, um spielbezogene Informationen wie Zeit, Punkte und den Rekord anzuzeigen.
  • Wir verwenden die blit()-Methode, um den Text auf dem Bildschirm zu zeichnen.
  • Wir verwenden die flip()-Methode, um die Anzeige zu aktualisieren.
✨ Lösung prüfen und üben

Starte das Spiel

Jetzt, nachdem wir alle Schritte abgeschlossen haben, können wir das Labyrinthspiel mit dem folgenden Befehl starten:

cd ~/project
python maze.py
Screenshot der Ausführung des Labyrinthspiels
✨ Lösung prüfen und üben

Zusammenfassung

In diesem Projekt haben wir den Prozess des Erstellens eines Labyrinthspiels mit Pygame in zehn klare und handhabbare Schritte unterteilt. Du wirst lernen, wie du die Spielumgebung einrichtest, Labyrinthzellen erstellst, das Labyrinth generierst, die Spielerbewegung und die Kollisionserkennung behandelst, das Spielgeschehen und die Punktzahl implementierst, die Aufzeichnungen verwaltest und vieles mehr. Indem du diesen Schritten folgst, wirst du in der Lage sein, ein voll funktionsfähiges Labyrinthspiel in Python zu erstellen.