incanto 0.68.0 → 0.69.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 (75) hide show
  1. package/assets/catalog.json +9 -5
  2. package/bin/incanto-assets.mjs +14 -1
  3. package/bin/incanto-check.mjs +53 -3
  4. package/bin/incanto-new.mjs +29 -1
  5. package/bin/incanto-serve.mjs +160 -0
  6. package/bin/incanto-verify.mjs +40 -0
  7. package/bin/incanto.mjs +1 -0
  8. package/dist/2d.d.ts +7 -5
  9. package/dist/2d.js +4 -4
  10. package/dist/3d.d.ts +4 -4
  11. package/dist/3d.js +7 -7
  12. package/dist/{audio-player-DOrq7sP-.d.ts → audio-player-C0j2k-yB.d.ts} +32 -13
  13. package/dist/{behavior-DoFPYrgo.d.ts → behavior-rm8vVzu_.d.ts} +67 -0
  14. package/dist/{create-game-DbWtVTxD.js → create-game-CvJ1wSRP.js} +13 -9
  15. package/dist/{create-game-IZIydDwI.js → create-game-CwxEDlCm.js} +13 -9
  16. package/dist/debug.d.ts +1 -1
  17. package/dist/{duplicate-IWIqk0HJ.js → duplicate-Dj4L-5AA.js} +1 -1
  18. package/dist/editor.js +1 -1
  19. package/dist/{environment-presets-CybQXNqS.js → environment-presets-BO-7XoFV.js} +4 -4
  20. package/dist/{frame-report-DCnHFmto.d.ts → frame-report-DNxDAb1w.d.ts} +8 -0
  21. package/dist/{frame-report-BSMny7oe.js → frame-report-Dlq13Gyj.js} +1 -0
  22. package/dist/{gameplay-DM1eu_cV.js → gameplay-D1KixWK8.js} +157 -151
  23. package/dist/gameplay.d.ts +1 -1
  24. package/dist/gameplay.js +1 -1
  25. package/dist/index.d.ts +4 -4
  26. package/dist/index.js +6 -6
  27. package/dist/{loader-BC4PNtJX.js → loader-DZE7B07H.js} +22 -6
  28. package/dist/{loader-CcB533FR.d.ts → loader-DadV2QCT.d.ts} +1 -1
  29. package/dist/net.d.ts +2 -2
  30. package/dist/net.js +1 -1
  31. package/dist/{physics-2d-B7Y6dPZO.js → physics-2d-CF5yyjbj.js} +2 -2
  32. package/dist/{physics-3d-bG3n70Ky.js → physics-3d-DbYaEcZy.js} +3 -3
  33. package/dist/react.d.ts +1 -1
  34. package/dist/react.js +1 -1
  35. package/dist/{register-ibCjm-wH.js → register-DbVArsns.js} +19 -10
  36. package/dist/{register-3ta-2Xig.js → register-mmfugpaQ.js} +107 -15
  37. package/dist/{replay-CYvhVHHN.js → replay-BEHLDcQV.js} +2 -2
  38. package/dist/{replay-Dvn8aeBd.d.ts → replay-BQfkX4x7.d.ts} +1 -1
  39. package/dist/{sheet-grid-BT6N_Bjs.js → sheet-grid-Cea343VO.js} +6 -2
  40. package/dist/{split-screen-CYwDkbLF.js → split-screen-CauMwu6y.js} +2 -2
  41. package/dist/{split-screen-DhrSzZIB.d.ts → split-screen-Cg76MCV5.d.ts} +2 -2
  42. package/dist/{src-D7RIqXYF.js → src-CYEu-_S9.js} +1 -1
  43. package/dist/{teardown-D2NEmxPB.js → teardown-CMqFVxO9.js} +5 -4
  44. package/dist/{test-8hoHeRmo.js → test-D6ISmuFE.js} +60 -17
  45. package/dist/test.d.ts +15 -4
  46. package/dist/test.js +2 -2
  47. package/dist/vite.d.ts +70 -2
  48. package/dist/vite.js +176 -14
  49. package/dist/{webgl-unavailable-N9nQqesw.js → webgl-unavailable-Z5_g8x9H.js} +12 -1
  50. package/editor/assets/{agent8-BrrHOjMJ.js → agent8-BDvaZMQJ.js} +1 -1
  51. package/editor/assets/{debug-BBhKuBNV.js → debug-CMULinBW.js} +1 -1
  52. package/editor/assets/{index-eVd0BToA.js → index-CZIRr5EL.js} +91 -91
  53. package/editor/index.html +1 -1
  54. package/package.json +4 -3
  55. package/skills/incanto-assets.md +16 -2
  56. package/skills/incanto-audio.md +19 -3
  57. package/skills/incanto-building-2d-games.md +29 -0
  58. package/skills/incanto-building-3d-games.md +60 -2
  59. package/skills/incanto-gameplay-behaviors.md +18 -1
  60. package/skills/incanto-save-slots.md +27 -0
  61. package/skills/incanto-verifying-your-game.md +96 -2
  62. package/skills/incanto-your-first-game.md +2 -1
  63. package/templates-app/beacon-isle-3d/package.json +1 -1
  64. package/templates-app/beacon-isle-3d/src/main.ts +13 -3
  65. package/templates-app/platformer-2d/index.html +0 -23
  66. package/templates-app/platformer-2d/package.json +1 -1
  67. package/templates-app/platformer-2d/src/behaviors.ts +26 -16
  68. package/templates-app/platformer-2d/src/game.scene.json +17 -27
  69. package/templates-app/platformer-2d/src/main.ts +24 -12
  70. package/templates-app/star-survivor/package.json +1 -1
  71. package/templates-app/star-survivor/src/main.ts +17 -6
  72. package/templates-app/tps-3d/package.json +1 -1
  73. package/templates-app/tps-3d/src/main.ts +26 -15
  74. package/templates-app/village-quest-3d/package.json +1 -1
  75. package/templates-app/village-quest-3d/src/main.ts +13 -3
@@ -58,18 +58,30 @@ const game = await createGame2D({
58
58
  throw e;
59
59
  });
60
60
 
61
- document.querySelector('#loading')?.remove();
61
+ // The console handle FIRST, before any wiring of your own can throw.
62
+ // `game.stats()`, `game.assetErrors()`, `game.frame()` and `game.engine.log`
63
+ // are the entire in-page diagnostic surface, and a static build has no other.
64
+ // Assigned after the wiring, one mistake below took all of them with it.
65
+ (window as unknown as { game: typeof game }).game = game;
62
66
 
63
- if (MUSIC_URL) {
64
- game.engine.music.play(MUSIC_URL, { loop: true, fadeIn: 1.5 });
65
- game.engine.audio.music = 0.3;
66
- }
67
+ // And the loading overlay comes down LAST. Everything between here and there is
68
+ // your code; a throw in it used to leave a level that renders perfectly with no
69
+ // player, no error UI, and no way to ask the page what happened.
70
+ try {
71
+ if (MUSIC_URL) {
72
+ game.engine.music.play(MUSIC_URL, { loop: true, fadeIn: 1.5 });
73
+ game.engine.audio.music = 0.3;
74
+ }
67
75
 
68
- // On-screen JUMP button (mobile + desktop parity); the joystick is auto-shown by
69
- // createGame2D on coarse pointers for the 'move' action.
70
- const jumpBtn = document.querySelector('#btn-jump');
71
- jumpBtn?.addEventListener('pointerdown', () => game.engine.input.handleKey('Space', true));
72
- jumpBtn?.addEventListener('pointerup', () => game.engine.input.handleKey('Space', false));
76
+ // No hand-rolled touch button here: the scene declares `"touch": "button"` on
77
+ // `jump` and `"touch": "joystick"` on `move`, so the ENGINE draws both on a
78
+ // coarse pointer — safe-area aware, off the home-indicator band, and sized to
79
+ // its own rules. This template used to draw an 88 px disc of its own at a flat
80
+ // `bottom: 2rem`, which covered 78% of the engine's jump button and put its
81
+ // lower edge inside the band iOS reserves for the leave-the-app swipe.
82
+ } catch (e) {
83
+ showBootFailure(e);
84
+ throw e;
85
+ }
73
86
 
74
- // Console playground: game.scene.root.getNode('Player').position = [x, y]
75
- Object.assign(window, { game });
87
+ document.querySelector('#loading')?.remove();
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@dimforge/rapier2d-compat": "0.19.3",
14
- "incanto": "^0.68.0",
14
+ "incanto": "^0.69.0",
15
15
  "three": "^0.184.0"
16
16
  },
17
17
  "devDependencies": {
@@ -45,12 +45,23 @@ const game = await createGame2D({
45
45
  throw e;
46
46
  });
47
47
 
48
- document.querySelector('#loading')?.remove();
48
+ // The console handle FIRST, before any wiring of your own can throw.
49
+ // `game.stats()`, `game.assetErrors()`, `game.frame()` and `game.engine.log`
50
+ // are the entire in-page diagnostic surface, and a static build has no other.
51
+ // Assigned after the wiring, one mistake below took all of them with it.
52
+ (window as unknown as { game: typeof game }).game = game;
49
53
 
50
- if (MUSIC_URL) {
51
- game.engine.music.play(MUSIC_URL, { loop: true, fadeIn: 1.5 });
52
- game.engine.audio.music = 0.3;
54
+ // And the loading overlay comes down LAST. Everything between here and there is
55
+ // your code; a throw in it used to leave a level that renders perfectly with no
56
+ // player, no error UI, and no way to ask the page what happened.
57
+ try {
58
+ if (MUSIC_URL) {
59
+ game.engine.music.play(MUSIC_URL, { loop: true, fadeIn: 1.5 });
60
+ game.engine.audio.music = 0.3;
61
+ }
62
+ } catch (e) {
63
+ showBootFailure(e);
64
+ throw e;
53
65
  }
54
66
 
55
- // Console playground: game.scene.root.getNode('Player').position = [x, y]
56
- Object.assign(window, { game });
67
+ document.querySelector('#loading')?.remove();
@@ -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.68.0",
16
+ "incanto": "^0.69.0",
17
17
  "three": "^0.184.0"
18
18
  },
19
19
  "devDependencies": {
@@ -50,22 +50,33 @@ const game = await createGame3D({
50
50
  throw e;
51
51
  });
52
52
 
53
- document.querySelector('#loading')?.remove();
53
+ // The console handle FIRST, before any wiring of your own can throw.
54
+ // `game.stats()`, `game.assetErrors()`, `game.frame()` and `game.engine.log`
55
+ // are the entire in-page diagnostic surface, and a static build has no other.
56
+ // Assigned after the wiring, one mistake below took all of them with it.
57
+ (window as unknown as { game: typeof game }).game = game;
54
58
 
55
- // Looping background music on the music bus (a calm tense pad). The engine
56
- // auto-resumes a gesture-blocked track on the first click/keypress.
57
- game.engine.music.play(musicUrl, { loop: true, fadeIn: 1.5 });
58
- game.engine.audio.music = 0.3;
59
+ // And the loading overlay comes down LAST. Everything between here and there is
60
+ // your code; a throw in it used to leave a level that renders perfectly with no
61
+ // player, no error UI, and no way to ask the page what happened.
62
+ try {
63
+ // Looping background music on the music bus (a calm tense pad). The engine
64
+ // auto-resumes a gesture-blocked track on the first click/keypress.
65
+ game.engine.music.play(musicUrl, { loop: true, fadeIn: 1.5 });
66
+ game.engine.audio.music = 0.3;
59
67
 
60
- // On-screen FIRE / JUMP buttons (mobile + desktop parity).
61
- for (const [id, code] of [
62
- ['btn-fire', 'KeyF'],
63
- ['btn-jump', 'Space'],
64
- ] as const) {
65
- const el = document.querySelector(`#${id}`);
66
- el?.addEventListener('pointerdown', () => game.engine.input.handleKey(code, true));
67
- el?.addEventListener('pointerup', () => game.engine.input.handleKey(code, false));
68
+ // On-screen FIRE / JUMP buttons (mobile + desktop parity).
69
+ for (const [id, code] of [
70
+ ['btn-fire', 'KeyF'],
71
+ ['btn-jump', 'Space'],
72
+ ] as const) {
73
+ const el = document.querySelector(`#${id}`);
74
+ el?.addEventListener('pointerdown', () => game.engine.input.handleKey(code, true));
75
+ el?.addEventListener('pointerup', () => game.engine.input.handleKey(code, false));
76
+ }
77
+ } catch (e) {
78
+ showBootFailure(e);
79
+ throw e;
68
80
  }
69
81
 
70
- // Console playground for vibe-coding: game.scene.root.getNode('Player')
71
- Object.assign(window, { game });
82
+ document.querySelector('#loading')?.remove();
@@ -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.68.0",
16
+ "incanto": "^0.69.0",
17
17
  "three": "^0.184.0"
18
18
  },
19
19
  "devDependencies": {
@@ -36,7 +36,17 @@ const game = await createGame3D({
36
36
  throw e;
37
37
  });
38
38
 
39
- document.querySelector('#loading')?.remove();
40
-
41
- // Console-poking handle for playtesting ("teleport me to the elder").
39
+ // The console handle FIRST, before any wiring of your own can throw.
40
+ // `game.stats()`, `game.assetErrors()`, `game.frame()` and `game.engine.log`
41
+ // are the entire in-page diagnostic surface, and a static build has no other.
42
+ // Assigned after the wiring, one mistake below took all of them with it.
42
43
  (window as unknown as { game: typeof game }).game = game;
44
+
45
+ // The overlay comes down LAST, after any wiring of your own. There is none in
46
+ // this template — when you add some, put it above this line and wrap it:
47
+ //
48
+ // try { …your wiring… } catch (e) { showBootFailure(e); throw e; }
49
+ //
50
+ // A throw between the overlay coming down and the handle going up used to leave
51
+ // a level that renders perfectly with no player and no error of any kind.
52
+ document.querySelector('#loading')?.remove();