99 lines
3.3 KiB
Python
99 lines
3.3 KiB
Python
"""
|
|
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()
|