incanto 0.31.0 → 0.32.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-play.mjs +7 -2
- package/dist/2d.js +1 -1
- package/dist/3d.d.ts +20 -0
- package/dist/3d.js +1 -1
- package/dist/{create-game-z5XaB1p5.js → create-game-bKHgHcsZ.js} +3 -2
- package/dist/{create-game-DqOjMBUS.js → create-game-gXI7PYl0.js} +11 -5
- package/dist/index.d.ts +10 -0
- package/dist/index.js +2 -2
- package/dist/react.js +1 -1
- package/dist/test-WwRIlXsK.js +642 -0
- package/dist/test.d.ts +53 -1
- package/dist/test.js +2 -392
- package/dist/{touch-031PxtCR.js → touch-BoNg_MnF.js} +2 -1
- package/dist/vite.js +1 -1
- package/editor/assets/{agent8-o27_Y1xN.js → agent8-C5k1nTCH.js} +1 -1
- package/editor/assets/{debug-DfcWX3uW.js → debug-BT_0mjk-.js} +1 -1
- package/editor/assets/{index-C9fb5QcT.js → index-gfyrByWw.js} +3 -3
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/skills/README.md +14 -2
- package/skills/incanto-building-2d-games.md +16 -0
- package/skills/incanto-building-3d-games.md +16 -0
- package/skills/incanto-verifying-your-game.md +86 -30
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
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-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-gfyrByWw.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="./assets/GameServer-C56iOUgF.js">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/package.json
CHANGED
package/skills/README.md
CHANGED
|
@@ -2,8 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
Full agent skills for building games with this **installed version** of Incanto.
|
|
4
4
|
An AI agent should start with `incanto-scene-json-authoring.md`, then the domain skill
|
|
5
|
-
for the task at hand
|
|
6
|
-
|
|
5
|
+
for the task at hand, and **finish every task with `incanto-verifying-your-game.md`**
|
|
6
|
+
— you cannot see the game, and that skill is how you find out whether it works.
|
|
7
|
+
`incanto-node-reference.md` (+ `../schemas/scene.schema.json`) is generated from the
|
|
8
|
+
engine source and lists every node type, prop, and default.
|
|
9
|
+
|
|
10
|
+
**Never hand a game back without reading these four.** Each answers a failure that
|
|
11
|
+
otherwise looks like nothing at all — see `incanto-verifying-your-game.md`:
|
|
12
|
+
|
|
13
|
+
| read | it is not clean when |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| `bunx incanto-check` | the scene will not load, or renders black (no light) |
|
|
16
|
+
| `stats().errors` | something threw and was skipped to keep the game alive |
|
|
17
|
+
| `assetErrors()` | a model or texture 404'd — the thing is simply not there |
|
|
18
|
+
| `framing` | the camera points the wrong way, or nothing is lit |
|
|
7
19
|
|
|
8
20
|
These files are the source of truth; the thin platform-delivery entries live in the
|
|
9
21
|
repo's root `skills/` folder and merely point here.
|
|
@@ -277,3 +277,19 @@ engine seed — runScript verifies particle gameplay reproducibly.
|
|
|
277
277
|
Mark unchanging subtrees (tile decor, backgrounds) `static: true` — the
|
|
278
278
|
renderer syncs them once and skips them every frame. Flip to `false` to
|
|
279
279
|
resume live syncing.
|
|
280
|
+
|
|
281
|
+
## Before you hand it back
|
|
282
|
+
|
|
283
|
+
You cannot see this game. `incanto-verifying-your-game.md` is how you find out
|
|
284
|
+
whether it works — run it after every edit, not once at the end:
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
bunx incanto-check # will it load? is anything lit?
|
|
288
|
+
printf 'step 500\nframing\nquit\n' | bunx incanto-play src/game.scene.json
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
`framing` tells you what the camera can actually SEE (on screen / off screen /
|
|
292
|
+
behind it), what lights the scene, and which colliders intersect. Then read
|
|
293
|
+
`stats().errors` (something threw and got skipped) and `assetErrors()` (a model
|
|
294
|
+
404'd). All four are silent failures otherwise — the screen just looks wrong,
|
|
295
|
+
or empty, and nothing throws.
|
|
@@ -562,3 +562,19 @@ if (cells) follow.setPath(cells.map(([cx, cy]) => nav.toWorld(cx, cy)));
|
|
|
562
562
|
dense-forest frame). Use when shadow CASTERS don't move — pair moving
|
|
563
563
|
characters with sprite/blob shadows. After a one-off world edit call
|
|
564
564
|
`renderer.refreshShadows()`.
|
|
565
|
+
|
|
566
|
+
## Before you hand it back
|
|
567
|
+
|
|
568
|
+
You cannot see this game. `incanto-verifying-your-game.md` is how you find out
|
|
569
|
+
whether it works — run it after every edit, not once at the end:
|
|
570
|
+
|
|
571
|
+
```bash
|
|
572
|
+
bunx incanto-check # will it load? is anything lit?
|
|
573
|
+
printf 'step 500\nframing\nquit\n' | bunx incanto-play src/game.scene.json
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
`framing` tells you what the camera can actually SEE (on screen / off screen /
|
|
577
|
+
behind it), what lights the scene, and which colliders intersect. Then read
|
|
578
|
+
`stats().errors` (something threw and got skipped) and `assetErrors()` (a model
|
|
579
|
+
404'd). All four are silent failures otherwise — the screen just looks wrong,
|
|
580
|
+
or empty, and nothing throws.
|
|
@@ -12,6 +12,20 @@ You usually cannot SEE the game (no browser in most agent environments). The
|
|
|
12
12
|
scene state itself is your screenshot. The loop is: **edit → check → scripted
|
|
13
13
|
run → read the capture → fix**. Never hand a game back without steps 2–3.
|
|
14
14
|
|
|
15
|
+
**The four things to read before you call it done.** Three of them are new, and
|
|
16
|
+
each answers a failure that used to look like nothing at all:
|
|
17
|
+
|
|
18
|
+
| read this | when it is not clean | see |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| `incanto-check` | the scene will not load, or renders black | §1, §5b |
|
|
21
|
+
| `stats().errors` | something threw and was skipped to keep the game alive | §6b |
|
|
22
|
+
| `assetErrors()` | a model/texture 404'd — the thing is simply not there | §6c |
|
|
23
|
+
| `framing` | the camera is pointed the wrong way, or nothing is lit | §6a |
|
|
24
|
+
|
|
25
|
+
A run that finishes is not a run that worked. `runScript()` fails the run when
|
|
26
|
+
`stats().errors` is non-zero, and prints the engine's warnings under the
|
|
27
|
+
failures — but `framing` and `assetErrors()` you have to ASK for.
|
|
28
|
+
|
|
15
29
|
## 1. After EVERY scene edit: `incanto-check`
|
|
16
30
|
|
|
17
31
|
```bash
|
|
@@ -144,6 +158,25 @@ const res = validateScene(sceneJson); // { ok } | { ok: false, error }
|
|
|
144
158
|
if (!res.ok) console.error(res.error.code, res.error.details); // details.path/prop/signal/validOptions
|
|
145
159
|
```
|
|
146
160
|
|
|
161
|
+
## 5b. What a green `incanto-check` now covers
|
|
162
|
+
|
|
163
|
+
`validateScene` / `incanto-check` hard-fail on all of these, so they never reach
|
|
164
|
+
a browser:
|
|
165
|
+
|
|
166
|
+
- **Every prop's type AND its enum values** — `"mesh": "crystal"` names what is
|
|
167
|
+
valid instead of printing `ok` and throwing at boot. All 31 enum props.
|
|
168
|
+
- **`input{}`** — a declaration's shape (`"keys": "Space"` instead of
|
|
169
|
+
`["Space"]`, an unknown `type`, a wrong `touch`). This used to be checked only
|
|
170
|
+
by `Engine.setScene`, i.e. never headlessly.
|
|
171
|
+
- **`assets{}`** — every entry an object with a non-empty `url`.
|
|
172
|
+
- **`environment.preset`** — resolved only inside Renderer3D before, so a typo
|
|
173
|
+
survived every check and died at boot.
|
|
174
|
+
|
|
175
|
+
And `auditScene` (the warnings `incanto-check` prints) gained the loudest
|
|
176
|
+
"why is my screen black" of all: **nothing lights this 3D scene** — no light
|
|
177
|
+
node, no `environment` sky/hdri/preset, no ambient intensity. Ambient defaults to
|
|
178
|
+
0, so such a scene renders nothing, throws nothing and logs nothing.
|
|
179
|
+
|
|
147
180
|
## 6. Catch broken edits at save time (vite)
|
|
148
181
|
|
|
149
182
|
```ts
|
|
@@ -161,44 +194,47 @@ ANY scene in the project — not just the one the game booted with. `incantoScen
|
|
|
161
194
|
root })` bounds that to a directory other than vite's; nothing outside it is readable
|
|
162
195
|
or writable, and none of it exists in a build (`configureServer`).
|
|
163
196
|
|
|
164
|
-
##
|
|
197
|
+
## 6a. See what the camera sees — without a GPU
|
|
165
198
|
|
|
166
|
-
`
|
|
167
|
-
|
|
199
|
+
`describe()` tells you a gem is at `[4, 1, -2]`. It cannot tell you whether you
|
|
200
|
+
can SEE it, which is the question you actually had. `framing()` answers that,
|
|
201
|
+
from geometry alone — no renderer, no canvas, no browser:
|
|
168
202
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
203
|
+
```
|
|
204
|
+
> framing
|
|
205
|
+
camera /World/Player/Cam at [0, 2, 8] looking [0, -0.2, -0.97] fov 60
|
|
206
|
+
lit by: /World/Sun (DirectionalLight3D), environment.sky
|
|
207
|
+
3 on screen, 1 off screen, 2 behind the camera
|
|
208
|
+
onScreen /World/Island (MeshInstance3D) [0, 0, 0] screen [0.02, -0.11] 8.2m
|
|
209
|
+
behind /World/Chest (ModelInstance3D) [0, 0, 40] 32m
|
|
210
|
+
offscreen /World/Gem (MeshInstance3D) [80, 0, 0] screen [4.4, 0] 80.1m
|
|
211
|
+
overlap /World/Platform ∩ /World/Gem
|
|
212
|
+
```
|
|
177
213
|
|
|
178
|
-
|
|
179
|
-
"why is my screen black" of all: **nothing lights this 3D scene** — no light
|
|
180
|
-
node, no `environment` sky/hdri/preset, no ambient intensity. Ambient defaults to
|
|
181
|
-
0, so such a scene renders nothing, throws nothing and logs nothing.
|
|
214
|
+
Read it for the three visual failures that look identical from a node list:
|
|
182
215
|
|
|
183
|
-
|
|
216
|
+
- **`behind`** — the thing is fine, the camera has its back to it. Indistinguishable
|
|
217
|
+
from "my model did not load" until you can see this line.
|
|
218
|
+
- **`lit by: NOTHING`** — the scene renders black. No error, no log, nothing wrong
|
|
219
|
+
with any node.
|
|
220
|
+
- **`overlap`** — two declared colliders intersect: the gem is inside the platform.
|
|
184
221
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
simply never appears, and `logs` comes back empty.
|
|
222
|
+
Also `incanto-play`'s `framing` command, and `describeFraming(scene)` /
|
|
223
|
+
`framingText(report)` from `incanto/test` for the structured form. A node counts
|
|
224
|
+
as on screen when its `size` box (or collider) is, not only its origin — so a
|
|
225
|
+
200 m island whose origin sits off to the left is correctly `onScreen`.
|
|
190
226
|
|
|
191
|
-
|
|
227
|
+
**For actual pixels**, turn on `preserveDrawingBuffer` — WebGL clears the buffer
|
|
228
|
+
the instant a frame composites, so `canvas.toDataURL()` and every screenshot
|
|
229
|
+
built on it come back BLANK without it:
|
|
192
230
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
— the direct answer to "why is my model not there". The store itself is
|
|
198
|
-
reachable as `renderer.assets` in both dimensions.
|
|
231
|
+
```ts
|
|
232
|
+
createGame3D({ ..., preserveDrawingBuffer: true });
|
|
233
|
+
// or in the scene: "environment": { "rendering": { "preserveDrawingBuffer": true } }
|
|
234
|
+
```
|
|
199
235
|
|
|
200
|
-
|
|
201
|
-
|
|
236
|
+
Then drive the page with whatever browser tool you have. It costs a buffer copy
|
|
237
|
+
per frame, which is why it is off by default.
|
|
202
238
|
|
|
203
239
|
## 6b. A thrown error no longer stops the game
|
|
204
240
|
|
|
@@ -223,6 +259,26 @@ stopped. It no longer can.
|
|
|
223
259
|
|
|
224
260
|
So the check after every edit is still `ok`, plus: **read `stats().errors`**.
|
|
225
261
|
|
|
262
|
+
## 6c. Engine diagnostics you can actually read
|
|
263
|
+
|
|
264
|
+
Every internal warning the engine produces — a GLB that 404'd, a body with no
|
|
265
|
+
collider, a retarget that dropped bones, an exception swallowed inside a physics
|
|
266
|
+
trigger handler — used to go to `console.*` and nowhere else, which is the one
|
|
267
|
+
channel a headless tool cannot read. The symptom was always the same: the model
|
|
268
|
+
simply never appears, and `logs` comes back empty.
|
|
269
|
+
|
|
270
|
+
They now go to **`engine.log` as well as the console**, so:
|
|
271
|
+
|
|
272
|
+
- `runScript().logs` contains them, and `describe()` prints them under the
|
|
273
|
+
failures (`! warn: …`).
|
|
274
|
+
- The debug overlay's **Logs** panel shows them live.
|
|
275
|
+
- `game.assetErrors()` lists every asset that failed **with its reason and ref**
|
|
276
|
+
— the direct answer to "why is my model not there". The store itself is
|
|
277
|
+
reachable as `renderer.assets` in both dimensions.
|
|
278
|
+
|
|
279
|
+
So the after-every-edit check is: `ok`, then **`stats().errors`**, then
|
|
280
|
+
**`assetErrors()`**.
|
|
281
|
+
|
|
226
282
|
## 7. See inside the RUNNING game (debug overlay)
|
|
227
283
|
|
|
228
284
|
```ts
|