""" Mond-Animation mit pygame. Die Klasse Moon erbt von Game und zeigt: - blaue Erde im Zentrum - weißer Mond, der die Erde umkreist Mathematische Operationen (Rotationsmatrix * Vektor) werden über compute.matmul() erledigt (Separation of Concerns). """ from __future__ import annotations import math from typing import Tuple, List import pygame # type: ignore from game import Game import compute class Moon(Game): """Unterklasse von Game: Animation Mond-um-Erde.""" # --- Konfiguration (leicht anpassbar / erweiterbar) --- WIDTH: int = 800 HEIGHT: int = 600 FPS: int = 60 EARTH_COLOR: Tuple[int, int, int] = (40, 120, 255) # Blau MOON_COLOR: Tuple[int, int, int] = (240, 240, 240) # Weiß BG_COLOR: Tuple[int, int, int] = (10, 10, 20) # Dunkel ORBIT_COLOR: Tuple[int, int, int] = (60, 60, 80) # dezente Orbit-Linie EARTH_RADIUS: int = 30 MOON_RADIUS: int = 10 MOON_ORBIT_RADIUS: int = 160 # Winkelgeschwindigkeit des Mondes (rad/s) MOON_ANGULAR_SPEED: float = math.radians(45.0) def __init__(self) -> None: """Initialisiert Fenster, Farben und Startwerte.""" super().__init__(width=self.WIDTH, height=self.HEIGHT, fps=self.FPS, title="Moon Orbit") self._theta: float = 0.0 self._center: Tuple[float, float] = (self.width / 2, self.height / 2) # --- Hooks: erleichtern Erweiterungen (OCP) --- def get_earth_center(self) -> Tuple[float, float]: """Zentrum der Erde (kann von Subklassen überschrieben werden).""" return self._center def get_moon_angle(self) -> float: """Aktueller Mond-Winkel in Radiant (kann überschrieben werden).""" return self._theta def get_moon_orbit_radius(self) -> int: """Orbit-Radius des Mondes um die Erde (Pixel).""" return self.MOON_ORBIT_RADIUS def get_moon_position(self) -> Tuple[int, int]: """Berechnet die aktuelle Mondposition (Bildschirmkoordinaten).""" theta = self.get_moon_angle() r = float(self.get_moon_orbit_radius()) # Rotierter Vektor (r, 0) mit Winkel theta per compute.matmul (2x2 @ 2x1) rot: List[List[float]] = [ [math.cos(theta), -math.sin(theta)], [math.sin(theta), math.cos(theta)], ] vec: List[List[float]] = [[r], [0.0]] res = compute.matmul(rot, vec) # 2x1 cx, cy = self.get_earth_center() return int(cx + res[0][0]), int(cy + res[1][0]) # --- Game-Hooks --- def update(self, dt: float) -> None: """Aktualisiert den Winkel für die Mondrotation.""" self._theta = (self._theta + self.MOON_ANGULAR_SPEED * dt) % (2.0 * math.pi) def draw(self, surface: pygame.Surface) -> None: """Zeichnet Erde, Orbit und Mond.""" surface.fill(self.BG_COLOR) # Erde ex, ey = self.get_earth_center() pygame.draw.circle(surface, self.EARTH_COLOR, (int(ex), int(ey)), self.EARTH_RADIUS) # Orbit (visuelle Hilfe) pygame.draw.circle( surface, self.ORBIT_COLOR, (int(ex), int(ey)), self.get_moon_orbit_radius(), width=1 ) # Mond mx, my = self.get_moon_position() pygame.draw.circle(surface, self.MOON_COLOR, (mx, my), self.MOON_RADIUS) if __name__ == "__main__": Moon().run()