ha1 znd ue
This commit is contained in:
commit
9487b40127
20
Hausaufgaben/ha1/.env
Normal file
20
Hausaufgaben/ha1/.env
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Anzeige
|
||||||
|
WIDTH=800
|
||||||
|
HEIGHT=600
|
||||||
|
FPS=60
|
||||||
|
BG_COLOR=#0a0a14
|
||||||
|
|
||||||
|
# Erde
|
||||||
|
EARTH_COLOR=#2878ff
|
||||||
|
EARTH_RADIUS=30
|
||||||
|
|
||||||
|
# Mond
|
||||||
|
MOON_COLOR=#f0f0f0
|
||||||
|
MOON_RADIUS=10
|
||||||
|
MOON_ORBIT_RADIUS=160
|
||||||
|
MOON_ANGULAR_SPEED_DEG=45 # Grad/Sekunde
|
||||||
|
|
||||||
|
# Apollo (optional, nur falls apollo.py genutzt wird)
|
||||||
|
APOLLO_COLOR=#dc3232
|
||||||
|
APOLLO_RADIUS=7
|
||||||
|
APOLLO_ORBIT_RADIUS=40
|
||||||
41
Hausaufgaben/ha1/1. Apollo.py
Normal file
41
Hausaufgaben/ha1/1. Apollo.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
import math
|
||||||
|
from typing import Tuple, List
|
||||||
|
import pygame # type: ignore
|
||||||
|
|
||||||
|
from moon import Moon
|
||||||
|
import compute
|
||||||
|
|
||||||
|
|
||||||
|
class Apollo(Moon):
|
||||||
|
"""Fügt die Apollo-Kapsel hinzu; liest alle Werte aus Settings (env)."""
|
||||||
|
|
||||||
|
def get_apollo_angle(self) -> float:
|
||||||
|
# doppelte Winkelgeschwindigkeit, entgegengesetzte Richtung
|
||||||
|
return -2.0 * self.get_moon_angle()
|
||||||
|
|
||||||
|
def get_apollo_position(self) -> Tuple[int, int]:
|
||||||
|
theta = self.get_apollo_angle()
|
||||||
|
r = float(self.settings.apollo_orbit_radius)
|
||||||
|
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)
|
||||||
|
mx, my = self.get_moon_position()
|
||||||
|
return int(mx + res[0][0]), int(my + res[1][0])
|
||||||
|
|
||||||
|
def draw(self, surface: pygame.Surface) -> None:
|
||||||
|
super().draw(surface)
|
||||||
|
# kleine Orbit-Linie um den Mond (optional)
|
||||||
|
pygame.draw.circle(
|
||||||
|
surface, (90, 50, 50), self.get_moon_position(), self.settings.apollo_orbit_radius, width=1
|
||||||
|
)
|
||||||
|
ax, ay = self.get_apollo_position()
|
||||||
|
pygame.draw.circle(surface, self.settings.apollo_color, (ax, ay), self.settings.apollo_radius)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
Apollo().run()
|
||||||
|
|
||||||
69
Hausaufgaben/ha1/compute.py
Normal file
69
Hausaufgaben/ha1/compute.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
def matmul(A: List[List[float]], B: List[List[float]]) -> List[List[float]]:
|
||||||
|
"""
|
||||||
|
Multiplies two matrices A and B (nested Python lists).
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
- A has shape (m x n), B has shape (n x p).
|
||||||
|
- All rows in A and B must have equal length.
|
||||||
|
- Elements are numeric (float/int).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
A: Left matrix, list of rows (m x n).
|
||||||
|
B: Right matrix, list of rows (n x p).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
New matrix C = A * B with shape (m x p).
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If matrices are empty, ragged,
|
||||||
|
or shapes are incompatible.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not A or not B:
|
||||||
|
raise ValueError("Empty matrices are not supported.")
|
||||||
|
if not A[0] or not B[0]:
|
||||||
|
raise ValueError("Matrices must have at least one column.")
|
||||||
|
|
||||||
|
a_cols = len(A[0])
|
||||||
|
|
||||||
|
for row in A:
|
||||||
|
if len(row) != a_cols:
|
||||||
|
raise ValueError("Left matrix has inconsistent row lengths.")
|
||||||
|
b_cols = len(B[0])
|
||||||
|
for row in B:
|
||||||
|
if len(row) != b_cols:
|
||||||
|
raise ValueError("Right matrix has inconsistent row lengths.")
|
||||||
|
|
||||||
|
if a_cols != len(B):
|
||||||
|
raise ValueError(
|
||||||
|
f"Incompatible shapes: A is {len(A)}x{a_cols}, "
|
||||||
|
f"B is {len(B)}x{b_cols}; need cols(A) == rows(B)."
|
||||||
|
)
|
||||||
|
|
||||||
|
m, n, p = len(A), a_cols, b_cols
|
||||||
|
C: List[List[float]] = [[0 for _ in range(p)] for _ in range(m)]
|
||||||
|
|
||||||
|
for i in range(m):
|
||||||
|
for k in range(n):
|
||||||
|
a_ik = A[i][k]
|
||||||
|
for j in range(p):
|
||||||
|
C[i][j] += a_ik * B[k][j]
|
||||||
|
|
||||||
|
return C
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
matrix_a = [[3, 4, -1, 4],
|
||||||
|
[-2, 2, 5, 1]]
|
||||||
|
matrix_b = [[1, 3, -2],
|
||||||
|
[2, 5, 1],
|
||||||
|
[-1, 4, -4],
|
||||||
|
[2, 3, 6]]
|
||||||
|
matrix_c = matmul(matrix_a, matrix_b)
|
||||||
|
print("Ergebnis C = A * B:")
|
||||||
|
for row in matrix_c:
|
||||||
|
print(row)
|
||||||
|
|
||||||
|
|
||||||
105
Hausaufgaben/ha1/config.py
Normal file
105
Hausaufgaben/ha1/config.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
"""Konfigurations-Loader für das Moon/Apollo-Projekt.
|
||||||
|
|
||||||
|
Lädt Werte aus .env in Umgebungsvariablen und stellt sie typisiert bereit.
|
||||||
|
Verwendet python-dotenv. Enthält Validierung & sinnvolle Defaults.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# .env → os.environ laden
|
||||||
|
load_dotenv(override=False)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_env(name: str, default: str) -> str:
|
||||||
|
val = os.getenv(name)
|
||||||
|
return val if val is not None and val != "" else default
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_int(name: str, default: int, min_val: int | None = None) -> int:
|
||||||
|
raw = _get_env(name, str(default))
|
||||||
|
try:
|
||||||
|
v = int(raw)
|
||||||
|
if min_val is not None and v < min_val:
|
||||||
|
raise ValueError
|
||||||
|
return v
|
||||||
|
except Exception as _:
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_float(name: str, default: float, min_val: float | None = None) -> float:
|
||||||
|
raw = _get_env(name, str(default))
|
||||||
|
try:
|
||||||
|
v = float(raw)
|
||||||
|
if min_val is not None and v < min_val:
|
||||||
|
raise ValueError
|
||||||
|
return v
|
||||||
|
except Exception as _:
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
_HEX = re.compile(r"^#?([0-9a-fA-F]{6})$")
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_rgb(name: str, default_hex: str) -> Tuple[int, int, int]:
|
||||||
|
"""Erlaubt '#rrggbb' oder 'rrggbb'. Fällt auf default zurück, wenn ungültig."""
|
||||||
|
raw = _get_env(name, default_hex)
|
||||||
|
m = _HEX.match(raw)
|
||||||
|
hx = m.group(1) if m else default_hex.lstrip("#")
|
||||||
|
r = int(hx[0:2], 16)
|
||||||
|
g = int(hx[2:4], 16)
|
||||||
|
b = int(hx[4:6], 16)
|
||||||
|
return (r, g, b)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Settings:
|
||||||
|
# Anzeige
|
||||||
|
width: int
|
||||||
|
height: int
|
||||||
|
fps: int
|
||||||
|
bg_color: Tuple[int, int, int]
|
||||||
|
|
||||||
|
# Erde
|
||||||
|
earth_color: Tuple[int, int, int]
|
||||||
|
earth_radius: int
|
||||||
|
|
||||||
|
# Mond
|
||||||
|
moon_color: Tuple[int, int, int]
|
||||||
|
moon_radius: int
|
||||||
|
moon_orbit_radius: int
|
||||||
|
moon_angular_speed_deg: float # Grad/Sekunde
|
||||||
|
|
||||||
|
# Apollo (optional)
|
||||||
|
apollo_color: Tuple[int, int, int]
|
||||||
|
apollo_radius: int
|
||||||
|
apollo_orbit_radius: int
|
||||||
|
|
||||||
|
|
||||||
|
def get_settings() -> Settings:
|
||||||
|
"""Erzeugt Settings aus Umgebungsvariablen oder Defaults."""
|
||||||
|
return Settings(
|
||||||
|
# Anzeige
|
||||||
|
width=_parse_int("WIDTH", 800, min_val=100),
|
||||||
|
height=_parse_int("HEIGHT", 600, min_val=100),
|
||||||
|
fps=_parse_int("FPS", 60, min_val=1),
|
||||||
|
bg_color=_parse_rgb("BG_COLOR", "#0a0a14"),
|
||||||
|
# Erde
|
||||||
|
earth_color=_parse_rgb("EARTH_COLOR", "#2878ff"),
|
||||||
|
earth_radius=_parse_int("EARTH_RADIUS", 30, min_val=1),
|
||||||
|
# Mond
|
||||||
|
moon_color=_parse_rgb("MOON_COLOR", "#f0f0f0"),
|
||||||
|
moon_radius=_parse_int("MOON_RADIUS", 10, min_val=1),
|
||||||
|
moon_orbit_radius=_parse_int("MOON_ORBIT_RADIUS", 160, min_val=10),
|
||||||
|
moon_angular_speed_deg=_parse_float("MOON_ANGULAR_SPEED_DEG", 45.0, min_val=0.1),
|
||||||
|
# Apollo
|
||||||
|
apollo_color=_parse_rgb("APOLLO_COLOR", "#dc3232"),
|
||||||
|
apollo_radius=_parse_int("APOLLO_RADIUS", 7, min_val=1),
|
||||||
|
apollo_orbit_radius=_parse_int("APOLLO_ORBIT_RADIUS", 40, min_val=5),
|
||||||
|
)
|
||||||
32
Hausaufgaben/ha1/game.py
Normal file
32
Hausaufgaben/ha1/game.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import pygame
|
||||||
|
|
||||||
|
class Game:
|
||||||
|
def __init__(self, width=800, height=600, fps=60, title="Game"):
|
||||||
|
pygame.init()
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.fps = fps
|
||||||
|
self.title = title
|
||||||
|
self.screen = pygame.display.set_mode((width, height))
|
||||||
|
pygame.display.set_caption(title)
|
||||||
|
self.clock = pygame.time.Clock()
|
||||||
|
self.running = True
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""Startet die Hauptschleife."""
|
||||||
|
while self.running:
|
||||||
|
dt = self.clock.tick(self.fps) / 1000 # Zeit seit letztem Frame
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == pygame.QUIT:
|
||||||
|
self.running = False
|
||||||
|
self.update(dt)
|
||||||
|
self.draw(self.screen)
|
||||||
|
pygame.display.flip()
|
||||||
|
pygame.quit()
|
||||||
|
|
||||||
|
|
||||||
|
def update(self, dt: float):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def draw(self, surface: pygame.Surface):
|
||||||
|
pass
|
||||||
65
Hausaufgaben/ha1/moon.py
Normal file
65
Hausaufgaben/ha1/moon.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
import math
|
||||||
|
from typing import Tuple, List
|
||||||
|
import pygame # type: ignore
|
||||||
|
|
||||||
|
from game import Game
|
||||||
|
import compute
|
||||||
|
from config import get_settings
|
||||||
|
|
||||||
|
|
||||||
|
class Moon(Game):
|
||||||
|
"""Unterklasse von Game: Animation Mond-um-Erde mit .env-Konfiguration."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.settings = get_settings()
|
||||||
|
super().__init__(
|
||||||
|
width=self.settings.width,
|
||||||
|
height=self.settings.height,
|
||||||
|
fps=self.settings.fps,
|
||||||
|
title="Moon Orbit (env-configured)",
|
||||||
|
)
|
||||||
|
self._theta: float = 0.0
|
||||||
|
self._center: Tuple[float, float] = (self.width / 2, self.height / 2)
|
||||||
|
|
||||||
|
# Hooks
|
||||||
|
def get_earth_center(self) -> Tuple[float, float]:
|
||||||
|
return self._center
|
||||||
|
|
||||||
|
def get_moon_angle(self) -> float:
|
||||||
|
return self._theta
|
||||||
|
|
||||||
|
def get_moon_orbit_radius(self) -> int:
|
||||||
|
return self.settings.moon_orbit_radius
|
||||||
|
|
||||||
|
def get_moon_position(self) -> Tuple[int, int]:
|
||||||
|
theta = self.get_moon_angle()
|
||||||
|
r = float(self.get_moon_orbit_radius())
|
||||||
|
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)
|
||||||
|
cx, cy = self.get_earth_center()
|
||||||
|
return int(cx + res[0][0]), int(cy + res[1][0])
|
||||||
|
|
||||||
|
def update(self, dt: float) -> None:
|
||||||
|
omega = math.radians(self.settings.moon_angular_speed_deg)
|
||||||
|
self._theta = (self._theta + omega * dt) % (2.0 * math.pi)
|
||||||
|
|
||||||
|
def draw(self, surface: pygame.Surface) -> None:
|
||||||
|
s = self.settings
|
||||||
|
surface.fill(s.bg_color)
|
||||||
|
|
||||||
|
ex, ey = self.get_earth_center()
|
||||||
|
pygame.draw.circle(surface, s.earth_color, (int(ex), int(ey)), s.earth_radius)
|
||||||
|
|
||||||
|
pygame.draw.circle(surface, (60, 60, 80), (int(ex), int(ey)), s.moon_orbit_radius, width=1)
|
||||||
|
|
||||||
|
mx, my = self.get_moon_position()
|
||||||
|
pygame.draw.circle(surface, s.moon_color, (mx, my), s.moon_radius)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
Moon().run()
|
||||||
69
Übungen/compute.py
Normal file
69
Übungen/compute.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
def matmul(A: List[List[float]], B: List[List[float]]) -> List[List[float]]:
|
||||||
|
"""
|
||||||
|
Multiplies two matrices A and B (nested Python lists).
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
- A has shape (m x n), B has shape (n x p).
|
||||||
|
- All rows in A and B must have equal length.
|
||||||
|
- Elements are numeric (float/int).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
A: Left matrix, list of rows (m x n).
|
||||||
|
B: Right matrix, list of rows (n x p).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
New matrix C = A * B with shape (m x p).
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If matrices are empty, ragged,
|
||||||
|
or shapes are incompatible.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not A or not B:
|
||||||
|
raise ValueError("Empty matrices are not supported.")
|
||||||
|
if not A[0] or not B[0]:
|
||||||
|
raise ValueError("Matrices must have at least one column.")
|
||||||
|
|
||||||
|
a_cols = len(A[0])
|
||||||
|
|
||||||
|
for row in A:
|
||||||
|
if len(row) != a_cols:
|
||||||
|
raise ValueError("Left matrix has inconsistent row lengths.")
|
||||||
|
b_cols = len(B[0])
|
||||||
|
for row in B:
|
||||||
|
if len(row) != b_cols:
|
||||||
|
raise ValueError("Right matrix has inconsistent row lengths.")
|
||||||
|
|
||||||
|
if a_cols != len(B):
|
||||||
|
raise ValueError(
|
||||||
|
f"Incompatible shapes: A is {len(A)}x{a_cols}, "
|
||||||
|
f"B is {len(B)}x{b_cols}; need cols(A) == rows(B)."
|
||||||
|
)
|
||||||
|
|
||||||
|
m, n, p = len(A), a_cols, b_cols
|
||||||
|
C: List[List[float]] = [[0 for _ in range(p)] for _ in range(m)]
|
||||||
|
|
||||||
|
for i in range(m):
|
||||||
|
for k in range(n):
|
||||||
|
a_ik = A[i][k]
|
||||||
|
for j in range(p):
|
||||||
|
C[i][j] += a_ik * B[k][j]
|
||||||
|
|
||||||
|
return C
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
matrix_a = [[3, 4, -1, 4],
|
||||||
|
[-2, 2, 5, 1]]
|
||||||
|
matrix_b = [[1, 3, -2],
|
||||||
|
[2, 5, 1],
|
||||||
|
[-1, 4, -4],
|
||||||
|
[2, 3, 6]]
|
||||||
|
matrix_c = matmul(matrix_a, matrix_b)
|
||||||
|
print("Ergebnis C = A * B:")
|
||||||
|
for row in matrix_c:
|
||||||
|
print(row)
|
||||||
|
|
||||||
|
|
||||||
32
Übungen/game.py
Normal file
32
Übungen/game.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import pygame
|
||||||
|
|
||||||
|
class Game:
|
||||||
|
def __init__(self, width=800, height=600, fps=60, title="Game"):
|
||||||
|
pygame.init()
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.fps = fps
|
||||||
|
self.title = title
|
||||||
|
self.screen = pygame.display.set_mode((width, height))
|
||||||
|
pygame.display.set_caption(title)
|
||||||
|
self.clock = pygame.time.Clock()
|
||||||
|
self.running = True
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""Startet die Hauptschleife."""
|
||||||
|
while self.running:
|
||||||
|
dt = self.clock.tick(self.fps) / 1000 # Zeit seit letztem Frame
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == pygame.QUIT:
|
||||||
|
self.running = False
|
||||||
|
self.update(dt)
|
||||||
|
self.draw(self.screen)
|
||||||
|
pygame.display.flip()
|
||||||
|
pygame.quit()
|
||||||
|
|
||||||
|
# Diese beiden Methoden überschreibst du in Unterklassen:
|
||||||
|
def update(self, dt: float):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def draw(self, surface: pygame.Surface):
|
||||||
|
pass
|
||||||
98
Übungen/moon.py
Normal file
98
Übungen/moon.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
"""
|
||||||
|
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()
|
||||||
23
Übungen/product.py
Normal file
23
Übungen/product.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
def product(numbers: List[float]) -> float:
|
||||||
|
"""Berechnet das Produkt aller Zahlen in einer Liste.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
numbers (List[float]): Liste mit Zahlen.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
float: Das Produkt aller Zahlen.
|
||||||
|
"""
|
||||||
|
if not numbers:
|
||||||
|
raise ValueError("Liste darf nicht leer sein")
|
||||||
|
|
||||||
|
result = 1.0
|
||||||
|
for n in numbers:
|
||||||
|
result *= n
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
# Beispieltests
|
||||||
|
print(product([1, 2, 3, 4])) # 24.0
|
||||||
|
print(product([2.5, 2, 2])) # 10.0
|
||||||
19
Übungen/substr.py
Normal file
19
Übungen/substr.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
def substr(string: str, start: int, length: int | None = None) -> str:
|
||||||
|
|
||||||
|
"""
|
||||||
|
Find Substring of a original String.
|
||||||
|
:param string: Original String.
|
||||||
|
:param start: Start of Substring.
|
||||||
|
:param length: Length of Substring.
|
||||||
|
:return: Substring of original String.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if length is not None and (length < 0 or length > len(string)):
|
||||||
|
raise ValueError("invalid Param")
|
||||||
|
if length is None:
|
||||||
|
return string [start:]
|
||||||
|
else:
|
||||||
|
return string[start:start+length]
|
||||||
|
|
||||||
|
print(substr("GEEKSFORGEEKS", 0,5))
|
||||||
|
print(substr("GEEKSFORGEEKS", 4, 2))
|
||||||
Loading…
x
Reference in New Issue
Block a user