A transition is a named arrow between two states, drawn without pins (#52)
State machines: the asset is no longer "a set of states and nothing more" -- it holds the moves between them. How a transition is drawn (right-click, Make transition, click the target), why a state still carries ports it never shows, what the arrow looks like border to border, and that the inspector's out/in lists are the only way to delete one. Names need not be unique across a machine, only among the transitions leaving the same state, and that is exactly what makes one `State transition` node usable from several states. The node itself is the third way a behavior reads a machine, beside `State branch` and `Set state`. Concepts, Home: the summary lines name `State transition` too. Development: 844 -> 862 checks.
1 parent
6e524c262e
commit
7b5974b37c
4 files changed
+44
-11
No files matched your search
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
| **Asset** | Named thing with a type (`scene`, `camera`, `sprite`, `text`, `behavior`, `collider`, `container`, `texture`, `animation`, `statemachine`, `shader`, `font`, `particles`) and typed properties. Assets have **no position**. |
|
| **Asset** | Named thing with a type (`scene`, `camera`, `sprite`, `text`, `behavior`, `collider`, `container`, `texture`, `animation`, `statemachine`, `shader`, `font`, `particles`) and typed properties. Assets have **no position**. |
|
||||||
| **Texture** | An uploaded image. Scenes, textures, animations, state machines, shaders and fonts are the six types that cannot be placed: a texture has no position, it is *worn* by a sprite through the ordinary property `texture`. See [Textures](Textures). |
|
| **Texture** | An uploaded image. Scenes, textures, animations, state machines, shaders and fonts are the six types that cannot be placed: a texture has no position, it is *worn* by a sprite through the ordinary property `texture`. See [Textures](Textures). |
|
||||||
| **Font** | An uploaded typeface, worn by a text through the ordinary property `font`; no font means the editor's own. Uploaded and picked exactly like a texture, and stored the same way. See [Fonts](Fonts). |
|
| **Font** | An uploaded typeface, worn by a text through the ordinary property `font`; no font means the editor's own. Uploaded and picked exactly like a texture, and stored the same way. See [Fonts](Fonts). |
|
||||||
| **State machine** | A named set of **states**, edited as nodes in its own tab. A behavior puts it into a state with `Set state` and branches on it with `State branch`; each behavior instance keeps its own current state. See [State machines](State-machines). |
|
| **State machine** | A named set of **states**, edited as nodes in its own tab. A behavior puts it into a state with `Set state`, moves it along a named transition with `State transition` and branches on it with `State branch`; each behavior instance keeps its own current state. See [State machines](State-machines). |
|
||||||
| **Shader** | A node graph that becomes the GLSL a sprite is drawn with, edited in its own tab. A sprite wears it through `shader`; the numbers the graph declares are rows below that dropdown. See [Shaders](Shaders). |
|
| **Shader** | A node graph that becomes the GLSL a sprite is drawn with, edited in its own tab. A sprite wears it through `shader`; the numbers the graph declares are rows below that dropdown. See [Shaders](Shaders). |
|
||||||
| **Particles** | A node graph that says what *one* particle is as a function of its age and of a random number drawn once for it — no forces, no simulation. Unlike the other graph assets it **is** placeable: the object made from it is a source, whose rows say how many go out and for how long they live. Because a particle is a formula, the same second always draws the same picture and the tab's slider can jump to any of them exactly. See [Particles](Particles). |
|
| **Particles** | A node graph that says what *one* particle is as a function of its age and of a random number drawn once for it — no forces, no simulation. Unlike the other graph assets it **is** placeable: the object made from it is a source, whose rows say how many go out and for how long they live. Because a particle is a formula, the same second always draws the same picture and the tab's slider can jump to any of them exactly. See [Particles](Particles). |
|
||||||
| **Text** | An asset that draws a line of text (`text`, `font`, `fontSize`, `color`, `align`) — titles, HUD readouts, button labels. Its content is an ordinary property, so a `Properties` node of type Text with `text` switched to Set changes it while playing. |
|
| **Text** | An asset that draws a line of text (`text`, `font`, `fontSize`, `color`, `align`) — titles, HUD readouts, button labels. Its content is an ordinary property, so a `Properties` node of type Text with `text` switched to Set changes it while playing. |
|
||||||
|
|||||||
+2
-2
@@ -12,7 +12,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs
|
|||||||
# code is lost (tail's is reported), so a red run reads as green
|
# code is lost (tail's is reported), so a red run reads as green
|
||||||
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
|
||||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 844 editor checks, screenshots in /tmp/gm-e2e-*.png
|
node tools/seed-e2e.mjs && node tools/e2e.mjs # 862 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
|
||||||
@@ -165,4 +165,4 @@ widths to find click points. The **render device is not in this repo** — `/dev
|
|||||||
and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which
|
and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which
|
||||||
applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets
|
applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets
|
||||||
WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`,
|
WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`,
|
||||||
WebGL 2.0, and the same 844 checks as here.
|
WebGL 2.0, and the same 862 checks as here.
|
||||||
+1
-1
@@ -15,7 +15,7 @@ Live: <https://nockal.com/game-maker/> · Widget playground: <https://nockal.com
|
|||||||
| [Colliders](Colliders) | Collider assets, collision events, blocking movement |
|
| [Colliders](Colliders) | Collider assets, collision events, blocking movement |
|
||||||
| [Textures](Textures) | Getting images in, where they go, tinting, the filter, frames, upload limits |
|
| [Textures](Textures) | Getting images in, where they go, tinting, the filter, frames, upload limits |
|
||||||
| [Animations](Animations) | Animation assets, the Animation tab, how they run |
|
| [Animations](Animations) | Animation assets, the Animation tab, how they run |
|
||||||
| [State machines](State-machines) | The state machine asset, `State branch` and `Set state` |
|
| [State machines](State-machines) | The state machine asset, named transitions, `State branch`, `Set state` and `State transition` |
|
||||||
| [Shaders](Shaders) | The shader asset, the Shader tab, the node set, the Adjust colors recipe, wearing a shader |
|
| [Shaders](Shaders) | The shader asset, the Shader tab, the node set, the Adjust colors recipe, wearing a shader |
|
||||||
| [Containers](Containers) | Editing a template, instances and their edits, screens without scene switching |
|
| [Containers](Containers) | Editing a template, instances and their edits, screens without scene switching |
|
||||||
| [Keyboard](Keyboard) | Every shortcut |
|
| [Keyboard](Keyboard) | Every shortcut |
|
||||||
|
|||||||
+40
-7
@@ -1,14 +1,40 @@
|
|||||||
A **state machine asset** is a named set of states and nothing more, yet: its graph holds one
|
A **state machine asset** is a named set of states and the moves allowed between them: its graph
|
||||||
`State` node per state (a title and a *Name* setting, no ports) and no edges. Transitions,
|
holds one `State` node per state (a title and a *Name* setting) and one edge per transition. Events
|
||||||
events like "on state entered" and a highlight of the current state while playing are later
|
like "on state entered" and a highlight of the current state while playing are later steps. The states are edited in the **State machine** tab, which is the graph
|
||||||
steps. The states are edited in the **State machine** tab, which is the graph canvas the Behavior
|
canvas the Behavior tab uses — so placing, dragging, the header's **Snap** checkbox, renaming in
|
||||||
tab uses — so placing, dragging, the header's **Snap** checkbox, renaming in the inspector,
|
the inspector, connecting, `Delete` and undo are the graph's.
|
||||||
`Delete` and undo are the graph's.
|
|
||||||
Double-clicking the asset (or creating it) opens the tab, like every asset with a tab; a click
|
Double-clicking the asset (or creating it) opens the tab, like every asset with a tab; a click
|
||||||
only selects. Right-click on its canvas offers a `State` and
|
only selects. Right-click on its canvas offers a `State` and
|
||||||
nothing else, named by its number (`State 3` for the third); no behavior palette offers one.
|
nothing else, named by its number (`State 3` for the third); no behavior palette offers one.
|
||||||
|
|
||||||
**A behavior reads it through two nodes**, both with a `machine` input that is a picker while
|
## Transitions
|
||||||
|
|
||||||
|
A **transition** is an arrow from one state to another. Right-click a state, choose
|
||||||
|
**Make transition**, then click the state it should lead to; anywhere else, or `Escape`, drops the
|
||||||
|
attempt. It joins two whole states, so there is nothing to aim at on either node and **no pins are
|
||||||
|
drawn**.
|
||||||
|
|
||||||
|
Underneath it is an ordinary graph edge, which is the whole point: connecting, undo, the clean-up
|
||||||
|
when a state is deleted and the save format all come from the graph and needed nothing new. A state
|
||||||
|
therefore still *carries* an `in` and an `out` port — a port is the only anchor an edge has in this
|
||||||
|
editor — the editor simply never draws them and never lets them be grabbed. Between two states the
|
||||||
|
edge is a **straight arrow** rather than the usual curve, running border to border with a little
|
||||||
|
air at each end. Two transitions between the same pair are pushed apart, so a there-and-back pair
|
||||||
|
lies side by side instead of on top of each other. Two arrows the *same* way round are refused
|
||||||
|
(`Already connected`), because every transition hangs on the same two ports.
|
||||||
|
|
||||||
|
A transition can be **named**. Select a state and the inspector lists its transitions in two
|
||||||
|
groups, *out* and *in*, each row with the state at the far end, a name field and a button to
|
||||||
|
remove it — that list is also the only way to delete a transition, since the arrow itself cannot
|
||||||
|
be clicked. The name is drawn on the arrow. Names need **not** be unique across the machine: what
|
||||||
|
must not repeat is two transitions of the same name leaving the *same* state (the inspector warns
|
||||||
|
when they do). That is the point of naming them — a single `State transition` node asking for
|
||||||
|
`alarm` moves every state that has an `alarm`.
|
||||||
|
|
||||||
|
A transition does **not** restrict `Set state`: that node still puts the machine into any state it
|
||||||
|
is wired to. What the arrows are for at runtime is `State transition`.
|
||||||
|
|
||||||
|
**A behavior reads it through three nodes**, each with a `machine` input that is a picker while
|
||||||
unconnected (or takes a `State machine` node, the literal every kind has):
|
unconnected (or takes a `State machine` node, the literal every kind has):
|
||||||
|
|
||||||
- **`State branch`** grows **one exec output per state**, named after the state, and continues
|
- **`State branch`** grows **one exec output per state**, named after the state, and continues
|
||||||
@@ -19,6 +45,13 @@ unconnected (or takes a `State machine` node, the literal every kind has):
|
|||||||
flow *arrives through* names the new state — so `OnStart → Set state (Open)` and `On key down →
|
flow *arrives through* names the new state — so `OnStart → Set state (Open)` and `On key down →
|
||||||
Set state (Closed)` are two edges into one node. The interpreter hands every node the exec input
|
Set state (Closed)` are two edges into one node. The interpreter hands every node the exec input
|
||||||
a pulse entered through (`run(…, entry)`); this is the first node to read it.
|
a pulse entered through (`run(…, entry)`); this is the first node to read it.
|
||||||
|
- **`State transition`** takes the transition of a chosen **name** out of the current state, then
|
||||||
|
continues. The name is picked in the inspector from the transitions of the machine on its
|
||||||
|
`machine` input — the options depend on another field, which no field kind can express, so that
|
||||||
|
picker is written by hand. Leaving it at *(unnamed)* follows the one transition nobody named.
|
||||||
|
If the current state carries no transition of that name, or **two** of it, the machine stays
|
||||||
|
where it is — choosing between two arrows the graph never picked between would be a guess. It
|
||||||
|
reads the machine's transitions through the project lookup the interpreter already carries.
|
||||||
|
|
||||||
The ports are keyed by the **state's node id** and labelled by its name: renaming a state keeps
|
The ports are keyed by the **state's node id** and labelled by its name: renaming a state keeps
|
||||||
every edge. Deleting one is the awkward case, because the port lives in a *behavior* while the
|
every edge. Deleting one is the awkward case, because the port lives in a *behavior* while the
|
||||||
|
|||||||
Reference in new issue
Block a user