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.
59 lines
3.7 KiB
Markdown
59 lines
3.7 KiB
Markdown
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.
|