incanto 0.63.1 → 0.64.1

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 (37) hide show
  1. package/dist/2d.js +3 -3
  2. package/dist/3d.js +4 -4
  3. package/dist/{create-game-BsqKOAFN.js → create-game-B1KM6dA6.js} +3 -3
  4. package/dist/{create-game-CSnlQDkz.js → create-game-B746rYbr.js} +3 -3
  5. package/dist/{environment-presets-BKRo-HXg.js → environment-presets-D2vzw583.js} +1 -1
  6. package/dist/{gameplay-Dqm4LyKR.js → gameplay-CLgFdkh5.js} +31 -0
  7. package/dist/gameplay.d.ts +23 -0
  8. package/dist/gameplay.js +1 -1
  9. package/dist/index.js +1 -1
  10. package/dist/{physics-2d-BUD-MADM.js → physics-2d-BPJcJRRP.js} +1 -1
  11. package/dist/{physics-3d-BsutZCtX.js → physics-3d-BOO58xzw.js} +2 -2
  12. package/dist/react.js +1 -1
  13. package/dist/{register-BSA93acW.js → register-dGsbnJ87.js} +1 -1
  14. package/dist/{src-DQzZD_gx.js → src-CNS2xQB1.js} +1 -1
  15. package/dist/{test-wPUuuJpP.js → test-Ccob3X5i.js} +7 -7
  16. package/dist/test.js +1 -1
  17. package/dist/vite.js +2 -2
  18. package/editor/assets/{agent8-CfacwdPM.js → agent8-Di-UEn5O.js} +1 -1
  19. package/editor/assets/{debug-D0kX3cGf.js → debug-DWztJ5_y.js} +1 -1
  20. package/editor/assets/{index-BrG3srCa.js → index-fct4H89G.js} +2 -2
  21. package/editor/index.html +1 -1
  22. package/package.json +1 -1
  23. package/skills/incanto-gameplay-behaviors.md +20 -4
  24. package/skills/incanto-node-reference.md +1 -1
  25. package/skills/incanto-your-first-game.md +11 -3
  26. package/templates-app/beacon-isle-3d/coverage.json +9 -0
  27. package/templates-app/beacon-isle-3d/package.json +1 -1
  28. package/templates-app/platformer-2d/coverage.json +5 -0
  29. package/templates-app/platformer-2d/package.json +1 -1
  30. package/templates-app/star-survivor/coverage.json +5 -0
  31. package/templates-app/star-survivor/package.json +1 -1
  32. package/templates-app/tps-3d/coverage.json +5 -0
  33. package/templates-app/tps-3d/package.json +1 -1
  34. package/templates-app/tps-3d/src/game.scene.json +7 -1
  35. package/templates-app/village-quest-3d/coverage.json +9 -0
  36. package/templates-app/village-quest-3d/package.json +1 -1
  37. package/templates-app/village-quest-3d/src/village.scene.json +4 -0
package/editor/index.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Incanto Scene Editor</title>
7
7
  <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><rect width='16' height='16' rx='3' fill='%236ee7dc'/><text x='8' y='12' text-anchor='middle' font-size='11' font-family='monospace' fill='%230e1018'>i</text></svg>" />
8
- <script type="module" crossorigin src="./assets/index-BrG3srCa.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-fct4H89G.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="./assets/GameServer-C56iOUgF.js">
10
10
  </head>
11
11
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incanto",
3
- "version": "0.63.1",
3
+ "version": "0.64.1",
4
4
  "description": "Vibe-coding-first web game engine SDK — JSON-driven scenes on three.js",
5
5
  "keywords": [
6
6
  "game-engine",
@@ -90,8 +90,8 @@ a connection `to` the root is `/root` (or `.`), never `/root/Game`.
90
90
 
91
91
  Hit points with regen and post-hit invulnerability (i-frames). The universal
92
92
  "can be hurt / can die" behavior. Hurt it via `damage(n)` (e.g. from
93
- `DamageOnContact`); heal/kill via `heal(n)` / `kill()`. Clamps to `0..max`,
94
- dies once.
93
+ `DamageOnContact`); heal/kill via `heal(n)` / `kill()`; bring it back with
94
+ `revive(hp?)`. Clamps to `0..max`.
95
95
 
96
96
  | Prop | Default | Meaning |
97
97
  |---|---|---|
@@ -101,8 +101,24 @@ dies once.
101
101
  | `freeOnDeath` | `false` | `queueFree()` this node when it dies (clone-safe) |
102
102
 
103
103
  Signals: `damaged(amount, current)` · `healed(amount, current)` ·
104
- `healthChanged(current, max)` · `died`
105
- Methods: `damage(n)` · `heal(n)` · `kill()` — state: `current`, `isDead`
104
+ `healthChanged(current, max)` · `died` · `revived(current)`
105
+ Methods: `damage(n)` · `heal(n)` · `kill()` · `revive(hp?)` — state: `current`,
106
+ `isDead`
107
+
108
+ **A dead Health STAYS dead until you revive it.** `damage`, `heal` and regen all
109
+ no-op once it has died — which is what makes a lives system work at all, and
110
+ what breaks one that forgets the other half:
111
+
112
+ ```json
113
+ { "signal": "died", "from": "Player", "to": "Score", "handler": "loseLife" },
114
+ { "signal": "lifeLost", "from": "Score", "to": "Player", "handler": "revive" }
115
+ ```
116
+
117
+ Without the second wire the player is a walking corpse after the first death —
118
+ full HP bar, immune to every enemy, `died` never firing again, lives frozen, and
119
+ the game quietly unlosable, with every check green. `revive()` comes back at
120
+ `max` (or the hp you pass), re-arms the i-frames, and does nothing at all to
121
+ someone who never died.
106
122
 
107
123
  **`healthChanged` is the one to put on a health BAR.** `damaged`/`healed` lead
108
124
  with the DELTA, so wiring either to `UiBar.setValue` paints the damage as the
@@ -1438,7 +1438,7 @@ Signals: `flowChanged`
1438
1438
  | `invulnerableFor` | `0` | number |
1439
1439
  | `freeOnDeath` | `false` | boolean |
1440
1440
 
1441
- Signals: `damaged(amount, current)` · `healed(amount, current)` · `died` · `healthChanged`
1441
+ Signals: `damaged(amount, current)` · `healed(amount, current)` · `died` · `revived` · `healthChanged`
1442
1442
 
1443
1443
  ### `Interactable`
1444
1444
 
@@ -82,12 +82,19 @@ and it is entirely JSON.
82
82
 
83
83
  ```jsonc
84
84
  "connections": [
85
- { "signal": "died", "from": "Player", "to": "Score", "handler": "loseLife" },
86
- { "signal": "won", "from": "Score", "to": "Flow", "handler": "win" },
87
- { "signal": "lost", "from": "Score", "to": "Flow", "handler": "gameOver" }
85
+ { "signal": "died", "from": "Player", "to": "Score", "handler": "loseLife" },
86
+ { "signal": "lifeLost", "from": "Score", "to": "Player", "handler": "revive" },
87
+ { "signal": "won", "from": "Score", "to": "Flow", "handler": "win" },
88
+ { "signal": "lost", "from": "Score", "to": "Flow", "handler": "gameOver" }
88
89
  ]
89
90
  ```
90
91
 
92
+ **`lifeLost → revive` is not optional.** A `Health` that has died stays dead:
93
+ `damage`, `heal` and regen all stop, so without that wire the player becomes a
94
+ walking corpse after the first death — full HP bar, immune to everything,
95
+ `died` never firing again, lives frozen, and the game quietly unlosable. It
96
+ looks fine from every check.
97
+
91
98
  `GameFlow` freezes `engine.timeScale`, shows a sticky banner, and waits for the
92
99
  `restart` action. **Give the Flow its own node** — a node holds one behavior and
93
100
  your root probably already has the game's director script.
@@ -212,6 +219,7 @@ Things that cost real time, in the order you will meet them.
212
219
 
213
220
  | when | the trap |
214
221
  | --- | --- |
222
+ | a game with LIVES | `died` stops a `Health` for good — wire `lifeLost → revive` or you can spend only one. |
215
223
  | wiring a score | `died` carries nothing; `addScore(n)` wants one → `NaN`. Wire `dealtDamage` from the killer. |
216
224
  | enemies feel harmless | `repeatEvery` on the contact hitbox, or one hit is all you get. |
217
225
  | enemies never arrive | a chaser cannot climb — `stepHeight`, and it loses to a large downward velocity you apply yourself. |
@@ -0,0 +1,9 @@
1
+ {
2
+ "hurt": {
3
+ "onto": "%Shade1_1"
4
+ },
5
+ "lose": {
6
+ "skip": "no fail state by design \u2014 `onPlayerDown` shows a banner and reloads the level after 1.6s"
7
+ },
8
+ "seconds": 20
9
+ }
@@ -14,7 +14,7 @@
14
14
  "@dimforge/rapier2d-compat": "0.19.3",
15
15
  "@dimforge/rapier3d-compat": "0.19.3",
16
16
  "@pixiv/three-vrm": "^3.5.3",
17
- "incanto": "^0.63.1",
17
+ "incanto": "^0.64.1",
18
18
  "three": "^0.184.0"
19
19
  },
20
20
  "devDependencies": {
@@ -0,0 +1,5 @@
1
+ {
2
+ "hurt": { "onto": "%Spikes1" },
3
+ "lose": true,
4
+ "seconds": 20
5
+ }
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@dimforge/rapier2d-compat": "0.19.3",
14
- "incanto": "^0.63.1",
14
+ "incanto": "^0.64.1",
15
15
  "three": "^0.184.0"
16
16
  },
17
17
  "devDependencies": {
@@ -0,0 +1,5 @@
1
+ {
2
+ "hurt": "afk",
3
+ "lose": true,
4
+ "seconds": 30
5
+ }
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@dimforge/rapier2d-compat": "0.19.3",
14
- "incanto": "^0.63.1",
14
+ "incanto": "^0.64.1",
15
15
  "three": "^0.184.0"
16
16
  },
17
17
  "devDependencies": {
@@ -0,0 +1,5 @@
1
+ {
2
+ "hurt": "afk",
3
+ "lose": true,
4
+ "seconds": 30
5
+ }
@@ -13,7 +13,7 @@
13
13
  "@dimforge/rapier2d-compat": "0.19.3",
14
14
  "@dimforge/rapier3d-compat": "0.19.3",
15
15
  "@pixiv/three-vrm": "^3.5.3",
16
- "incanto": "^0.63.1",
16
+ "incanto": "^0.64.1",
17
17
  "three": "^0.184.0"
18
18
  },
19
19
  "devDependencies": {
@@ -96,7 +96,7 @@
96
96
  "script": {
97
97
  "name": "ScoreKeeper",
98
98
  "props": {
99
- "lives": 1
99
+ "lives": 3
100
100
  }
101
101
  },
102
102
  "children": [
@@ -718,6 +718,12 @@
718
718
  "to": "/root",
719
719
  "handler": "loseLife"
720
720
  },
721
+ {
722
+ "signal": "lifeLost",
723
+ "from": "/root",
724
+ "to": "Player",
725
+ "handler": "revive"
726
+ },
721
727
  {
722
728
  "signal": "damaged",
723
729
  "from": "Player",
@@ -0,0 +1,9 @@
1
+ {
2
+ "hurt": {
3
+ "onto": "%Wolf1"
4
+ },
5
+ "lose": {
6
+ "skip": "no fail state by design \u2014 `onPlayerDown` shows a banner and reloads the level after 1.6s"
7
+ },
8
+ "seconds": 20
9
+ }
@@ -13,7 +13,7 @@
13
13
  "@dimforge/rapier2d-compat": "0.19.3",
14
14
  "@dimforge/rapier3d-compat": "0.19.3",
15
15
  "@pixiv/three-vrm": "^3.5.3",
16
- "incanto": "^0.63.1",
16
+ "incanto": "^0.64.1",
17
17
  "three": "^0.184.0"
18
18
  },
19
19
  "devDependencies": {
@@ -80,6 +80,10 @@
80
80
  "restart": {
81
81
  "type": "button",
82
82
  "keys": ["KeyR"]
83
+ },
84
+ "pause": {
85
+ "type": "button",
86
+ "keys": ["Escape"]
83
87
  }
84
88
  },
85
89
  "assets": {