Files
2026-09-24 15:45:31 +02:00

194 lines
6.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Physik-Sandbox
Interaktive 2D-Physiksimulation in Python. Über eine Werkzeugleiste erzeugst du Kreise und
Rechtecke unterschiedlicher Größe, greifst sie mit der Maus, ziehst sie herum und wirfst
sie gegeneinander. Die Körper fallen, prallen ab, reiben, rollen, stapeln sich und kommen
stabil zur Ruhe.
Die **gesamte Physik ist selbst geschrieben** – Vektormathematik, Integration,
Kollisionserkennung und impulsbasierte Kollisionsauflösung verwenden ausschließlich das
Standardmodul `math`. [pygame-ce](https://pyga.me/) dient nur für Fenster, Zeichnen,
Eingaben und Zeitmessung.
![Demo-Szene: Ein Rechteck wird gerade geworfen, daneben Kreispyramide und Rechteckturm](docs/images/screenshot.png)
## Funktionen
- Kreise und achsenparallele Rechtecke; Größe, Seitenverhältnis, Elastizität, Dichte und
Farbe in der Sidebar einstellbar – die Masse ergibt sich aus Fläche × Dichte.
- Objekte per Klick in die Welt oder per Ziehen aus der Vorschau-Kachel erzeugen.
- Drag & Drop mit Kollisionen: Ein gezogenes Objekt schiebt andere weg und wird von Wänden
gestoppt. Beim Loslassen erhält es die geglättete Mausgeschwindigkeit (Werfen).
- Schwerkraft, Kreis–Kreis-, Kreis–Rechteck-, Rechteck–Rechteck- und Wandkollisionen,
Restitution, Coulomb-Reibung, Rollen und Rollwiderstand.
- Fester Zeitschritt (120 Hz), semi-impliziter Euler, Warm-Starting, Positionskorrektur,
Schlafmodus für ruhende Körper, Geschwindigkeitsgrenze gegen Tunneln.
- Pause, Schwerkraft an/aus, Alles löschen, Debug-Ansicht mit Kontaktpunkten.
## Voraussetzungen
- Python **3.10 oder neuer** (entwickelt und getestet mit Python 3.14)
- Windows, macOS oder Linux
> **Warum pygame-ce?** Das Original-`pygame` (2.6.1) bietet keine fertigen Pakete für
> Python 3.14. `pygame-ce` ist der API-kompatible Community-Fork; im Code heißt es weiterhin
> `import pygame`.
## Einrichtung
Im Projektordner eine virtuelle Umgebung anlegen und die Abhängigkeiten installieren:
```bash
python -m venv .venv
```
Aktivieren – unter Windows (PowerShell):
```powershell
.venv\Scripts\Activate.ps1
```
Meldet PowerShell "Die Ausführung von Skripts ist auf diesem System deaktiviert", erlaube
lokale Skripte einmalig für deinen Benutzer (danach die Aktivierung wiederholen):
```powershell
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
```
Alternativ ohne Aktivierung: Ersetze in allen folgenden Befehlen
| Befehl | durch |
|---|---|
| `python` | `.venv\Scripts\python.exe` |
| `pip` | `.venv\Scripts\python.exe -m pip` |
| `pytest` | `.venv\Scripts\python.exe -m pytest` |
| `ruff` | `.venv\Scripts\ruff.exe` |
| `physics-sandbox` | `.venv\Scripts\physics-sandbox.exe` |
Unter macOS/Linux:
```bash
source .venv/bin/activate
```
Dann installieren:
```bash
pip install -r requirements.txt
```
`requirements.txt` installiert `pygame-ce` und das Projekt selbst im Editable-Modus
(`-e .`). Den Befehl deshalb im Projektordner ausführen.
## Starten
```bash
python -m sandbox
```
Weitere Möglichkeiten:
| Befehl | Wirkung |
|---|---|
| `python -m sandbox --demo` | startet mit einer Beispielszene (Turm, Kreispyramide, Gummibälle) |
| `physics-sandbox` | gleichwertiger Befehl, den die Installation anlegt |
| `python -m sandbox --demo --screenshot bild.png --seconds 3` | läuft 3 s, speichert ein Bildschirmfoto und beendet sich |
## Bedienung (Kurzfassung)
| Eingabe | Aktion |
|---|---|
| Linksklick ins Leere | Objekt erzeugen (gedrückt halten und ziehen = sofort werfen) |
| Linksklick auf Objekt + Ziehen | greifen und verschieben; Loslassen in Bewegung wirft es |
| Ziehen aus der Vorschau-Kachel | neues Objekt aus der Sidebar in die Welt ziehen |
| Rechtsklick / `Entf` | Objekt unter der Maus löschen |
| Mausrad | Größe ändern (über einem Regler: diesen Regler verstellen) |
| `Leertaste` · `G` · `C` | Pause/Weiter · Schwerkraft an/aus · Alles löschen |
| `1` · `2` | Kreis · Rechteck |
| `F1` · `Esc` | Debug-Ansicht · Beenden |
Alle Details: [docs/CONTROLS.md](docs/CONTROLS.md).
## Entwicklung
Entwicklungswerkzeuge (pytest, pytest-cov, ruff) installieren:
```bash
pip install -r requirements-dev.txt
```
Tests ausführen (inklusive Headless-UI-Tests – es öffnet sich kein Fenster):
```bash
pytest
```
Mit Testabdeckung:
```bash
pytest --cov=sandbox --cov-report=term-missing
```
Code prüfen und formatieren:
```bash
ruff check src tests
```
```bash
ruff format src tests
```
Details zu den Tests: [docs/TESTING.md](docs/TESTING.md).
## Projektstruktur
```text
├── src/sandbox/
│ ├── main.py Einstiegspunkt, App und Game-Loop
│ ├── config.py alle Konstanten (Physik, Interaktion, Farben, Layout)
│ ├── physics/ eigene Physik-Engine – nur `math`, kein pygame
│ │ ├── vector.py Vector2
│ │ ├── shapes.py Circle, Box (AABB), HalfPlane (Wände)
│ │ ├── body.py Body, Material
│ │ ├── collision.py Kollisionserkennung (Narrowphase)
│ │ ├── broadphase.py Sweep-and-Prune
│ │ ├── solver.py Impulsauflösung, Reibung, Rollwiderstand, Positionskorrektur
│ │ ├── sleep.py Schlafmodus (Kontakt-Inseln)
│ │ ├── timestep.py fester Zeitschritt
│ │ └── world.py Welt und Simulationsschritt
│ ├── interaction/ Werkzeuge ohne pygame: Erzeugen, Ziehen, Werfen
│ ├── ui/ Sidebar und selbst gezeichnete Widgets
│ ├── input_handler.py Maus und Tastatur → Aktionen
│ ├── renderer.py Zeichnen der Welt
│ ├── viewport.py Bildschirm ↔ Welt
│ └── demo.py Beispielszene
├── tests/ pytest-Suite (Physik, Interaktion, Headless-UI, Smoke-Test)
├── docs/ Dokumentation
├── requirements.txt Laufzeit-Abhängigkeiten
├── requirements-dev.txt Test- und Linting-Werkzeuge
└── pyproject.toml Paket-, ruff- und pytest-Konfiguration
```
## Dokumentation
- [docs/PHYSIK_EINSTIEG.md](docs/PHYSIK_EINSTIEG.md) – die Physik Schritt für Schritt für Einsteiger
- [docs/PHYSICS.md](docs/PHYSICS.md) – die verwendete Physik und ihre Formeln
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) – Module, Datenfluss im Game-Loop, Diagramme
- [docs/TESTING.md](docs/TESTING.md) – Tests ausführen, was getestet wird, Headless-Modus
- [docs/CONTROLS.md](docs/CONTROLS.md) – alle Maus- und Tastaturbefehle
## Screenshots
Demo-Szene mit gerade geworfenem Rechteck (gelb umrandet, der Pfeil zeigt die
Wurfgeschwindigkeit):
![Demo-Szene](docs/images/screenshot.png)
Debug-Ansicht (`F1`): Kontaktpunkte (gelb), Kontaktnormalen (rot) und Kennzahlen:
![Debug-Ansicht](docs/images/debug.png)
Ein aktuelles Bild der Demo-Szene erzeugst du jederzeit mit
`python -m sandbox --demo --screenshot docs/images/demo.png`.