Files
feuerwerk/todo-notes/done/game-pause.md
T
root 9c4148dc1b Hold a running game, and let the editor run reach into containers
Pause is a sub-state of play, not a third mode: the toolbar button and
Ctrl+Enter stop ticking the world, the clock included. A held frame still
drops the input edges, so resuming does not fire a pause worth of keys in
one go.

The editor run missed the case it is most wanted for. hasEditorRun only
looked at the stored scene objects, so a behavior inside a placed
container never started one; the world now builds from resolveObjects and
writes back through objectRef, keeping the move as an instance edit
instead of baking the instance out.

Keys and clicks go to the run while the Game tab is on screen, where no
key means anything to the editor, and are handed back on leaving it -
held keys released, so nothing keeps walking unpressed.
2026-09-09 18:16:28 +02:00

59 lines
3.7 KiB
Markdown
Raw 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.
die möglichkeit das spiel zu pausieren und fortzusetzen
---
**Umgesetzt (2026-09-09).** In der Toolbar steht neben *Play* ein zweiter Knopf, der zwischen
**Pause** und **Resume** wechselt; dasselbe macht **`Ctrl+Enter`** waehrend des Spielens. Gehalten
heisst: die Welt wird **nicht mehr getickt**. Damit stehen Behaviors, Timer und Kollisionen still
— und die Weltuhr steht mit ihnen, was fuer `On timer` der eigentliche Punkt ist.
**Pause ist ein Unterzustand von Play, kein dritter Modus** (`EditorState.paused`). Alles, was
Play von Edit unterscheidet — die Laufzeitkopie, die eigene Undo-Historie, dass nichts gespeichert
wird —, gilt waehrend der Pause unveraendert; ein dritter `EditorMode` haette jede vorhandene
Abfrage `mode === 'play'` zu einer Fallunterscheidung gemacht. Der Zustand wird beim Verlassen von
Play, beim Betreten und beim Laden eines Projekts geloescht: **eine Pause kann ihren Lauf nie
ueberleben**, sonst stuende der Editor still und niemand wuesste warum.
**Eingaben waehrend der Pause werden verworfen, nicht gesammelt.** Ein gehaltener Frame ruft
weiterhin `input.endFrame()` und `world.dropPointerEdges()` auf. Ohne das haetten sich die
Tastatur- und Klick-Flanken der ganzen Pause angestaut und waeren beim Fortsetzen in einem
einzigen Frame losgegangen — aus zehn Sekunden Pause waere ein Sprung geworden, den niemand
ausgeloest hat.
**Warum `Ctrl+Enter` und kein Buchstabe:** waehrend des Spielens gehoert die Tastatur dem Spiel.
Ein `P` oder die Leertaste waere dem Spiel dauerhaft weggenommen. `Ctrl+Enter` startet Play schon
bisher, haelt es jetzt und laesst es weiterlaufen; `Esc` stoppt wie gehabt.
**Belegt** — sieben Unit-Tests (`tests/editor/pause.test.ts`; ohne die Regeln fallen drei davon
um, gegengeprueft) und neun E2E-Checks in Modul 18. Der Test-Hook `__gm.playInfo()` nennt dafuer
neu die **Weltuhr**, sonst waere "steht wirklich still" nicht von "sieht gerade gleich aus" zu
unterscheiden:
```
PASS the box drifts on its own while playing, with nothing held down
– x 46.66 → 98.33, {"playing":true,"paused":false,"time":0.4666}
PASS pausing stops the world where it is: the box and the clock both stand still
– x 99.99 → 99.99, clock 1.00 → 1.00 over 1 s
PASS resuming lets it move on from where it stopped, without catching up the held time
– x 99.99 → 141.65, clock 1.00 → 1.40
PASS a key pressed while paused is swallowed instead of firing on resume
– 0 hits before, 0 while held, 0 after resuming
PASS the same key does fire once the game is running again – 0 → 1
PASS stopping clears the hold, so the next play runs
– after stop {"playing":false,"paused":false,"time":0}, x 96.66 → 138.33
```
Der erste Check ist die Voraussetzung des zweiten: ohne nachgewiesene Bewegung waere "steht still"
trivial gruen. Der letzte Check derselbe Gedanke fuer die Tastatur — ohne ihn waere "keine Taste
hat gefeuert" auch dann gruen, wenn der Graph ueberhaupt nie feuert. Die Uhr im dritten Check ist
der Beweis gegen das Nachholen: sie laeuft bei **1.00** weiter, nicht bei den ~3.5, die seit dem
Anhalten vergangen sind.
**Offen geblieben — bewusst.** Ein **`Pause game`-Node** fuer den Graphen (passend zu `Stop game`
und `Restart game`) waere der naechste Schritt, damit ein Spiel sich selbst anhalten kann
(Pausenmenue, Game Over). Ich habe dazu gefragt, aber keine Antwort bekommen, und einen
game-facing Node nicht im Alleingang eingefuehrt: ein Node ist dauerhafte API, und ohne einen
Weg zurueck **aus dem Spiel heraus** waere ein so pausiertes Spiel nur ueber die Toolbar wieder
zu starten. Beides — Node und ein fester Weiter-Weg im Spiel — laesst sich auf dem jetzigen
Stand billig nachziehen: `state.setPaused(true)` ist alles, was ein Node tun muesste.