# 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`.