Skip to content

Commit fe5d822

Browse files
AlexZ005claude
andcommitted
[docs] the Spawn node, and build-a-game on the collectible module
- nodes/spawn.md: what a spawner is for, the four parameters and the 200 global ceiling, that `at` is an OFFSET from the template rather than a world position, and the crate-dispenser walkthrough. Plus the four things that read as bugs until you know them: nothing fires until the next real press after wiring (the stale-stamp guard that stops a node spawning on connect), stopping the sim removes every copy and undo will not bring them back, saving mid-run saves the template only, and a copy does not carry the template's clips/flow/shader graph. - build-a-game: the collectible section now installs the module from Browse and uses its one node instead of core's old seven-node recipe, covers all six params incl. per-player scope and the touch trigger, and says that legacy scenes keep working. The mkdocs Splines entry and the terrain/controls edits pending in this checkout belong to the 21-C batch and are deliberately left uncommitted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 72d14c7 commit fe5d822

3 files changed

Lines changed: 142 additions & 29 deletions

File tree

‎docs/build-a-game.md‎

Lines changed: 68 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@
22

33
A complete worked example — a start menu, a walking character, collectibles that count
44
into the HUD, a hold-to-peek map, a pause menu you can click, and a second level to
5-
travel to. Everything is authored in the app with the HUD editor and flow nodes. No
6-
code, no modules.
5+
travel to. Everything is authored in the app with the HUD editor and flow nodes — no
6+
code, and one optional module for the collectibles.
77

88
Allow about twenty minutes. Each step works on its own, so you can stop anywhere and
99
still have something playable, and every piece is visible to the people connected with
1010
you as you build it.
1111

1212
!!! tip "What you'll need"
1313
A scene with some ground to walk on and a few objects to collect. A gamepad is
14-
optional — it works out of the box if you have one.
14+
optional — it works out of the box if you have one. Step 4 uses the
15+
**Collectibles** module: install it once from **Menu ▸ Modules ▸ Browse**, and have
16+
everyone you are playing with install it too — modules do not travel over the
17+
connection.
1518

1619
---
1720

@@ -82,34 +85,64 @@ node can read or set that same value — so a sprint key is just a key press wir
8285

8386
## 4. Collectibles that count
8487

85-
1. Select the objects you want to collect, right-click and choose
86-
**Game ▸ Make collectible**.
87-
2. Each object gets a small graph: clicking it hides it, remembers that it was
88-
collected, and adds `1` to a variable called `gems`.
88+
This step uses the **Collectibles** module — install it from **Menu ▸ Modules ▸ Browse**
89+
(and so does everyone playing with you).
90+
91+
1. Select the objects you want to collect.
92+
2. Open the **Collectibles** window: the sidebar's **Modules** section, or the viewport
93+
right-click menu. Leave the fields alone for now and press **Make collectible**.
8994
3. On your in-game HUD screen, add a **Text** element, then **Actions ▸ Show a
9095
variable** and enter `gems`.
9196

9297
Press Play, walk up to one and click it with the crosshair. It disappears for
9398
**everyone**, the counter goes up on every screen, and clicking the empty space where it
9499
was does nothing — it stays collected.
95100

96-
A few dials, all optional:
97-
98-
- **Make collectible into…** asks which variable it counts into (existing names are
99-
offered as chips, or type a new one) and whether it **respawns** after a few seconds.
100-
The respawn is built into the graph — a Delay off the click resets the Latch and
101-
re-arms the Once — so you can see it and change it in the node editor.
102-
- Run it on a **Group** and every mesh inside becomes a collectible sharing the group's
103-
variable, as one undo step. Add a new member later and run it again: the ones that are
104-
already collectible are skipped ("2 added, 3 skipped").
105-
- Collectibles **reset when a new round starts** and when the game returns to its menu —
106-
that is the "reset each round" checkbox the recipe sets on its Latch and Once, derived
107-
from the shared round, so a Restart needs no extra wiring. And when you leave play
108-
mode, collected objects come straight back on your own screen ("only while playing"
109-
on the Visibility node), so the editor never loses an object to a running game.
110-
- **Collect Count** is the node that answers "how many are left" — it reads the
111-
collectible chains in the graph, not the score, so it is right after a respawn and
112-
after a round reset. **Actions ▸ Show collectibles left** wires it to a Text for you.
101+
Each object got **one Collectible node** wired to an Object Selector naming it, in the
102+
scene graph, added as **one undo step**. Open the node editor and you can see it, change
103+
it, or wire something else off it — it is an ordinary graph, not a hidden feature.
104+
105+
The node's dials, all optional and all editable either on the card or in the Collectibles
106+
window's list:
107+
108+
- **Counts into** — the variable, `gems` by default. Existing names are suggested; type a
109+
new one for a second kind of pickup.
110+
- **Scope** — `shared` gives the room one score. `player` makes it **personal**: the
111+
object vanishes only for whoever picked it up and counts into *their* number, which is
112+
what you want for a race or a co-op scramble. Read a personal number back with the
113+
**Player Variable** node, or show the standings with **Leaderboard**.
114+
- **Trigger** — `click` (mouse or VR trigger) or `touch`, which fires when a player walks
115+
within **Radius** metres of it. Touch needs no physics: each player notices the pickup
116+
for themselves.
117+
- **Hide** — turn it **off** and you get a *counting checkpoint*: it still collects and
118+
still counts, but it never disappears. That is a lap gate or a pressure plate.
119+
- **Respawn** — seconds until it comes back. `0` means gone for good. A re-collect after a
120+
respawn counts again.
121+
122+
Two behaviours you get without wiring anything:
123+
124+
- Collectibles **reset when a new round starts** and read un-collected while the game sits
125+
in its menu, derived from the shared round — so a Restart needs no extra work.
126+
- When **you** leave play mode, your collected objects come straight back on your own
127+
screen, so the editor never loses an object to a running game — and hiding one from the
128+
object list works normally again.
129+
130+
The **Collectibles** window also lists everything in the scene grouped by variable, with
131+
live *collected / left of total* counts; click a row to select that object in the
132+
viewport.
133+
134+
**Collectibles** (the value node) answers "how many are left". It counts the nodes in the
135+
graph rather than the score — a score only goes up, so it would be wrong the first time
136+
something respawned. **Actions ▸ Show collectibles left** wires it to a Text for you.
137+
138+
!!! note "Two things worth knowing"
139+
A scene built with the older seven-node collectible recipe keeps working exactly as
140+
it did, and the **Collectibles** count node counts both shapes together.
141+
142+
A player who joins **mid-round** sees already-collected objects back on the table:
143+
pickups are events, and an event that happened before you connected is not replayed.
144+
Everything from the moment they join is in sync. Start the round after everyone is in,
145+
or use a Restart to put everybody on the same footing.
113146

114147
---
115148

@@ -167,15 +200,20 @@ That's the loop: menu → play → score → pause → end → menu.
167200
One scene is one level; a game can have many.
168201

169202
1. Build your first level, then in the **Explorer** right-click the file grid and
170-
choose **Save scene as level…**. It lands in a `Levels` folder as an ordinary
171-
`.tpscene` file. **New scene…** gives you an empty one to build the next level in.
203+
choose **Save scene…** — type the name right there in the grid and press Enter. It
204+
lands in a `Scenes` folder as an ordinary `.tpscene` file (a tidy default, nothing
205+
more: scenes are found by kind wherever they live, and a save lands in whatever
206+
library folder you have open). **New scene…** gives you an empty one to build the
207+
next level in.
172208
2. Where the first level should end — a door, a portal, a Finish button — add a
173209
**Travel** node (Game group) and pick the destination level on its card. Wire any
174210
trigger into it, or use **Actions ▸ Level complete — travel to a level** on a button.
175211
3. Press it and **everyone travels together**: each player loads the level themselves,
176212
and anyone missing the file pulls it from whoever has it first. The game — state,
177213
round, score variables — **carries across the hop**; the new level's own collectibles
178-
start fresh, because their little graphs live in the level file.
214+
start fresh, because their nodes live in the level file. Edits survive the
215+
round trip too: leaving an edited scene saves a new version of it automatically —
216+
see [Projects](projects.md) for version history and the `.tp` project file.
179217

180218
Two helpers that come with it:
181219

@@ -184,8 +222,9 @@ Two helpers that come with it:
184222
player in play mode says yes — spectators in the editor don't count. Feed it into the
185223
Travel node and nobody gets left behind.
186224
- The **Debug** HUD element (Display group) is a little pill for building: game state,
187-
round, elapsed time, your variables, collectibles left, who is playing and fps. Click
188-
it in-game to expand. Take it off the screen when you ship.
225+
round, elapsed time, your variables, who is playing and fps — plus a line per
226+
collectible variable when the Collectibles module is installed. Click it in-game to
227+
expand. Take it off the screen when you ship.
189228

190229
---
191230

‎docs/nodes/spawn.md‎

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Spawn
2+
3+
Makes copies of an object while the simulation runs — crates off a conveyor, targets, debris, ammo, waves of anything.
4+
5+
**Inputs:** `trigger` (event) · `at` (vector3) · `source` (object — the template)
6+
**Output:** effect (or wire the template into `source`)
7+
8+
## How it works
9+
10+
On the **rising edge** of whatever is wired into `trigger` — [Key Press](keypress.md), [On Click](onclick.md), [Timer](timer.md), [On Enter](onenter.md) — the node copies its **template** object and drops the copy into the scene with a live physics body. The copy inherits the template's physics, material and geometry, so a dynamic template gives you something that falls.
11+
12+
Copies are **transient**. They live for the run and nothing else: they are never written into a saved scene, they leave nothing on the undo stack however many times you fire, and they all disappear when the simulation stops. That is the whole design — a run's debris is not scene content.
13+
14+
The peer running the simulation makes the copy and everybody else receives it through the ordinary object sync, so two peers never disagree about what exists. Nothing extra goes on the wire for this node.
15+
16+
!!! warning "It needs a running simulation"
17+
A copy made with physics stopped would be inert, which is exactly the problem this node exists to remove — so with nothing simulating it refuses and says so instead of quietly doing nothing. Press <kbd>P</kbd> (or the ▶ button) **in the editor** first. You cannot start a simulation from inside Play mode; if you want both, turn on *simulate on play* in the scene's physics settings.
18+
19+
!!! tip "Give the template a body"
20+
If the template has no physics, the copies just hang in the air where they appear. Select it, then Inspector ▸ Physics ▸ Mode = *Dynamic*. The node warns you once when it notices.
21+
22+
## Parameters
23+
24+
| Parameter | Default | Meaning |
25+
|---|---|---|
26+
| copies per fire | 1 | how many appear per event (hard limit 20) |
27+
| max alive | 32 | how many this spawner keeps alive; when it is full, the **oldest** copy disappears as each new one arrives |
28+
| min seconds between | 0 | a floor between fires. A trigger edge is not a rate limit on its own — a *held* key re-fires several times a second |
29+
| spread | 0.5 | metres of random scatter, so a batch does not stack in one column |
30+
31+
There is also a **ceiling of 200 live copies across every spawner in the scene**, whatever the individual numbers say. An unbounded spawner in a shared session is both a memory problem and a griefing vector, so the limits are enforced when the copies are made and not merely suggested on the card.
32+
33+
## Where the copies appear
34+
35+
The `at` input (and the x/y/z on the card) is an **offset from the template**, not a world position — so a node with nothing wired drops copies just above an object you can already see. Wire a [Vector3](vector3.md) into `at` to aim it, or a [Math](math.md) chain if you want the point to move.
36+
37+
## Choosing the template
38+
39+
The same three ways as every other action node:
40+
41+
- **Object Selector → `source`** — "copy *that* object". The usual choice.
42+
- **Nothing at all**, if the Spawn node lives in an object's own flow (double-click the object in the node editor's Graphs tree) — it copies that object.
43+
- Keep the template somewhere visible in the scene. It stays editable, and a scene file that ships a spawner is self-documenting because you can see what it makes.
44+
45+
## Practical example
46+
47+
**A crate dispenser on a key.**
48+
49+
1. `/create box`, then Inspector ▸ Physics ▸ Mode = *Dynamic*. This is the template — move it somewhere visible and off the floor.
50+
2. In the node editor add **Scene ▸ Spawn**.
51+
3. Add **Triggers ▸ Key Press** (`code` = `KeyG`) → Spawn `trigger`.
52+
4. Add an **Object Selector** naming the box → Spawn `source`.
53+
5. Press <kbd>P</kbd> to start physics, then <kbd>G</kbd>: a copy appears 3 m above the template and falls.
54+
55+
**A burst.** Set *copies per fire* to 5 — five at once, scattered by *spread*.
56+
57+
**A capped fountain.** Set *max alive* to 8 and hold <kbd>G</kbd>: the count climbs to 8 and stays there, the oldest copy vanishing as each new one lands. That is the recycling, and it is what makes a spawner safe to leave running.
58+
59+
**A conveyor.** Drive `trigger` from a [Timer](timer.md) and set *min seconds between* to 2 for one crate every couple of seconds.
60+
61+
## Things worth knowing
62+
63+
- **Nothing spawns until the next real press** after you wire up a fresh Spawn node to a trigger that has already fired. That is deliberate: without it, a node arriving on a peer would adopt the last stamp it sees and spawn on connect.
64+
- **Stopping the simulation removes every copy at once**, and <kbd>Ctrl</kbd>+<kbd>Z</kbd> will not bring them back — there is nothing to undo, by design.
65+
- **Saving mid-run saves the template only.** Reload a scene you saved with forty crates in the air and you get the one box back.
66+
- A copy does not carry the template's animation clips, object flow or shader graph. Each of those replicates a whole document per object, and volume is a spawner's whole point.
67+
68+
## See also
69+
70+
- [Impulse](impulse.md) — shove a copy the moment it appears
71+
- [On Rest](onrest.md) — fire when a spawned body has settled
72+
- [Counter](counter.md) — count what you have made
73+
- [Physics](../physics.md) — bodies, ground, gravity and the simulation controls

‎mkdocs.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ nav:
4040
- Object Selector: nodes/objectselector.md
4141
- Velocity: nodes/velocity.md
4242
- Measure: nodes/measure.md
43+
- Spawn: nodes/spawn.md
4344
- Flow Input: nodes/flowinput.md
4445
- Flow Output: nodes/flowoutput.md
4546
- Object Flow: nodes/objectflow.md

0 commit comments

Comments
 (0)