incanto 0.71.0 → 0.73.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/incanto-check.mjs +114 -42
- package/bin/incanto-editor.mjs +15 -9
- package/bin/incanto-feel.mjs +11 -1
- package/bin/incanto-play.mjs +11 -1
- package/bin/incanto-playtest.mjs +11 -1
- package/bin/incanto-verify.mjs +9 -2
- package/dist/2d.d.ts +29 -4
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +137 -15
- package/dist/3d.js +6 -6
- package/dist/{agent8-Cfmd3ar_.js → agent8-CHTT4unP.js} +1 -1
- package/dist/{audio-player-L8yccdMP.d.ts → audio-player-BOrk4eQx.d.ts} +1 -1
- package/dist/{behavior-Dcz0fr1S.d.ts → behavior-J1cmVah0.d.ts} +9 -1
- package/dist/{create-game-LCHBLfA4.js → create-game-CAu-ucHg.js} +8 -7
- package/dist/{create-game-CH4kt78v.js → create-game-CbTLFjis.js} +37 -13
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +1 -1
- package/dist/editor.js +1036 -930
- package/dist/{environment-presets-99BzP_L-.js → environment-presets-BsFJM3v0.js} +277 -60
- package/dist/{gameplay-CNULJvwh.js → gameplay-CRte0OVf.js} +589 -35
- package/dist/gameplay.d.ts +136 -4
- package/dist/gameplay.js +2 -2
- package/dist/index.d.ts +6 -4
- package/dist/index.js +6 -6
- package/dist/{loader-8-IHvbKD.d.ts → loader-BAeWMYfF.d.ts} +10 -3
- package/dist/net.d.ts +2 -2
- package/dist/net.js +2 -2
- package/dist/{physics-2d-FhrXUc6B.js → physics-2d-CovokK7s.js} +94 -11
- package/dist/{physics-3d-CFEGxBXZ.js → physics-3d-BiK6Emwn.js} +202 -15
- package/dist/{picking-DVo7fI13.js → picking-Dtd8JInh.js} +2 -2
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-BYQCBySi.js → register-CY9QCCZs.js} +45 -9
- package/dist/{register-DuVdzxbq.js → register-CjociOtt.js} +19 -4
- package/dist/{replay-DEvp3kyV.js → replay-B6BbgGM_.js} +55 -12
- package/dist/{replay-F7IZHdFR.d.ts → replay-wZK5Ok5c.d.ts} +2 -2
- package/dist/{save-slots-Bvuh2p_r.js → save-slots-CEUGeLuB.js} +57 -3
- package/dist/{split-screen-eULetcg-.js → split-screen-BxZ5rBe7.js} +4 -4
- package/dist/{split-screen-CIYf1zSf.d.ts → split-screen-D6sx8z3Z.d.ts} +2 -2
- package/dist/{sprite-animation-CqR2o3SA.js → sprite-animation-Bz3DHD_4.js} +1 -1
- package/dist/{src-_jk0qLsS.js → src-D-dnVrFY.js} +1 -1
- package/dist/{test-CmN54kWv.js → test-DZmCFz0Q.js} +162 -30
- package/dist/test.d.ts +56 -5
- package/dist/test.js +2 -2
- package/dist/{touch-BnCyPA0G.js → touch-CioTZB-y.js} +1 -1
- package/dist/vite.d.ts +8 -1
- package/dist/vite.js +22 -5
- package/editor/assets/{agent8-yLIEYHbd.js → agent8-GuZ5u5bi.js} +1 -1
- package/editor/assets/{debug-u31w_yhq.js → debug-BbxionO2.js} +1 -1
- package/editor/assets/{index-DK9xMGpW.js → index-CNlTzQbm.js} +92 -92
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +634 -10
- package/skills/incanto-3d-character.md +113 -5
- package/skills/incanto-assets.md +9 -3
- package/skills/incanto-behaviors-and-scripts.md +26 -2
- package/skills/incanto-building-2d-games.md +15 -0
- package/skills/incanto-building-3d-games.md +45 -0
- package/skills/incanto-editor.md +10 -1
- package/skills/incanto-environment.md +7 -2
- package/skills/incanto-game-feel.md +16 -11
- package/skills/incanto-gameplay-behaviors.md +174 -15
- package/skills/incanto-node-reference.md +122 -45
- package/skills/incanto-physics-and-input.md +67 -5
- package/skills/incanto-scene-json-authoring.md +37 -1
- package/skills/incanto-verifying-your-game.md +19 -2
- package/templates-app/beacon-isle-3d/PROJECT/Status.md +8 -0
- package/templates-app/beacon-isle-3d/PROJECT/Structure.md +3 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/src/game.scene.json +512 -184
- package/templates-app/beacon-isle-3d/verify.ts +144 -0
- package/templates-app/molehill-2d/package.json +1 -1
- package/templates-app/platformer-2d/PROJECT/Status.md +7 -0
- package/templates-app/platformer-2d/PROJECT/Structure.md +3 -0
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/platformer-2d/src/game.scene.json +319 -93
- package/templates-app/platformer-2d/verify.ts +54 -0
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/star-survivor/src/game.scene.json +18 -9
- package/templates-app/tps-3d/PROJECT/Context.md +1 -1
- package/templates-app/tps-3d/PROJECT/Status.md +40 -1
- package/templates-app/tps-3d/PROJECT/Structure.md +19 -0
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/tps-3d/src/behaviors.ts +9 -0
- package/templates-app/tps-3d/src/cover.scene.json +26 -0
- package/templates-app/tps-3d/src/game.scene.json +379 -80
- package/templates-app/tps-3d/src/main.ts +14 -0
- package/templates-app/tps-3d/src/pillar.scene.json +25 -0
- package/templates-app/tps-3d/verify.ts +582 -3
- package/templates-app/village-quest-3d/package.json +1 -1
- package/templates-app/village-quest-3d/src/grove.scene.json +98 -46
- package/templates-app/village-quest-3d/src/village.scene.json +449 -223
|
@@ -103,7 +103,11 @@ Rules the engine enforces with **hard errors** (it never warns silently):
|
|
|
103
103
|
On export, default-equal values are omitted automatically.
|
|
104
104
|
3. Prop keys and value kinds are validated against the type's schema:
|
|
105
105
|
unknown key → `UNKNOWN_PROP` (message lists valid keys); wrong JSON kind
|
|
106
|
-
(e.g. string where the default is boolean) → `PROP_TYPE_MISMATCH`.
|
|
106
|
+
(e.g. string where the default is boolean) → `PROP_TYPE_MISMATCH`. A prop
|
|
107
|
+
whose default is `null` means AUTO — the engine decides — and validates the
|
|
108
|
+
other kinds it declares (`drape`/`collide`/`islandEdge`/`Chase.ground` take
|
|
109
|
+
a boolean, `snapToGround` a boolean or a lift in metres, `reflectivity` a
|
|
110
|
+
number); the editor offers the boolean ones as auto / on / off.
|
|
107
111
|
A few props accept TWO kinds — `Flowers3D.density` takes a preset name or
|
|
108
112
|
plants per m², `Water3D.underwater` takes `true`/`false` or a settings
|
|
109
113
|
object — and `incanto-node-reference.md` names both in its Kind column
|
|
@@ -398,6 +402,37 @@ that do exist at the failing spot).
|
|
|
398
402
|
- Current limitation: exporting expands instances into full trees (the `instance` reference is
|
|
399
403
|
not preserved on export yet).
|
|
400
404
|
- Cycles (`a` instances `b` instances `a`) and missing resolvers → `UNRESOLVED_INSTANCE`.
|
|
405
|
+
- A placement's props go in `overrides`. `props` on an `instance:` node is a
|
|
406
|
+
hard `BAD_FORMAT` error — it used to be accepted and read by nothing, so a
|
|
407
|
+
position written there was silently the sub-scene's own.
|
|
408
|
+
|
|
409
|
+
### Giving the loader the sub-scenes (the half that is not JSON)
|
|
410
|
+
|
|
411
|
+
`loadScene` never reads files: it asks `resolveScene(path)` for the JSON behind
|
|
412
|
+
an `instance:` string, synchronously, and without one a scene with a prefab in
|
|
413
|
+
it does not load. Every CLI (`incanto-check`, `-playtest`, `-verify`, `-feel`,
|
|
414
|
+
`-play`) passes one already, resolved against the SCENE's own folder — your
|
|
415
|
+
game and your harness are the two places you write it yourself:
|
|
416
|
+
|
|
417
|
+
```ts
|
|
418
|
+
// main.ts — vite. Every *.scene.json beside this file, keyed by the path an
|
|
419
|
+
// `instance:` names.
|
|
420
|
+
const prefabs = import.meta.glob('./*.scene.json', { eager: true, import: 'default' });
|
|
421
|
+
const resolveScene = (path: string): unknown => prefabs[`./${path}`] ?? null;
|
|
422
|
+
await createGame2D({ canvas, scene: sceneJson, resolveScene });
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
```ts
|
|
426
|
+
// verify.ts — bun, no bundler: import the prefab and hand it over by path.
|
|
427
|
+
import crateJson from './src/crate.scene.json';
|
|
428
|
+
const resolveScene = (path: string) => (path === 'crate.scene.json' ? crateJson : null);
|
|
429
|
+
await runScript(sceneJson, { durationMs: 4000, resolveScene, steps: [...] });
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
`examples/tiles-2d` is the worked example in 2D: two crates that ARE
|
|
433
|
+
`crate.scene.json`, one of them adding a rope child of its own. `examples/tps-3d`
|
|
434
|
+
is the 3D one: the arena's cover blocks and pillars are `cover.scene.json` and
|
|
435
|
+
`pillar.scene.json`, placed with a `position` override each.
|
|
401
436
|
|
|
402
437
|
## Error codes you will see (all hard failures at load)
|
|
403
438
|
|
|
@@ -417,6 +452,7 @@ that do exist at the failing spot).
|
|
|
417
452
|
| `UNKNOWN_SIGNAL` | connection (or emit/on) names a signal the from node never declares | use a declared signal, or declare it (`static signals` / `declareSignal`) |
|
|
418
453
|
| `UNKNOWN_BEHAVIOR` | `script.name` not registered | `registerBehavior(name, Class)` before `loadScene` |
|
|
419
454
|
| `UNRESOLVED_INSTANCE` | no resolver, unknown path, or instance cycle | provide/fix `resolveScene`, break the cycle |
|
|
455
|
+
| `WRONG_DIMENSION` | a `*3D` node in a 2D scene (or the reverse), or `createGame2D` given a 3D scene | use the matching node type / the matching `createGame*` |
|
|
420
456
|
| `DUPLICATE_NODE_TYPE` | two classes registered under one type name | rename one type, or `{ replace: true }` for hot reload |
|
|
421
457
|
| `DUPLICATE_BEHAVIOR` | two classes registered under one behavior name | rename one, or `{ replace: true }` for hot reload |
|
|
422
458
|
| `TREE_VIOLATION` | invalid name, re-parenting without detach, cycles, double root | follow the rule in the message |
|
|
@@ -41,6 +41,10 @@ $ bunx incanto verify # finds your scene AND your behaviou
|
|
|
41
41
|
passes what was measured — plays, draws not measured.
|
|
42
42
|
next: nothing here is broken — a win that takes skill or a sequence is out of reach of random play. Judge it with a scripted run: `bun run verify`
|
|
43
43
|
```
|
|
44
|
+
`--runs N` gives the `plays` rung more seeds (default 8). Eight see a one-in-eight event
|
|
45
|
+
64% of the time; `bun run sweep` asks the six shipped starters for sixteen, and a starter that
|
|
46
|
+
falls out of the world once in twelve runs is how the arena in tps-3d got its `Respawn`.
|
|
47
|
+
|
|
44
48
|
|
|
45
49
|
### `agrees` — do two clients hold the same values?
|
|
46
50
|
|
|
@@ -72,7 +76,10 @@ encodes so you do not have to remember them:
|
|
|
72
76
|
warned about is printed under it with a `!` — `loads` runs `incanto-check`,
|
|
73
77
|
and the ladder used to read only whether it passed and drop the warnings, so a
|
|
74
78
|
scene the check describes as "It will render black" came back as
|
|
75
|
-
`✓ loads — the scene is legal and its assets resolve
|
|
79
|
+
`✓ loads — the scene is legal and its assets resolve` (LOCAL art is looked for on
|
|
80
|
+
disk; REMOTE urls are asked with a HEAD request — a 404 drops the claim to
|
|
81
|
+
`the scene is legal`, and a host that cannot be reached is a `note:`, never a
|
|
82
|
+
failure);
|
|
76
83
|
- an **unmeasured** rung (`?`) is not a failure. "No dev server" means the
|
|
77
84
|
question was never asked; treating that as a broken game sends you editing a
|
|
78
85
|
scene that is fine;
|
|
@@ -218,7 +225,7 @@ const result = await runScript(sceneJson, {
|
|
|
218
225
|
durationMs: 3000,
|
|
219
226
|
seed: 42, // same seed → identical run
|
|
220
227
|
steps: [
|
|
221
|
-
{ atMs: 0, vector: ['move', 1, 0] }, // hold right
|
|
228
|
+
{ atMs: 0, vector: ['move', 1, 0] }, // hold right (y is DOWN: forward is [0, -1])
|
|
222
229
|
{ atMs: 1000, press: 'jump' },
|
|
223
230
|
{ atMs: 1100, release: 'jump' },
|
|
224
231
|
{ atMs: 1500, label: 'jump apex reached',
|
|
@@ -252,6 +259,16 @@ captures; `result.logs` holds everything behaviors logged via `this.log`.
|
|
|
252
259
|
Steps that never execute (atMs beyond the run) are reported as failures —
|
|
253
260
|
an assert cannot "pass" by not running.
|
|
254
261
|
|
|
262
|
+
**A game that has ended does not advance.** `GameFlow` stops the clock
|
|
263
|
+
(`timeScale 0`) on a win or a loss, and a pause does the same; after that every
|
|
264
|
+
`ctx.engine.step()` is a no-op and every value you read is the last one before
|
|
265
|
+
it stopped. A harness that lost its player three times inside one `do:` then
|
|
266
|
+
measured `0.00` for everything after it. The report now names each `do:`/`assert:`
|
|
267
|
+
step that ran with the clock stopped (`! at 4000ms [measure apex]: the clock
|
|
268
|
+
was stopped …`, also `result.stalled`) — read that line before reading the
|
|
269
|
+
zeros. Measure before the game ends, or `restartScene` / read `Flow.state` in
|
|
270
|
+
the step.
|
|
271
|
+
|
|
255
272
|
Note: `validateScene`/`runScript` register node types and your `behaviors`
|
|
256
273
|
into the process-global registries (hot-replacing same names). In a test
|
|
257
274
|
suite, isolate with `clearRegistry()`/`clearBehaviors()` between files if
|
|
@@ -36,3 +36,11 @@
|
|
|
36
36
|
|
|
37
37
|
- Boss attack telegraphs (charge-up glow, ground slam particles).
|
|
38
38
|
- A hurt/attack clip for shades once one lands in the catalog.
|
|
39
|
+
|
|
40
|
+
## This round's surfaces, on the island (2026-09-04)
|
|
41
|
+
|
|
42
|
+
`Pad` (StaticBody3D, `restitution 1`, `snapToGround: 0.1`) with a dead `Ball` dropped on it,
|
|
43
|
+
and `Walker` (CharacterBody3D + `Chase` on a child, `slopeLimitDeg 50`, `stepHeight 0.5`) on
|
|
44
|
+
the west slope, `loseRange 25` so it never joins the quest. `verify.ts` measures the rebound
|
|
45
|
+
(2.4 m of 3), the chase up the slope (8.5 m of 10, +1.75 m) and that the walker stays on the
|
|
46
|
+
terrain (0.97 m over `heightAt`).
|
|
@@ -22,3 +22,6 @@ verify.ts audit + quest E2E + hunt + death/respawn + replay
|
|
|
22
22
|
keeps lit wards; `IsleDirector.onReady` re-applies their glow.
|
|
23
23
|
- The whole Terrain subtree is static EXCEPT Sea and Clouds (auditScene
|
|
24
24
|
catches the freeze-the-water mistake if you regress this).
|
|
25
|
+
|
|
26
|
+
- `Pad`, `Ball`, `Walker` — the harness's fixtures for a trampoline and a ground chaser on the
|
|
27
|
+
heightfield.
|