proejct commit
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
# 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.
|
||||
|
||||

|
||||
|
||||
## 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):
|
||||
|
||||

|
||||
|
||||
Debug-Ansicht (`F1`): Kontaktpunkte (gelb), Kontaktnormalen (rot) und Kennzahlen:
|
||||
|
||||

|
||||
|
||||
Ein aktuelles Bild der Demo-Szene erzeugst du jederzeit mit
|
||||
`python -m sandbox --demo --screenshot docs/images/demo.png`.
|
||||
Reference in New Issue
Block a user