Moon Aufgabe
This commit is contained in:
1 parent
a9c95dfc03
commit
0c59c96407
3 files changed
+210
No files matched your search
+23
@@ -59,6 +59,29 @@ def matmul(matrix_a: Matrix, matrix_b: Matrix) -> Matrix:
|
||||
import math
|
||||
|
||||
|
||||
def matvec(a: Matrix, v: list[float]) -> list[float]:
|
||||
"""Return the product of a matrix and a column vector.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a: list[list[float]]
|
||||
Matrix of shape ``(m, n)``.
|
||||
v: list[float]
|
||||
Column vector of shape ``(n,)``.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list[float]
|
||||
Resulting vector of shape ``(m,)``.
|
||||
"""
|
||||
if not isinstance(a, list) or not isinstance(v, list):
|
||||
raise TypeError("Matrix and vector must be lists of numbers.")
|
||||
if not a or not a[0] or not v:
|
||||
raise ValueError("Matrix and vector must be non-empty.")
|
||||
if any(len(row) != len(v) for row in a):
|
||||
raise ValueError(f"Inner dimensions mismatch: vector has {len(v)} entries.")
|
||||
return [sum(x * y for x, y in zip(row, v)) for row in a]
|
||||
|
||||
def rot_2D(theta: float) -> Matrix:
|
||||
"""Return a 2×2 rotation matrix for the given angle ``theta``.
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
"""Basisklasse ``Game`` für einfache pygame-Anwendungen."""
|
||||
|
||||
import pygame
|
||||
|
||||
|
||||
class Game:
|
||||
"""Basisklasse für pygame-Spiele.
|
||||
|
||||
Unterklassen passen das Verhalten durch Überschreiben von
|
||||
:meth:`handle_event`, :meth:`update_game` und :meth:`draw_game` an.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
title: str,
|
||||
fps: int = 60,
|
||||
size: tuple[int, int] = (640, 400),
|
||||
) -> None:
|
||||
"""Legt Fenstertitel, Bildrate und Fenstergröße fest.
|
||||
|
||||
Args:
|
||||
title: Titel des Fensters.
|
||||
fps: Maximale Bilder pro Sekunde.
|
||||
size: Fenstergröße als (Breite, Höhe) in Pixeln.
|
||||
"""
|
||||
self.title: str = title
|
||||
self.fps: int = fps
|
||||
self.size: tuple[int, int] = size
|
||||
self.clock: pygame.time.Clock = pygame.time.Clock()
|
||||
self.dt: float = 0
|
||||
self.screen: pygame.Surface | None = None
|
||||
|
||||
def init_game(self) -> None:
|
||||
"""Initialisiert pygame und erzeugt das Fenster."""
|
||||
pygame.init()
|
||||
pygame.display.set_caption(self.title)
|
||||
self.screen = pygame.display.set_mode(self.size)
|
||||
|
||||
def game_loop(self) -> None:
|
||||
"""Führt die Hauptschleife aus, bis Events oder Update ``False`` liefern."""
|
||||
while True:
|
||||
# Berechnung der Zeitdifferenz seit dem letzten Frame
|
||||
self.dt = self.clock.tick(self.fps) / 1000
|
||||
if self.event_handling() == False:
|
||||
break
|
||||
if self.update_game() == False:
|
||||
break
|
||||
self.draw_game()
|
||||
|
||||
def exit_game(self) -> None:
|
||||
"""Beendet pygame."""
|
||||
pygame.quit()
|
||||
|
||||
def clear(self, color: tuple[int, int, int] = (0, 0, 0)) -> None:
|
||||
"""Füllt den Bildschirm mit einer Hintergrundfarbe.
|
||||
|
||||
Args:
|
||||
color: Hintergrundfarbe als (R, G, B).
|
||||
"""
|
||||
self.screen.fill(color)
|
||||
|
||||
def display(self) -> None:
|
||||
"""Bringt den gezeichneten Frame zur Anzeige."""
|
||||
pygame.display.flip()
|
||||
|
||||
def event_handling(self) -> bool:
|
||||
"""Verteilt alle anstehenden Events an :meth:`handle_event`.
|
||||
|
||||
Bleibt in der Unterklasse unverändert.
|
||||
|
||||
Returns:
|
||||
``False``, sobald ein Event das Spiel beenden soll, sonst ``True``.
|
||||
"""
|
||||
for event in pygame.event.get():
|
||||
if not self.handle_event(event):
|
||||
return False
|
||||
return True
|
||||
|
||||
def handle_event(self, event: pygame.event.Event) -> bool:
|
||||
"""Verarbeitet ein einzelnes Event.
|
||||
|
||||
Wird in der Unterklasse überschrieben.
|
||||
|
||||
Args:
|
||||
event: Das zu verarbeitende pygame-Event.
|
||||
|
||||
Returns:
|
||||
``False`` bei ``pygame.QUIT``, sonst ``True``.
|
||||
"""
|
||||
if event.type == pygame.QUIT:
|
||||
return False
|
||||
return True
|
||||
|
||||
def update_game(self) -> bool:
|
||||
"""Aktualisiert den Spielzustand um einen Frame.
|
||||
|
||||
Returns:
|
||||
``False``, wenn das Spiel beendet werden soll, sonst ``True``.
|
||||
"""
|
||||
return True
|
||||
|
||||
def draw_game(self) -> None:
|
||||
"""Zeichnet den aktuellen Frame und bringt ihn zur Anzeige."""
|
||||
pygame.display.flip()
|
||||
|
||||
def run(self) -> None:
|
||||
"""Startet das Spiel: Initialisierung, Hauptschleife, Beenden."""
|
||||
self.init_game()
|
||||
self.game_loop()
|
||||
self.exit_game()
|
||||
@@ -0,0 +1,77 @@
|
||||
"""Der Mond kreist um die Erde."""
|
||||
|
||||
import pygame
|
||||
|
||||
from compute import matvec, rot_2D
|
||||
from game import Game
|
||||
|
||||
EARTH_RADIUS = 30
|
||||
MOON_RADIUS = 10
|
||||
BLACK = (0, 0, 0)
|
||||
WHITE = (255, 255, 255)
|
||||
BLUE = (0, 0, 255)
|
||||
|
||||
MOON_DIST = 120 # Abstand Erde -> Mond
|
||||
ANGLE = 0.02 # Drehwinkel pro Bild
|
||||
|
||||
|
||||
class Moon(Game):
|
||||
"""Der Mond kreist um die Erde."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
title: str = "Moon",
|
||||
fps: int = 60,
|
||||
size: tuple[int, int] = (640, 400),
|
||||
) -> None:
|
||||
"""Legt Startposition, Drehwinkel und Rotationsmatrix fest."""
|
||||
super().__init__(title, fps, size)
|
||||
self.center = (size[0] / 2, size[1] / 2) # Erdposition
|
||||
self.angle = self.drehwinkel() # Drehwinkel pro Bild
|
||||
self.pos = self.startposition() # Vektor relativ zur Erde
|
||||
|
||||
def drehwinkel(self) -> float:
|
||||
"""Winkel, um den pro Bild weitergedreht wird (Hook für Apollo)."""
|
||||
return ANGLE
|
||||
|
||||
def startposition(self) -> list[float]:
|
||||
"""Startposition als Vektor relativ zum Mittelpunkt."""
|
||||
return [MOON_DIST, 0.0]
|
||||
|
||||
def update_game(self) -> bool:
|
||||
"""Dreht den Mond ein Stück weiter."""
|
||||
self.pos = self.drehe(self.pos)
|
||||
return True
|
||||
|
||||
def drehe(self, vektor: list[float]) -> list[float]:
|
||||
"""Dreht einen Vektor mit der Rotationsmatrix weiter."""
|
||||
return matvec(rot_2D(self.angle), vektor)
|
||||
|
||||
def absolut(self, vektor: list[float]) -> tuple[float, float]:
|
||||
"""Rechnet einen relativen Vektor in Bildschirmkoordinaten um."""
|
||||
return (self.center[0] + vektor[0], self.center[1] + vektor[1])
|
||||
|
||||
def draw_game(self) -> None:
|
||||
"""Zeichnet Erde und Mond."""
|
||||
self.draw_space()
|
||||
self.display()
|
||||
|
||||
def draw_space(self):
|
||||
self.clear()
|
||||
self.draw_earth()
|
||||
self.draw_body(self.absolut(self.pos), MOON_RADIUS, WHITE)
|
||||
|
||||
def draw_earth(self) -> None:
|
||||
"""Zeichnet die Erde ins Zentrum."""
|
||||
pygame.draw.circle(self.screen, BLUE, self.center, EARTH_RADIUS)
|
||||
|
||||
def draw_body(
|
||||
self, pos: tuple[float, float],
|
||||
radius: int, farbe: tuple[int, int, int],
|
||||
) -> None:
|
||||
"""Zeichnet einen Himmelskörper an einer Position."""
|
||||
pygame.draw.circle(self.screen, farbe, pos, radius)
|
||||
|
||||
if __name__ == "__main__":
|
||||
moon = Moon()
|
||||
moon.run()
|
||||
Reference in new issue
Block a user