diff --git a/Spiel Sitzung 04/Spiel.py b/Spiel Sitzung 04/Spiel.py new file mode 100644 index 0000000..21c197c --- /dev/null +++ b/Spiel Sitzung 04/Spiel.py @@ -0,0 +1,414 @@ + +import sys +from collections import deque + +import pygame + +# ------------------------------------------------------------ +# Maus im Käselabyrinth +# 2D-Labyrinthspiel / Sammelspiel mit pygame +# ------------------------------------------------------------ +# Installation, falls pygame noch fehlt: +# pip install pygame +# +# Starten: +# python maus_im_kaeselabyrinth.py +# ------------------------------------------------------------ + +pygame.init() + +# ----------------------------- +# Grundeinstellungen +# ----------------------------- +TILE_SIZE = 32 +HUD_HEIGHT = 80 +FPS = 60 +CAT_MOVE_DELAY = 350 # Millisekunden zwischen Katzenbewegungen + +# 0 = Weg, 1 = Wand +maze = [ + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], + [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], + [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1], + [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], + [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1], + [1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1], + [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1], + [1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], + [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], + [1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1], + [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1], + [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], +] + +ROWS = len(maze) +COLS = len(maze[0]) +WIDTH = COLS * TILE_SIZE +HEIGHT = ROWS * TILE_SIZE + HUD_HEIGHT + +screen = pygame.display.set_mode((WIDTH, HEIGHT)) +pygame.display.set_caption("Maus im Käselabyrinth") +clock = pygame.time.Clock() + +font_big = pygame.font.SysFont("arial", 38, bold=True) +font_medium = pygame.font.SysFont("arial", 24, bold=True) +font_small = pygame.font.SysFont("arial", 18) + +# ----------------------------- +# Farben +# ----------------------------- +BACKGROUND = (247, 239, 210) +PATH = (245, 215, 123) +WALL = (95, 67, 36) +WALL_DARK = (62, 43, 23) +GRID_LINE = (220, 185, 85) +MOUSE = (185, 185, 185) +MOUSE_DARK = (120, 120, 120) +CAT = (226, 124, 48) +CAT_DARK = (140, 70, 25) +CHEESE = (255, 214, 0) +CHEESE_DARK = (199, 154, 0) +BLACK = (20, 20, 20) +WHITE = (255, 255, 255) +RED = (190, 40, 40) +GREEN = (40, 150, 70) + +# ----------------------------- +# Spielvariablen +# ----------------------------- +mouse_pos = [1, 1] +cat_pos = [20, 13] +cheeses = [] +score = 0 +game_state = "running" # running, won, game_over +last_cat_move_time = 0 + + +def reset_game(): + """Setzt alle Spielvariablen zurück.""" + global mouse_pos, cat_pos, cheeses, score, game_state, last_cat_move_time + + mouse_pos = [1, 1] + cat_pos = [20, 13] + + # Liste mit genau 10 Käsestücken + cheeses = [ + [3, 1], + [8, 1], + [15, 1], + [20, 2], + [5, 5], + [13, 5], + [1, 9], + [9, 9], + [15, 11], + [18, 13], + ] + + score = 0 + game_state = "running" + last_cat_move_time = pygame.time.get_ticks() + + +def is_wall(x, y): + """Prüft, ob sich an der Position eine Wand befindet.""" + if y < 0 or y >= ROWS or x < 0 or x >= COLS: + return True + return maze[y][x] == 1 + + +def move_mouse(dx, dy): + """Bewegt die Maus, falls keine Wand im Weg ist.""" + global mouse_pos + + if game_state != "running": + return + + new_x = mouse_pos[0] + dx + new_y = mouse_pos[1] + dy + + # Bedingung: Die Maus darf nicht durch Wände laufen. + if not is_wall(new_x, new_y): + mouse_pos = [new_x, new_y] + + collect_cheese() + check_cat_collision() + check_win() + + +def collect_cheese(): + """Prüft, ob die Maus Käse eingesammelt hat.""" + global score, cheeses + + if mouse_pos in cheeses: + cheeses.remove(mouse_pos.copy()) + score += 1 + + +def check_cat_collision(): + """Prüft, ob Katze und Maus auf demselben Feld stehen.""" + global game_state + + if mouse_pos == cat_pos: + game_state = "game_over" + + +def check_win(): + """Prüft, ob alle 10 Käsestücke gesammelt wurden.""" + global game_state + + if score == 10 and game_state == "running": + game_state = "won" + + +def get_neighbors(position): + """Gibt alle begehbaren Nachbarfelder zurück.""" + x, y = position + directions = [(0, -1), (0, 1), (-1, 0), (1, 0)] + neighbors = [] + + for dx, dy in directions: + next_x = x + dx + next_y = y + dy + if not is_wall(next_x, next_y): + neighbors.append([next_x, next_y]) + + return neighbors + + +def find_shortest_path(start, goal): + """ + Sucht mit einer Breitensuche einen Weg von der Katze zur Maus. + Dadurch bewegt sich die Katze sinnvoll durch das Labyrinth. + """ + queue = deque() + queue.append((start, [])) + visited = {tuple(start)} + + while queue: + current, path = queue.popleft() + + if current == goal: + return path + + for neighbor in get_neighbors(current): + key = tuple(neighbor) + if key not in visited: + visited.add(key) + queue.append((neighbor, path + [neighbor])) + + return [] + + +def move_cat(): + """Bewegt die Katze einen Schritt in Richtung Maus.""" + global cat_pos + + if game_state != "running": + return + + path = find_shortest_path(cat_pos, mouse_pos) + + if path: + cat_pos = path[0] + + check_cat_collision() + + +def draw_hud(): + """Zeichnet Titel, Punkte und Hinweise.""" + pygame.draw.rect(screen, BACKGROUND, (0, 0, WIDTH, HUD_HEIGHT)) + + title = font_medium.render("Maus im Käselabyrinth", True, BLACK) + score_text = font_medium.render(f"Punkte: {score} / 10", True, BLACK) + + if game_state == "running": + status = "Status: Spiel läuft" + status_color = BLACK + elif game_state == "won": + status = "Status: Gewonnen!" + status_color = GREEN + else: + status = "Status: Game Over!" + status_color = RED + + status_text = font_medium.render(status, True, status_color) + help_text = font_small.render("Steuerung: Pfeiltasten oder W, A, S, D | R = Neustart | ESC = Beenden", True, BLACK) + + screen.blit(title, (20, 10)) + screen.blit(score_text, (20, 42)) + screen.blit(status_text, (250, 42)) + screen.blit(help_text, (20, 64)) + + +def draw_maze(): + """Zeichnet Labyrinth mit Wegen und Wänden.""" + for y in range(ROWS): + for x in range(COLS): + rect = pygame.Rect(x * TILE_SIZE, HUD_HEIGHT + y * TILE_SIZE, TILE_SIZE, TILE_SIZE) + + if maze[y][x] == 1: + pygame.draw.rect(screen, WALL, rect) + pygame.draw.rect(screen, WALL_DARK, rect, 2) + else: + pygame.draw.rect(screen, PATH, rect) + pygame.draw.rect(screen, GRID_LINE, rect, 1) + + +def draw_cheese(x, y): + """Zeichnet ein Käsestück.""" + center_x = x * TILE_SIZE + TILE_SIZE // 2 + center_y = HUD_HEIGHT + y * TILE_SIZE + TILE_SIZE // 2 + + points = [ + (center_x - 11, center_y + 10), + (center_x + 12, center_y), + (center_x - 11, center_y - 10), + ] + pygame.draw.polygon(screen, CHEESE, points) + pygame.draw.polygon(screen, CHEESE_DARK, points, 2) + + pygame.draw.circle(screen, CHEESE_DARK, (center_x - 3, center_y), 2) + pygame.draw.circle(screen, CHEESE_DARK, (center_x + 4, center_y - 3), 2) + pygame.draw.circle(screen, CHEESE_DARK, (center_x + 4, center_y + 4), 2) + + +def draw_mouse(): + """Zeichnet die Maus.""" + x, y = mouse_pos + center_x = x * TILE_SIZE + TILE_SIZE // 2 + center_y = HUD_HEIGHT + y * TILE_SIZE + TILE_SIZE // 2 + + # Ohren + pygame.draw.circle(screen, MOUSE_DARK, (center_x - 8, center_y - 9), 5) + pygame.draw.circle(screen, MOUSE_DARK, (center_x + 8, center_y - 9), 5) + + # Körper + pygame.draw.circle(screen, MOUSE, (center_x, center_y), 11) + pygame.draw.circle(screen, BLACK, (center_x, center_y + 2), 2) + + # Schwanz + pygame.draw.line(screen, MOUSE_DARK, (center_x - 10, center_y + 4), (center_x - 17, center_y + 10), 2) + + +def draw_cat(): + """Zeichnet die Katze.""" + x, y = cat_pos + center_x = x * TILE_SIZE + TILE_SIZE // 2 + center_y = HUD_HEIGHT + y * TILE_SIZE + TILE_SIZE // 2 + + # Kopf + pygame.draw.circle(screen, CAT, (center_x, center_y), 12) + + # Ohren + left_ear = [(center_x - 10, center_y - 7), (center_x - 4, center_y - 18), (center_x, center_y - 7)] + right_ear = [(center_x + 10, center_y - 7), (center_x + 4, center_y - 18), (center_x, center_y - 7)] + pygame.draw.polygon(screen, CAT, left_ear) + pygame.draw.polygon(screen, CAT, right_ear) + pygame.draw.polygon(screen, CAT_DARK, left_ear, 2) + pygame.draw.polygon(screen, CAT_DARK, right_ear, 2) + + # Augen + pygame.draw.circle(screen, BLACK, (center_x - 4, center_y - 2), 2) + pygame.draw.circle(screen, BLACK, (center_x + 4, center_y - 2), 2) + + # Nase + pygame.draw.circle(screen, CAT_DARK, (center_x, center_y + 4), 2) + + +def draw_end_message(): + """Zeichnet Gewinn- oder Game-Over-Meldung.""" + if game_state == "running": + return + + box_width = 500 + box_height = 160 + box_x = WIDTH // 2 - box_width // 2 + box_y = HEIGHT // 2 - box_height // 2 + + pygame.draw.rect(screen, (0, 0, 0), (box_x, box_y, box_width, box_height), border_radius=16) + pygame.draw.rect(screen, WHITE, (box_x + 5, box_y + 5, box_width - 10, box_height - 10), border_radius=14) + + if game_state == "won": + title = "GEWONNEN!" + subtitle = "Du hast alle 10 Käsestücke gesammelt." + color = GREEN + else: + title = "GAME OVER!" + subtitle = "Die Katze hat die Maus gefangen." + color = RED + + title_text = font_big.render(title, True, color) + subtitle_text = font_medium.render(subtitle, True, BLACK) + restart_text = font_small.render("Drücke R, um neu zu starten.", True, BLACK) + + screen.blit(title_text, title_text.get_rect(center=(WIDTH // 2, box_y + 48))) + screen.blit(subtitle_text, subtitle_text.get_rect(center=(WIDTH // 2, box_y + 92))) + screen.blit(restart_text, restart_text.get_rect(center=(WIDTH // 2, box_y + 128))) + + +def draw_game(): + """Zeichnet das gesamte Spiel neu.""" + screen.fill(BACKGROUND) + draw_hud() + draw_maze() + + for cheese in cheeses: + draw_cheese(cheese[0], cheese[1]) + + draw_mouse() + draw_cat() + draw_end_message() + + pygame.display.flip() + + +def handle_keydown(key): + """Reagiert auf Tastatureingaben.""" + if key in (pygame.K_ESCAPE,): + pygame.quit() + sys.exit() + + if key == pygame.K_r: + reset_game() + return + + if key in (pygame.K_UP, pygame.K_w): + move_mouse(0, -1) + elif key in (pygame.K_DOWN, pygame.K_s): + move_mouse(0, 1) + elif key in (pygame.K_LEFT, pygame.K_a): + move_mouse(-1, 0) + elif key in (pygame.K_RIGHT, pygame.K_d): + move_mouse(1, 0) + + +def main(): + """Game Loop: Eingaben lesen, Spiel aktualisieren, neu zeichnen.""" + global last_cat_move_time + + reset_game() + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + + if event.type == pygame.KEYDOWN: + handle_keydown(event.key) + + current_time = pygame.time.get_ticks() + if current_time - last_cat_move_time >= CAT_MOVE_DELAY: + move_cat() + last_cat_move_time = current_time + + draw_game() + clock.tick(FPS) + + +if __name__ == "__main__": + main()