incanto 0.12.0 → 0.14.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.
Files changed (83) hide show
  1. package/README.md +22 -0
  2. package/bin/incanto-new.mjs +87 -0
  3. package/dist/2d.d.ts +2 -2
  4. package/dist/2d.js +3 -3
  5. package/dist/3d.d.ts +219 -82
  6. package/dist/3d.js +74 -4
  7. package/dist/{behavior-Bod1AyJS.d.ts → behavior-CPibUfnH.d.ts} +4 -2
  8. package/dist/{create-game-C_xf4gm9.js → create-game-Ct86zczq.js} +5 -5
  9. package/dist/{create-game-B2fewJUy.js → create-game-OSntcIiM.js} +5 -5
  10. package/dist/debug.d.ts +1 -1
  11. package/dist/{duplicate-BEvGBtb_.js → duplicate-BINwP0WG.js} +1 -1
  12. package/dist/{gameplay-Dn3yidJw.js → gameplay-sSqrUcnz.js} +75 -3
  13. package/dist/gameplay.d.ts +37 -2
  14. package/dist/gameplay.js +2 -2
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.js +4 -4
  17. package/dist/{loader-B4OEXDZ8.js → loader-BZqOKfI2.js} +3 -1
  18. package/dist/{loader-BcUDfNHn.d.ts → loader-DILt9PGC.d.ts} +1 -1
  19. package/dist/net.d.ts +1 -1
  20. package/dist/net.js +3 -3
  21. package/dist/{pathfinding-BSiXjd6W.d.ts → pathfinding-RWYkNKx9.d.ts} +1 -1
  22. package/dist/{physics-2d-B6D864oZ.js → physics-2d-BiIdl51r.js} +2 -2
  23. package/dist/{physics-3d-RLNaxRyw.js → physics-3d-D_kUdOjr.js} +2 -2
  24. package/dist/react.d.ts +1 -1
  25. package/dist/react.js +1 -1
  26. package/dist/{register-Cwc-yCYx.js → register-BFFE1Mh1.js} +2 -2
  27. package/dist/{register-ysLR3WQS.js → register-C9-16x_t.js} +562 -157
  28. package/dist/{register-BD6zgrv_.js → register-Djwckzgx.js} +2 -2
  29. package/dist/{register-DJZXxwAn.js → register-nObreUQR.js} +1 -1
  30. package/dist/test.d.ts +2 -2
  31. package/dist/test.js +10 -10
  32. package/editor/assets/{agent8-D_4QY8Aq.js → agent8-BDC4LhjC.js} +1 -1
  33. package/editor/assets/{index-s0DZuroe.js → index-7qOYg7t8.js} +74 -74
  34. package/editor/index.html +1 -1
  35. package/package.json +4 -2
  36. package/schemas/scene.schema.json +266 -6
  37. package/skills/incanto-3d-character.md +35 -0
  38. package/skills/incanto-building-3d-games.md +48 -0
  39. package/skills/incanto-environment.md +15 -16
  40. package/skills/incanto-gameplay-behaviors.md +23 -1
  41. package/skills/incanto-node-reference.md +54 -3
  42. package/templates-app/beacon-isle-3d/PROJECT/Context.md +44 -0
  43. package/templates-app/beacon-isle-3d/PROJECT/Requirements.md +16 -0
  44. package/templates-app/beacon-isle-3d/PROJECT/Status.md +38 -0
  45. package/templates-app/beacon-isle-3d/PROJECT/Structure.md +24 -0
  46. package/templates-app/beacon-isle-3d/docs/project-3d-rules.md +38 -0
  47. package/templates-app/beacon-isle-3d/generate-world.ts +812 -0
  48. package/templates-app/beacon-isle-3d/index.html +68 -0
  49. package/templates-app/beacon-isle-3d/package.json +26 -0
  50. package/templates-app/beacon-isle-3d/src/behaviors.ts +570 -0
  51. package/templates-app/beacon-isle-3d/src/game.scene.json +2969 -0
  52. package/templates-app/beacon-isle-3d/src/main.ts +33 -0
  53. package/templates-app/beacon-isle-3d/tsconfig.json +13 -0
  54. package/templates-app/beacon-isle-3d/verify.ts +285 -0
  55. package/templates-app/beacon-isle-3d/vite.config.ts +5 -0
  56. package/templates-app/tps-3d/PROJECT/Context.md +49 -0
  57. package/templates-app/tps-3d/PROJECT/Requirements.md +38 -0
  58. package/templates-app/tps-3d/PROJECT/Status.md +41 -0
  59. package/templates-app/tps-3d/PROJECT/Structure.md +44 -0
  60. package/templates-app/tps-3d/docs/project-3d-rules.md +38 -0
  61. package/templates-app/tps-3d/index.html +244 -0
  62. package/templates-app/tps-3d/package.json +25 -0
  63. package/templates-app/tps-3d/src/behaviors.ts +405 -0
  64. package/templates-app/tps-3d/src/game.scene.json +677 -0
  65. package/templates-app/tps-3d/src/main.ts +64 -0
  66. package/templates-app/tps-3d/tsconfig.json +13 -0
  67. package/templates-app/tps-3d/verify.ts +167 -0
  68. package/templates-app/tps-3d/vite.config.ts +5 -0
  69. package/templates-app/village-quest-3d/PROJECT/Context.md +39 -0
  70. package/templates-app/village-quest-3d/PROJECT/Requirements.md +36 -0
  71. package/templates-app/village-quest-3d/PROJECT/Status.md +26 -0
  72. package/templates-app/village-quest-3d/PROJECT/Structure.md +30 -0
  73. package/templates-app/village-quest-3d/docs/project-3d-rules.md +38 -0
  74. package/templates-app/village-quest-3d/index.html +68 -0
  75. package/templates-app/village-quest-3d/package.json +25 -0
  76. package/templates-app/village-quest-3d/src/behaviors.ts +529 -0
  77. package/templates-app/village-quest-3d/src/grove.scene.json +826 -0
  78. package/templates-app/village-quest-3d/src/main.ts +35 -0
  79. package/templates-app/village-quest-3d/src/quest.ts +18 -0
  80. package/templates-app/village-quest-3d/src/village.scene.json +680 -0
  81. package/templates-app/village-quest-3d/tsconfig.json +13 -0
  82. package/templates-app/village-quest-3d/verify.ts +254 -0
  83. package/templates-app/village-quest-3d/vite.config.ts +5 -0
@@ -144,6 +144,24 @@ Signals: `finished`
144
144
  | `target` | `""` | string |
145
145
  | `bone` | `""` | string |
146
146
 
147
+ ## `BoneLookAt3D` — `incanto/3d`
148
+
149
+ | Prop | Default | Kind |
150
+ |---|---|---|
151
+ | `position` | `[0,0,0]` | array |
152
+ | `rotation` | `[0,0,0]` | array |
153
+ | `static` | `false` | boolean |
154
+ | `scale` | `[1,1,1]` | array |
155
+ | `visible` | `true` | boolean |
156
+ | `renderOrder` | `0` | number |
157
+ | `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
158
+ | `target` | `""` | string |
159
+ | `bone` | `"Head"` | string |
160
+ | `lookAt` | `""` | string |
161
+ | `maxAngleDeg` | `75` | number |
162
+ | `weight` | `0.85` | number |
163
+ | `forwardAxis` | `"+z"` | one of: `+x` `-x` `+y` `-y` `+z` `-z` |
164
+
147
165
  ## `Camera2D` — `incanto/2d`
148
166
 
149
167
  | Prop | Default | Kind |
@@ -312,7 +330,7 @@ Signals: `movementStateChanged(state)`
312
330
  | `height` | `0.45` | number |
313
331
  | `clustering` | `0.6` | number |
314
332
  | `sway` | `0.5` | number |
315
- | `drape` | `false` | boolean |
333
+ | `drape` | `null` | null |
316
334
  | `terrain` | `""` | string |
317
335
 
318
336
  ## `Foliage3D` — `incanto/3d`
@@ -344,7 +362,7 @@ Signals: `movementStateChanged(state)`
344
362
  | `coverage` | `0.85` | number |
345
363
  | `flowers` | `0` | number |
346
364
  | `seed` | `1` | number |
347
- | `drape` | `false` | boolean |
365
+ | `drape` | `null` | null |
348
366
  | `terrain` | `""` | string |
349
367
 
350
368
  ## `HudLayer` — `incanto`
@@ -354,6 +372,24 @@ Signals: `movementStateChanged(state)`
354
372
  | `zIndex` | `100` | number |
355
373
  | `visible` | `true` | boolean |
356
374
 
375
+ ## `InstancedMesh3D` — `incanto/3d`
376
+
377
+ | Prop | Default | Kind |
378
+ |---|---|---|
379
+ | `position` | `[0,0,0]` | array |
380
+ | `rotation` | `[0,0,0]` | array |
381
+ | `static` | `false` | boolean |
382
+ | `scale` | `[1,1,1]` | array |
383
+ | `visible` | `true` | boolean |
384
+ | `renderOrder` | `0` | number |
385
+ | `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
386
+ | `mesh` | `"box"` | one of: `box` `sphere` `capsule` `plane` `cylinder` `gem` |
387
+ | `size` | `[1,1,1]` | array |
388
+ | `material` | `{}` | object |
389
+ | `transforms` | `[]` | array |
390
+ | `castShadow` | `false` | boolean |
391
+ | `receiveShadow` | `false` | boolean |
392
+
357
393
  ## `Joint2D` — `incanto/2d`
358
394
 
359
395
  | Prop | Default | Kind |
@@ -460,6 +496,9 @@ Signals: `movementStateChanged(state)`
460
496
  | `targetHeight` | `0` | number |
461
497
  | `castShadow` | `false` | boolean |
462
498
  | `animationLoop` | `true` | boolean |
499
+ | `animationUpper` | `""` | string |
500
+ | `animationUpperLoop` | `false` | boolean |
501
+ | `upperBodyRoot` | `"Spine"` | string |
463
502
  | `receiveShadow` | `false` | boolean |
464
503
  | `tint` | `""` | string |
465
504
  | `metalness` | `-1` | number |
@@ -797,7 +836,7 @@ Signals: `timeout`
797
836
  | `leafFadeStart` | `0` | number |
798
837
  | `leafFadeEnd` | `0` | number |
799
838
  | `leafShadows` | `true` | boolean |
800
- | `drape` | `false` | boolean |
839
+ | `drape` | `null` | null |
801
840
  | `terrain` | `""` | string |
802
841
 
803
842
  ## `UILayer` — `incanto/2d`
@@ -961,6 +1000,18 @@ Signals: `totalChanged(total)`
961
1000
 
962
1001
  Signals: `dealtDamage(amount, target)`
963
1002
 
1003
+ ### `DayNight`
1004
+
1005
+ | Prop | Default | Kind |
1006
+ |---|---|---|
1007
+ | `daySeconds` | `240` | number |
1008
+ | `startHour` | `10` | number |
1009
+ | `maxSunElevationDeg` | `55` | number |
1010
+ | `nightDarkness` | `0.75` | number |
1011
+ | `paused` | `false` | boolean |
1012
+
1013
+ Signals: `dayPhaseChanged`
1014
+
964
1015
  ### `FollowCamera`
965
1016
 
966
1017
  | Prop | Default | Kind |
@@ -0,0 +1,44 @@
1
+ # Beacon Isle — Context
2
+
3
+ **The incanto 3D template.** A complete island action-adventure vertical
4
+ slice designed to be COPIED as the starting point for 3D vibe-coding: a
5
+ generated world, a real quest loop, enemies with terrain-aware AI, readable
6
+ combat, win AND lose states, mobile controls, and a headless verify harness —
7
+ all in ~2 files of game code.
8
+
9
+ ## What it plays like
10
+
11
+ You wash up on a golden-hour island. The lighthouse keeper (walk up, **E**)
12
+ asks you to relight three ancient wards. Shades — floating wraiths with
13
+ burning eyes — patrol each ward and HUNT you across the island surface when
14
+ you come close. Cut them down (**click/F**, a real melee swing with the sword
15
+ riding your hand bone), stand at the dark crystal and press **E**: it blazes
16
+ back to life. Three lit wards → report back → fireworks over the lighthouse.
17
+ The shades bite; at 0 HP the isle takes you and you respawn — lit wards stay lit.
18
+
19
+ ## The template story (why it's built this way)
20
+
21
+ 1. **The world is GENERATED, the game is AUTHORED.** `bun run world` re-emits
22
+ `src/game.scene.json` from `generate-world.ts` (deterministic seeds):
23
+ island terrain, sea, tree groves, grass, flowers, and QUEST SITES picked on
24
+ provably walkable ground (the same `buildTerrainNav` grid the enemies use).
25
+ Change the seed → new island, game logic untouched.
26
+ 2. **Game code is two behaviors** (`IsleDirector`, `SwordStrike`); everything
27
+ else — movement/camera/animations, NPC proximity, dialogue, HUD, touch
28
+ controls, contact damage, physics — is engine surface declared in JSON.
29
+ 3. **Verified headlessly**: `bun run verify` plays the whole quest, proves the
30
+ shades hunt, proves death keeps progress, and replays recorded input
31
+ bit-identically.
32
+
33
+ ## Feature map (engine 0.12)
34
+
35
+ | Feature | Where |
36
+ |---|---|
37
+ | `generateTerrain` island + Water3D sea | generate-world.ts |
38
+ | `buildTerrainNav` + `findPath` | ward-site picking AND shade patrol/hunt AI |
39
+ | `BoneAttachment3D` | sword in the right hand |
40
+ | `environment.post` + bloom | golden-hour grade, glowing ward crystals |
41
+ | input-map `"touch"` keys | joystick + buttons on phones, zero code |
42
+ | `UiDialogue`/`UiBar`/`UiBanner` | keeper quest, HP, win/lose |
43
+ | `startVoice('wind')` | speed-reactive ambience |
44
+ | `startRecording`/`replay` | determinism regression in verify.ts |
@@ -0,0 +1,16 @@
1
+ # Beacon Isle — Requirements
2
+
3
+ 1. Quest arc: keeper dialogue (choice) → 3 wards guarded by shades → clear +
4
+ E to relight each → report back → win banner + fireworks.
5
+ 2. Shades: patrol rings AROUND their ward on the island surface; hunt the
6
+ player within 9 m (re-path through terrain, never through sea/cliffs);
7
+ bites drain 20 HP per 1.2 s of contact.
8
+ 3. Losing: 0 HP → banner → fresh respawn; lit wards persist.
9
+ 4. A dark ward with living guards refuses to light (hint line).
10
+ 5. One strike fells a shade (dissolve poof); the sword rides the hand bone
11
+ and plays the melee clip.
12
+ 6. Works on phones: joystick + jump/interact/attack touch buttons from the
13
+ input map alone.
14
+ 7. `bun run verify` green: audit 0 warnings, quest E2E, hunt proof,
15
+ death/respawn proof, bit-identical replay.
16
+ 8. `bun run world` regenerates the island deterministically.
@@ -0,0 +1,38 @@
1
+ # Beacon Isle — Status
2
+
3
+ ## Round 2 (2026-07-12)
4
+
5
+ - **The Shadeheart**: lighting the third ward summons a glowing violet
6
+ colossus (primitive-built — a keeper.glb attempt rendered at zero scale,
7
+ see Learnings below) that hunts the player across the island via the
8
+ terrain nav; five strikes (recoil + eye-flare per hit) fell it in a triple
9
+ burst; only then does the keeper's report end the quest.
10
+ - **The clock IS the quest** (paused DayNight, director-lerped `hour`):
11
+ dusk start → each lit ward buys back light → the boss drags the isle to a
12
+ deep-red horizon (17.8 — sun kept ABOVE the horizon; below it the
13
+ atmosphere sky and its IBL go black) → victory brings morning.
14
+ - **Gliding**: hold JUMP while falling — capped descent + dash trail.
15
+ - Keeper NPC tracks the player with `BoneLookAt3D`; shoreline rocks are one
16
+ `InstancedMesh3D` draw call.
17
+
18
+ ## Round 1 (2026-07-11)
19
+
20
+ - Full quest loop, terrain-nav shade AI, bone-mounted sword, golden-hour
21
+ grade, headless verify + replay determinism, 4-iteration visual pass.
22
+
23
+ ## Learnings
24
+
25
+ - `PathFollow` writes WORLD coordinates into `node.position` — such nodes
26
+ must be ROOT children. Parenting one under a positioned wrapper doubles
27
+ the offset ON SCREEN while all position-based gameplay math stays
28
+ self-consistent: invisible-boss bugs that verify green.
29
+ - keeper.glb mounts at a degenerate scale through ModelInstance3D's
30
+ targetHeight fit (the known "explicit scale" trap) — primitives with
31
+ emissive materials are the reliable monster path.
32
+ - Atmosphere rule: keep `elevationDeg` (or DayNight `hour`) sun-above-horizon
33
+ in playable scenes; the sky + IBL die within ~1° below.
34
+
35
+ ## Ideas next
36
+
37
+ - Boss attack telegraphs (charge-up glow, ground slam particles).
38
+ - A hurt/attack clip for shades once one lands in the catalog.
@@ -0,0 +1,24 @@
1
+ # Beacon Isle — Structure
2
+
3
+ ```
4
+ generate-world.ts the WORLD AUTHORING script (bun run world):
5
+ island terrain + sea + groves/grass/flowers +
6
+ quest sites on walkable ground → src/game.scene.json
7
+ index.html canvas + loading bar
8
+ src/main.ts preload → createGame3D
9
+ src/game.scene.json GENERATED — do not hand-edit; edit generate-world.ts
10
+ src/behaviors.ts IsleDirector (quest FSM, terrain-nav shade AI,
11
+ ward relighting, fireworks, respawn) + SwordStrike
12
+ verify.ts audit + quest E2E + hunt + death/respawn + replay
13
+ ```
14
+
15
+ ## Key decisions
16
+
17
+ - The nav grid is built ONCE in `IsleDirector.onReady` from the live
18
+ Terrain3D; shade hunts re-path every 0.4 s with `findPath` (cheap A*).
19
+ - Shades are primitive-built (capsule + gem hood + emissive eyes + Trail3D
20
+ wisp) — zero external meshes, instantly reskinnable.
21
+ - Quest state is a module singleton (`quest`) so death → `goToScene` respawn
22
+ keeps lit wards; `IsleDirector.onReady` re-applies their glow.
23
+ - The whole Terrain subtree is static EXCEPT Sea and Clouds (auditScene
24
+ catches the freeze-the-water mistake if you regress this).
@@ -0,0 +1,38 @@
1
+ <userRequest>
2
+ YOU MUST follow these rules EXACTLY when vibe-coding on this Incanto template:
3
+
4
+ 1. 📖 READ THE SKILLS FIRST: `node_modules/incanto/skills/` is the engine
5
+ manual, version-pinned to what is installed. Start with
6
+ `incanto-building-3d-games.md`, `incanto-3d-character.md`,
7
+ `incanto-gameplay-behaviors.md`, `incanto-environment.md` and
8
+ `incanto-audio.md` — this template composes all five.
9
+ 2. 🧱 STRUCTURE IS JSON: scenes, nodes, props, assets, input maps and
10
+ replication all live in `src/game.scene.json`. Add nodes there (or with
11
+ `npx incanto-editor`), NOT by constructing them ad-hoc in code.
12
+ 3. 🧠 LOGIC IS BEHAVIORS: gameplay code = small TypeScript Behavior classes,
13
+ registered with `registerBehavior('Name', Class)` and attached in JSON via
14
+ `"script": { "name": "Name" }`. Reach for a BUILT-IN gameplay behavior
15
+ (Health, Chase, WaveSpawner, DamageOnContact, ScoreKeeper…) before writing
16
+ your own — this game's only custom behaviors are `Shoot` and `HudUpdater`.
17
+ 4. 🔑 UIDS ARE GENERATED: every node uid comes from
18
+ `import { newUid } from 'incanto'`. NEVER invent readable uid strings.
19
+ 5. 📦 ASSETS ARE DECLARED: `assets` entries need `type` + `url`; reference
20
+ them as `"$key"`. Free extra key-values are preserved — use them to leave
21
+ notes for yourself (license, palette, source prompt).
22
+ 6. ⬆️ Y IS UP: 3D space is y-UP meters, +Z is "south", rotations are degrees
23
+ (Euler XYZ). Negative gravity falls.
24
+ 7. 🧲 COLLIDERS ARE PROPS: `"collider": { "shape": "box"|"sphere"|"capsule", … }`
25
+ on a body node — never child shape nodes. Wrong shapes hard-fail at load.
26
+ 8. 🖥️ THE HUD IS DOM, NOT NODES: 3D scenes have no 2D `UILayer`/`Label` nodes
27
+ (those are `incanto/2d`). The HUD + crosshair + banner are plain HTML in
28
+ `index.html`; `HudUpdater` writes the live numbers into them (guarded so
29
+ headless runs are a no-op).
30
+ 9. 🐛 DEBUG WHEN UNSURE: `physics.debugDraw = true` (the object
31
+ `enablePhysics3D` returns) draws every collider in the running game; or boot
32
+ with `?incanto_debug=1` for the live Explorer/Inspector/Stats overlay.
33
+ 10. 🎬 DELTA DISCIPLINE: only write props that differ from defaults — the
34
+ loader treats unknown/garbage props as hard errors, which is your friend.
35
+ 11. ✅ VERIFY LIKE A USER: `bun run check` validates the scene, `bun run verify`
36
+ proves the loop headlessly, then `bun run dev` and actually PLAY what you
37
+ changed (move, shoot, clear a wave) before declaring it done.
38
+ </userRequest>