Document the game pause and time scale nodes (#167)
- Concepts: new section "The game pauses itself" and the "Run while paused" row. - Behaviors: the five new nodes in the node list. - Scenes: what Load scene and Restart do with pause and time scale. - Architecture: the second pause next to the toolbar pause. - Development: check total 1217. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent
1d530fe900
commit
396314f38d
5 files changed
+37
-6
No files matched your search
@@ -264,6 +264,15 @@ its sounds at normal speed — a tape being slowed is a sound effect of its own,
|
|||||||
"half speed" — so the audio device is left alone and only what the world *does* is scaled.
|
"half speed" — so the audio device is left alone and only what the world *does* is scaled.
|
||||||
A pause is the exception, because a voice playing over a still image is nobody's idea of paused:
|
A pause is the exception, because a voice playing over a still image is nobody's idea of paused:
|
||||||
the audio context is suspended and resumes mid-note.
|
the audio context is suspended and resumes mid-note.
|
||||||
|
**The game's own pause is a flag on the world, not a second clock** (#167). `Pause game` sets
|
||||||
|
`World.paused`; `World.tick` reads it once per frame (`frozen`), and a frozen frame neither moves
|
||||||
|
the world time nor ticks a system unless it says `runsWhilePaused` — only the `BehaviorSystem`
|
||||||
|
does, and it then runs just the instances whose object has `runWhilePaused` on, without collision
|
||||||
|
and animation events. The editor holds the global clock for such a frame too, so particles and
|
||||||
|
shaders freeze with the world, and hands the behaviors the step the clock *would* have taken
|
||||||
|
(`PlaySession.tick(step, awake)`). `Set time scale` writes `GameClock.scale` through the clock a
|
||||||
|
played game gives the `BehaviorSystem` (`GameSystemOptions.clock`); the editor run gets none,
|
||||||
|
which is how it ignores the node. The sounds stay out of it: a pause menu may have its music.
|
||||||
|
|
||||||
**Everything the graph does to the outside world goes through the context, audio included.**
|
**Everything the graph does to the outside world goes through the context, audio included.**
|
||||||
`NodeContext.playSound` takes an asset id, not a file: resolving it — and folding the asset's own
|
`NodeContext.playSound` takes an asset id, not a file: resolving it — and folding the asset's own
|
||||||
|
|||||||
+1
@@ -119,6 +119,7 @@ shown on the node and editable in the inspector.
|
|||||||
direction; every play is a voice of its own, so two in a row overlap, and the voice ends with the
|
direction; every play is a voice of its own, so two in a row overlap, and the voice ends with the
|
||||||
behavior that started it unless `detached` says otherwise),
|
behavior that started it unless `detached` says otherwise),
|
||||||
`Load scene` (swaps the running scene once the frame is over — see [Scenes](Scenes)), `Log`, `Stop game`, `Restart game`,
|
`Load scene` (swaps the running scene once the frame is over — see [Scenes](Scenes)), `Log`, `Stop game`, `Restart game`,
|
||||||
|
`Pause game`, `Resume game`, `Set time scale` with the data nodes `Is game paused` and `Time scale` (see [Concepts](Concepts), *The game pauses itself*),
|
||||||
`Apply force`, `Apply impulse`, `Set velocity`, `Set angular velocity`, `Set gravity` (see [Physics](Physics)),
|
`Apply force`, `Apply impulse`, `Set velocity`, `Set angular velocity`, `Set gravity` (see [Physics](Physics)),
|
||||||
`Raycast` (what a ray meets first on the layers it looks at: object, collider, point, normal, distance — see [Colliders](Colliders#raycast)),
|
`Raycast` (what a ray meets first on the layers it looks at: object, collider, point, normal, distance — see [Colliders](Colliders#raycast)),
|
||||||
`Raycast all` (everything on that line instead, as parallel lists sorted by distance, with a `count` and a `max hits` — see [Colliders](Colliders#raycast-all)),
|
`Raycast all` (everything on that line instead, as parallel lists sorted by distance, with a `count` and a `max hits` — see [Colliders](Colliders#raycast-all)),
|
||||||
|
|||||||
+21
@@ -16,6 +16,7 @@
|
|||||||
| **Behavior** | Logic as an asset: a **node graph** plus the **variables** it declares. Placed like anything else (a diamond symbol in the scene); its parent is the **owner** the graph acts on. |
|
| **Behavior** | Logic as an asset: a **node graph** plus the **variables** it declares. Placed like anything else (a diamond symbol in the scene); its parent is the **owner** the graph acts on. |
|
||||||
| **Variables asset** | Declarations and nothing else — no graph, no position, never placed. A `Variables` node naming it reads and writes **one value per key for the whole run**, however many graphs point at it. The values start at the declared ones on every Play and are never written back, so playing cannot change the project; while a run is on the asset's inspector shows them live and an edit there reaches the run at once. Two such assets may declare the same name without meeting. See [Behaviors](Behaviors). |
|
| **Variables asset** | Declarations and nothing else — no graph, no position, never placed. A `Variables` node naming it reads and writes **one value per key for the whole run**, however many graphs point at it. The values start at the declared ones on every Play and are never written back, so playing cannot change the project; while a run is on the asset's inspector shows them live and an edit there reaches the run at once. Two such assets may declare the same name without meeting. See [Behaviors](Behaviors). |
|
||||||
| **Run in editor** | A switch only behaviors have (default off). With it on the behavior keeps running while the project is **not** playing — and unlike Play it then edits the *saved* model: what it moves or writes is a real change, autosaved and not on the undo stack. See *Running without Play*. |
|
| **Run in editor** | A switch only behaviors have (default off). With it on the behavior keeps running while the project is **not** playing — and unlike Play it then edits the *saved* model: what it moves or writes is a real change, autosaved and not on the undo stack. See *Running without Play*. |
|
||||||
|
| **Run while paused** | The other switch only behaviors have (default off). While a graph has paused the game (`Pause game`), only behaviors with it on are ticked — the pause menu, which is also the only thing that can resume. See *The game pauses itself*. |
|
||||||
| **Collider** | A shape (box or circle) for collision detection, placed as a **child** of the object it belongs to (its *body*). Drawn as a green outline in edit mode only. |
|
| **Collider** | A shape (box or circle) for collision detection, placed as a **child** of the object it belongs to (its *body*). Drawn as a green outline in edit mode only. |
|
||||||
| **Collision layer** | One of up to 16 named layers of the project (**menu → Project settings…**). A collider or tilemap names the layer it is on and the layers it **collides with**; two of them meet only when each one names the layer of the other. A new project has one layer, *Default*, which every collider is on and meets — so nothing collides differently until a layer is named. See [Colliders](Colliders#collision-layers). |
|
| **Collision layer** | One of up to 16 named layers of the project (**menu → Project settings…**). A collider or tilemap names the layer it is on and the layers it **collides with**; two of them meet only when each one names the layer of the other. A new project has one layer, *Default*, which every collider is on and meets — so nothing collides differently until a layer is named. See [Colliders](Colliders#collision-layers). |
|
||||||
| **Rigidbody** | Placed as a **child** of an object, it hands that object to the physics engine while playing: it falls with the scene's gravity, bounces and rests on colliders, pushed by what it meets. At most one per object. See [Physics](Physics). |
|
| **Rigidbody** | Placed as a **child** of an object, it hands that object to the physics engine while playing: it falls with the scene's gravity, bounces and rests on colliders, pushed by what it meets. At most one per object. See [Physics](Physics). |
|
||||||
@@ -138,6 +139,26 @@ shaders and the Animation tab's preview stand still with the world rather than c
|
|||||||
it. That clock starts a run at second 0 and goes back to 0 when the run ends, which is why the
|
it. That clock starts a run at second 0 and goes back to 0 when the run ends, which is why the
|
||||||
scene view looks freshly loaded after Stop.
|
scene view looks freshly loaded after Stop.
|
||||||
|
|
||||||
|
**The game pauses itself.** The toolbar's hold is the editor's: nothing runs under it, not even a
|
||||||
|
graph. A game that wants a pause menu, a slow motion or a frozen moment during a dialog does it
|
||||||
|
from its own graphs (#167):
|
||||||
|
|
||||||
|
| Node | What it does |
|
||||||
|
| --- | --- |
|
||||||
|
| `Pause game` | From the next frame on the world time, physics, animations, particles and shader time stand still, and only behaviors with **Run while paused** are ticked. They get their keys, clicks, timers and `On update` as usual; collisions are not reported, because nothing moves that could collide. Sounds play on. |
|
||||||
|
| `Resume game` | Lets it run on from where it stood, from the next frame. |
|
||||||
|
| `Is game paused` | True while it is paused, so one key can do both (`Is game paused` → `Branch` → `Resume game` / `Pause game`). |
|
||||||
|
| `Set time scale` | How fast the game runs: 1 is real time, 0.5 slow motion, 2 twice as fast. Movement, physics, animations, particles and shader time follow it. At 0 everything is frozen, but the graphs keep running with a `dt` of 0 — that is the difference to a pause. |
|
||||||
|
| `Time scale` | The scale as it was last set. |
|
||||||
|
|
||||||
|
The two are kept apart on purpose: a pause stops the game but not its menu, a time scale of 0
|
||||||
|
stops time but no graph. **A pause belongs to the scene**, so a `Load scene` from a pause menu
|
||||||
|
arrives in an unpaused level, and so does a `Restart game`. **The time scale belongs to the run**:
|
||||||
|
it carries over a `Load scene`, and Play and Stop set it back to 1 — also for the editor's
|
||||||
|
previews, which share the clock. The toolbar's hold works on top of either one and leaves both as
|
||||||
|
they are. In the editor run both are ignored with a line in the console: an edited scene that stops
|
||||||
|
for no visible reason, or an editor whose previews crawl, would help nobody.
|
||||||
|
|
||||||
**Running without Play.** A behavior switched to **Run in editor** goes on running while the
|
**Running without Play.** A behavior switched to **Run in editor** goes on running while the
|
||||||
project is not playing (`src/editor/EditorRun.ts`, ticked by the Editor next to the play session).
|
project is not playing (`src/editor/EditorRun.ts`, ticked by the Editor next to the play session).
|
||||||
The switch is an ordinary property, so it can be set on the behavior asset and overridden per
|
The switch is an ordinary property, so it can be set on the behavior asset and overridden per
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs
|
|||||||
npm run build # writes dist/ and regenerates index.html
|
npm run build # writes dist/ and regenerates index.html
|
||||||
./build.sh # the same under `set -o pipefail`, for callers that pipe the output
|
./build.sh # the same under `set -o pipefail`, for callers that pipe the output
|
||||||
php tools/make-user.php <name> <password> # an account; every tool signs in (see Accounts)
|
php tools/make-user.php <name> <password> # an account; every tool signs in (see Accounts)
|
||||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1210 editor checks, screenshots in /tmp/gm-e2e-*.png
|
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1217 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||||
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
|
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
|
||||||
./e2e.sh start [GM_STEPS] # the same run detached, see below
|
./e2e.sh start [GM_STEPS] # the same run detached, see below
|
||||||
./e2e.sh status # live progress, or the last run's result
|
./e2e.sh status # live progress, or the last run's result
|
||||||
|
|||||||
+5
-5
@@ -82,8 +82,8 @@ are looking at, brought to life; swapping it would mean editing a scene you are
|
|||||||
|
|
||||||
## Restart, stop, load — what each one keeps
|
## Restart, stop, load — what each one keeps
|
||||||
|
|
||||||
| | Objects | Shared variables | Global machines | Clock | Sounds |
|
| | Objects | Shared variables | Global machines | Clock | Time scale | Pause game | Sounds |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
| **Load scene** | rebuilt | kept | kept | keeps running | end with their behavior |
|
| **Load scene** | rebuilt | kept | kept | keeps running | kept | lifted | end with their behavior |
|
||||||
| **Restart game** | rebuilt | back to declared | back to their start state | back to 0 | all end |
|
| **Restart game** | rebuilt | back to declared | back to their start state | back to 0 | back to 1 | lifted | all end |
|
||||||
| **Stop** (`Esc`) | gone | discarded | discarded | back to 0 | all end |
|
| **Stop** (`Esc`) | gone | discarded | discarded | back to 0 | back to 1 | lifted | all end |
|
||||||
Reference in new issue
Block a user