@pix3/cli 1.6.3 → 2.0.0-alpha.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/LICENSE +201 -201
- package/README.md +722 -788
- package/dist/index.js +557 -421
- package/dist/runtime-types.json +1 -1
- package/dist/smoke/prebuilt/{build-7MIXIMSZ.mjs → build-7REMSA2S.mjs} +52 -52
- package/dist/smoke/prebuilt/chunk-4DGG2BKR.mjs +2 -0
- package/dist/smoke/prebuilt/chunk-YLBMUJ2H.mjs +238 -0
- package/dist/smoke/prebuilt/runtime.mjs +1 -1
- package/dist/smoke/prebuilt/smoke-worker.mjs +211 -2
- package/dist/smoke/prebuilt/tree-defaults.mjs +1 -1
- package/dist/validate/prebuilt/{build-AUGKXER3.js → build-ADF5EEE2.js} +52 -52
- package/dist/validate/prebuilt/bundle-main.js +223 -18
- package/dist/validate/prebuilt/chunk-VIHIF4G2.js +238 -0
- package/dist/validate/prebuilt/runtime.js +1 -1
- package/kit/files/.claude/skills/pix3-editor/SKILL.md +200 -0
- package/kit/files/.claude/skills/pix3-nodes/SKILL.md +13 -15
- package/kit/files/.claude/skills/pix3-nodes/reference.md +77 -71
- package/kit/files/.claude/skills/pix3-scene-format/SKILL.md +38 -41
- package/kit/files/.claude/skills/pix3-scene-format/pix3anim.md +185 -0
- package/kit/files/.claude/skills/pix3-scene-format/project-files.md +244 -0
- package/kit/files/.claude/skills/pix3-scene-format/reference.md +28 -16
- package/kit/files/.claude/skills/pix3-scripts/SKILL.md +34 -24
- package/kit/files/.claude/skills/pix3-scripts/reference.md +68 -141
- package/kit/files/.claude/skills/pix3-verify/SKILL.md +65 -326
- package/kit/files/.claude/skills/pix3-verify/reference.md +2 -14
- package/kit/files/AGENTS.md +76 -84
- package/kit/files/design/tests/bots/pix3-test-bot.d.ts +89 -0
- package/kit/kit.json +8 -5
- package/package.json +62 -54
- package/templates/2d/files/scenes/main.pix3scene +31 -0
- package/templates/2d/template.yaml +11 -0
- package/templates/3d/files/scenes/main.pix3scene +50 -0
- package/templates/3d/template.yaml +11 -0
- package/templates/base/files/README.md +39 -0
- package/templates/base/files/gitignore +11 -0
- package/templates/base/files/index.html +23 -0
- package/templates/base/files/package.json +28 -0
- package/templates/base/files/src/main.ts +3 -0
- package/templates/base/files/tsconfig.json +17 -0
- package/templates/base/files/vite.config.ts +10 -0
- package/dist/smoke/prebuilt/chunk-CBFYKDS7.mjs +0 -2
- package/dist/smoke/prebuilt/chunk-VJHJ5BCO.mjs +0 -239
- package/dist/validate/prebuilt/chunk-CFQFEI52.js +0 -239
- package/templates/empty-2d/files/README.md +0 -20
- package/templates/empty-2d/files/scenes/main.pix3scene +0 -68
- package/templates/empty-2d/files/sprites/pix3-logo.png +0 -0
- package/templates/empty-2d/template.yaml +0 -7
- package/templates/empty-3d/files/README.md +0 -20
- package/templates/empty-3d/files/scenes/main.pix3scene +0 -108
- package/templates/empty-3d/files/sprites/pix3-logo.png +0 -0
- package/templates/empty-3d/template.yaml +0 -7
- package/templates/idea-blank/files/README.md +0 -22
- package/templates/idea-blank/files/scenes/main.pix3scene +0 -37
- package/templates/idea-blank/template.yaml +0 -10
- package/templates/minigame-2d/files/README.md +0 -44
- package/templates/minigame-2d/files/design/tests/reachability.json +0 -1
- package/templates/minigame-2d/files/design/tests/routines/mute-music.json +0 -44
- package/templates/minigame-2d/files/scenes/main.pix3scene +0 -84
- package/templates/minigame-2d/files/scenes/menu.pix3scene +0 -118
- package/templates/minigame-2d/files/scenes/ui/settings-window.pix3scene +0 -138
- package/templates/minigame-2d/files/scripts/GameFlow.ts +0 -133
- package/templates/minigame-2d/files/scripts/MenuFlow.ts +0 -217
- package/templates/minigame-2d/files/scripts/SettingsWindow.ts +0 -198
- package/templates/minigame-2d/template.yaml +0 -10
- package/templates/playable-2d/files/README.md +0 -30
- package/templates/playable-2d/files/design/recipe.md +0 -83
- package/templates/playable-2d/files/design/tests/reachability.json +0 -4
- package/templates/playable-2d/files/design/tests/routines/intro-to-cta.json +0 -32
- package/templates/playable-2d/files/scenes/main.pix3scene +0 -111
- package/templates/playable-2d/files/scenes/ui/end-screen.pix3scene +0 -91
- package/templates/playable-2d/files/scenes/ui/intro.pix3scene +0 -65
- package/templates/playable-2d/files/scripts/CtaButton.ts +0 -55
- package/templates/playable-2d/files/scripts/GameFlow.ts +0 -256
- package/templates/playable-2d/files/sprites/pix3-logo.png +0 -0
- package/templates/playable-2d/template.yaml +0 -9
- package/templates/playable-3d/files/README.md +0 -32
- package/templates/playable-3d/files/design/recipe.md +0 -127
- package/templates/playable-3d/files/design/tests/reachability.json +0 -4
- package/templates/playable-3d/files/design/tests/routines/intro-to-cta.json +0 -32
- package/templates/playable-3d/files/scenes/main.pix3scene +0 -230
- package/templates/playable-3d/files/scenes/ui/end-screen.pix3scene +0 -91
- package/templates/playable-3d/files/scenes/ui/intro.pix3scene +0 -65
- package/templates/playable-3d/files/scripts/CtaButton.ts +0 -55
- package/templates/playable-3d/files/scripts/GameFlow.ts +0 -309
- package/templates/playable-3d/files/scripts/GameRules.ts +0 -290
- package/templates/playable-3d/files/scripts/ScoreHud.ts +0 -113
- package/templates/playable-3d/template.yaml +0 -9
- package/templates/recipe-arena-2d/files/README.md +0 -48
- package/templates/recipe-arena-2d/files/design/recipe.md +0 -127
- package/templates/recipe-arena-2d/files/design/tests/reachability.json +0 -4
- package/templates/recipe-arena-2d/files/design/tests/routines/terminal-retry.json +0 -23
- package/templates/recipe-arena-2d/files/scenes/main.pix3scene +0 -292
- package/templates/recipe-arena-2d/files/scenes/menu.pix3scene +0 -100
- package/templates/recipe-arena-2d/files/scenes/prefabs/hazard.pix3scene +0 -42
- package/templates/recipe-arena-2d/files/scenes/prefabs/pickup.pix3scene +0 -45
- package/templates/recipe-arena-2d/files/scenes/ui/result.pix3scene +0 -85
- package/templates/recipe-arena-2d/files/scripts/GameRules.ts +0 -368
- package/templates/recipe-arena-2d/files/scripts/MenuFlow.ts +0 -106
- package/templates/recipe-arena-2d/files/scripts/PlayerController.ts +0 -151
- package/templates/recipe-arena-2d/files/scripts/ScoreHud.ts +0 -94
- package/templates/recipe-arena-2d/files/scripts/Spawner.ts +0 -214
- package/templates/recipe-arena-2d/files/scripts/TouchRules.ts +0 -174
- package/templates/recipe-arena-2d/files/sprites/ph-avatar.png +0 -0
- package/templates/recipe-arena-2d/files/sprites/ph-hazard.png +0 -0
- package/templates/recipe-arena-2d/files/sprites/ph-pickup.png +0 -0
- package/templates/recipe-arena-2d/template.yaml +0 -10
- package/templates/recipe-blank-2d/files/README.md +0 -61
- package/templates/recipe-blank-2d/files/design/recipe.md +0 -148
- package/templates/recipe-blank-2d/files/design/tests/reachability.json +0 -4
- package/templates/recipe-blank-2d/files/design/tests/routines/restart.json +0 -27
- package/templates/recipe-blank-2d/files/design/tests/routines/terminal-retry.json +0 -23
- package/templates/recipe-blank-2d/files/scenes/main.pix3scene +0 -224
- package/templates/recipe-blank-2d/files/scenes/ui/result.pix3scene +0 -85
- package/templates/recipe-blank-2d/files/scripts/GameRules.ts +0 -350
- package/templates/recipe-blank-2d/files/scripts/ScoreHud.ts +0 -110
- package/templates/recipe-blank-2d/files/sprites/ph-bg.png +0 -0
- package/templates/recipe-blank-2d/files/sprites/ph-capsule.png +0 -0
- package/templates/recipe-blank-2d/files/sprites/ph-circle.png +0 -0
- package/templates/recipe-blank-2d/files/sprites/ph-orb.png +0 -0
- package/templates/recipe-blank-2d/files/sprites/ph-ring.png +0 -0
- package/templates/recipe-blank-2d/files/sprites/ph-star.png +0 -0
- package/templates/recipe-blank-2d/template.yaml +0 -10
- package/templates/recipe-bouncer-2d/files/README.md +0 -81
- package/templates/recipe-bouncer-2d/files/design/recipe.md +0 -146
- package/templates/recipe-bouncer-2d/files/design/tests/reachability.json +0 -4
- package/templates/recipe-bouncer-2d/files/design/tests/routines/terminal-retry.json +0 -23
- package/templates/recipe-bouncer-2d/files/scenes/main.pix3scene +0 -615
- package/templates/recipe-bouncer-2d/files/scenes/menu.pix3scene +0 -191
- package/templates/recipe-bouncer-2d/files/scenes/ui/result.pix3scene +0 -87
- package/templates/recipe-bouncer-2d/files/scripts/BallBody.ts +0 -298
- package/templates/recipe-bouncer-2d/files/scripts/GameRules.ts +0 -377
- package/templates/recipe-bouncer-2d/files/scripts/MenuFlow.ts +0 -109
- package/templates/recipe-bouncer-2d/files/scripts/PaddleController.ts +0 -112
- package/templates/recipe-bouncer-2d/files/scripts/ScoreHud.ts +0 -94
- package/templates/recipe-bouncer-2d/files/scripts/TouchRules.ts +0 -263
- package/templates/recipe-bouncer-2d/files/scripts/ball-collision.ts +0 -307
- package/templates/recipe-bouncer-2d/files/sprites/ph-ball.png +0 -0
- package/templates/recipe-bouncer-2d/files/sprites/ph-bg.png +0 -0
- package/templates/recipe-bouncer-2d/files/sprites/ph-bumper.png +0 -0
- package/templates/recipe-bouncer-2d/files/sprites/ph-paddle.png +0 -0
- package/templates/recipe-bouncer-2d/template.yaml +0 -10
- package/templates/recipe-grid-3d/files/README.md +0 -22
- package/templates/recipe-grid-3d/files/design/recipe.md +0 -110
- package/templates/recipe-grid-3d/files/scenes/main.pix3scene +0 -169
- package/templates/recipe-grid-3d/files/scenes/menu.pix3scene +0 -100
- package/templates/recipe-grid-3d/files/scenes/ui/result.pix3scene +0 -105
- package/templates/recipe-grid-3d/files/scripts/GridBoard.ts +0 -319
- package/templates/recipe-grid-3d/files/scripts/GridRules.ts +0 -278
- package/templates/recipe-grid-3d/files/scripts/MenuFlow.ts +0 -106
- package/templates/recipe-grid-3d/files/scripts/ScoreHud.ts +0 -94
- package/templates/recipe-grid-3d/template.yaml +0 -10
- package/templates/recipe-tapper-2d/files/README.md +0 -39
- package/templates/recipe-tapper-2d/files/design/recipe.md +0 -132
- package/templates/recipe-tapper-2d/files/design/tests/reachability.json +0 -4
- package/templates/recipe-tapper-2d/files/design/tests/routines/terminal-retry.json +0 -23
- package/templates/recipe-tapper-2d/files/scenes/main.pix3scene +0 -269
- package/templates/recipe-tapper-2d/files/scenes/menu.pix3scene +0 -100
- package/templates/recipe-tapper-2d/files/scenes/prefabs/hazard.pix3scene +0 -42
- package/templates/recipe-tapper-2d/files/scenes/prefabs/target.pix3scene +0 -45
- package/templates/recipe-tapper-2d/files/scenes/ui/result.pix3scene +0 -85
- package/templates/recipe-tapper-2d/files/scripts/GameRules.ts +0 -368
- package/templates/recipe-tapper-2d/files/scripts/MenuFlow.ts +0 -106
- package/templates/recipe-tapper-2d/files/scripts/ScoreHud.ts +0 -94
- package/templates/recipe-tapper-2d/files/scripts/Spawner.ts +0 -214
- package/templates/recipe-tapper-2d/files/scripts/TouchRules.ts +0 -192
- package/templates/recipe-tapper-2d/files/sprites/ph-hazard.png +0 -0
- package/templates/recipe-tapper-2d/files/sprites/ph-target.png +0 -0
- package/templates/recipe-tapper-2d/template.yaml +0 -10
package/kit/files/AGENTS.md
CHANGED
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
<!-- Pix3 agent kit
|
|
1
|
+
<!-- Pix3 agent kit 2.0.0-alpha.0 — written by `pix3 kit`. You may edit it: `pix3 kit --update` never overwrites a kit file you changed. -->
|
|
2
2
|
# AGENTS.md — Pix3 game project
|
|
3
3
|
|
|
4
4
|
This folder is a **Pix3 game**: a 2D/3D browser game. You edit it by writing files. A human
|
|
5
5
|
has the same folder open in the Pix3 editor, moves things with the mouse and presses Play;
|
|
6
6
|
the editor saves their edits to the same files. The files are the whole contract.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
A project made by `npm create pix3` starts **empty**: one entry scene (`scenes/main.pix3scene`,
|
|
9
|
+
a 2D root and background, or a 3D camera and lights) and no scripts. The game is yours to build.
|
|
10
10
|
|
|
11
11
|
## Read first
|
|
12
12
|
|
|
13
|
-
1. `
|
|
14
|
-
|
|
15
|
-
them with the table in `.claude/skills/pix3-scene-format/SKILL.md` ("Recipe tool names").
|
|
16
|
-
2. `README.md` — file layout of this project.
|
|
17
|
-
3. The one scene or script you are about to change. Nothing else. Do not survey the repo.
|
|
13
|
+
1. `README.md` — file layout of this project.
|
|
14
|
+
2. The one scene or script you are about to change. Nothing else. Do not survey the repo.
|
|
18
15
|
To find it, and to find your way inside it, use `pix3 tree` (every scene and prefab with
|
|
19
16
|
node counts, types and components) and `pix3 tree <scene>` (one line per node: id, type,
|
|
20
|
-
position, size, layout, components, prefab instances
|
|
21
|
-
|
|
22
|
-
before you edit it (rule 2).
|
|
17
|
+
position, size, layout, components, prefab instances) — not a read of whole scene files.
|
|
18
|
+
Read the file itself right before you edit it (rule 2).
|
|
23
19
|
|
|
24
20
|
## Layout
|
|
25
21
|
|
|
@@ -34,9 +30,15 @@ The layout is **whatever this project has** — do not assume folders. Three rul
|
|
|
34
30
|
`pix3 check` scan). `export class X extends Script` → `type: user:X`.
|
|
35
31
|
|
|
36
32
|
`pix3project.yaml` is the manifest (do not edit unless asked); `.pix3/` is editor + CLI
|
|
37
|
-
bookkeeping (
|
|
33
|
+
bookkeeping (`dev.json` of the running dev server, the version journal, script types) — read
|
|
34
|
+
`dev.json`, never edit anything there.
|
|
38
35
|
|
|
39
|
-
|
|
36
|
+
**The editor never creates, renames, moves or deletes a file, never edits `pix3project.yaml` and
|
|
37
|
+
never builds — you do.** New scene, rename/move/delete with every reference, a branch turned into
|
|
38
|
+
a prefab, a new flipbook, a locale added or removed, project settings, build options:
|
|
39
|
+
`.claude/skills/pix3-scene-format/project-files.md`.
|
|
40
|
+
|
|
41
|
+
Example — the layout `npm create pix3` sets up (`pix3 new`); other projects differ:
|
|
40
42
|
|
|
41
43
|
| Path | What |
|
|
42
44
|
| --- | --- |
|
|
@@ -45,7 +47,8 @@ Example — the layout a **recipe** project (`pix3 new`) ships; other projects d
|
|
|
45
47
|
| `scenes/prefabs/*.pix3scene` | Prefabs: a scene file with exactly ONE root node (a top-level `prefabs/` works too) |
|
|
46
48
|
| `scripts/*.ts` | Script components |
|
|
47
49
|
| `sprites/`, `audio/`, `fonts/`, `models/` … | Assets, referenced as `res://sprites/x.png` |
|
|
48
|
-
| `design/` |
|
|
50
|
+
| `design/` | Design notes, GDD, references |
|
|
51
|
+
| `src/main.ts`, `index.html`, `vite.config.ts` | The Vite entry: `startGame('#app')` boots the entry scene; `pix3()` serves the editor at `/__pix3/` |
|
|
49
52
|
|
|
50
53
|
## The five rules
|
|
51
54
|
|
|
@@ -53,35 +56,25 @@ Example — the layout a **recipe** project (`pix3 new`) ships; other projects d
|
|
|
53
56
|
smallest form that plays, before asking anything. Choose small things yourself (a shade, a
|
|
54
57
|
speed, a count) and say so in one line. At most ONE question per turn, and only about a
|
|
55
58
|
fork that changes structure ("win by score or by time?"). Never open with a question.
|
|
56
|
-
2. **
|
|
57
|
-
minute ago
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
(
|
|
61
|
-
the human. Without that re-read the editor keeps restoring the human's value on every
|
|
62
|
-
write you make, even if you write the same number.
|
|
59
|
+
2. **Sync, then re-read a scene before you edit it.** The human may have moved things in the
|
|
60
|
+
editor a minute ago; a successful `pix3_sync` puts their unsaved edits on disk. Edit the lines
|
|
61
|
+
you mean to change (search/replace), never regenerate a whole scene from memory. After
|
|
62
|
+
writing, `pix3_sync` again with `expect` = the sha256 of every file you wrote
|
|
63
|
+
(`.claude/skills/pix3-editor/SKILL.md`).
|
|
63
64
|
3. **Leave layout, colours and fine-tuning to the human.** If asked "a bit more to the left",
|
|
64
65
|
do it, then offer: "you can drag it in the editor — it saves on its own".
|
|
65
66
|
4. **Run `pix3 check` after every batch of edits** and fix every error before you say "done".
|
|
66
67
|
It checks YAML, node types, properties, `res://` paths, prefabs, components, and
|
|
67
|
-
type-checks your scripts
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
`
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
smoke of the menu says nothing about the game. It runs that scene in Node for 2 s
|
|
74
|
-
(`--frames N` for more) and exits 1 on any script throw, `console.error` or unhandled
|
|
75
|
-
rejection, naming script, frame and source line. With no scene it runs several, a line
|
|
76
|
-
each: the scenes your uncommitted changes reach (git), else every top-level scene, game
|
|
77
|
-
first. Green means nothing threw; it does not mean it plays (nothing was tapped or drawn)
|
|
78
|
-
— so then tell the human what to press and what they should see.
|
|
79
|
-
5. **Art: placeholder → SVG → `generate_asset`, never emoji.** Placeholder = `ColorRect2D`, or
|
|
68
|
+
type-checks your scripts. Then run the game: with the editor open, `pix3_sync` with `expect`
|
|
69
|
+
and `pix3_play` / `pix3_game_run` / `pix3_errors` / a screenshot (`pix3-editor`); without it,
|
|
70
|
+
`pix3 smoke <the scene you changed>` — the game, not the menu, which never presses PLAY
|
|
71
|
+
headless (`pix3-verify`). A sync that is not `ok` is not green, and a green smoke means
|
|
72
|
+
nothing threw, not that it plays — so tell the human what to press and what they should see.
|
|
73
|
+
5. **Art: placeholder → SVG → a generated image, never emoji.** Placeholder = `ColorRect2D`, or
|
|
80
74
|
a near-white PNG in `sprites/` tinted with a `core:tint` effect. Better art = an SVG you
|
|
81
|
-
write into `sprites/`
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
refused — emoji are not art. List every placeholder you leave.
|
|
75
|
+
write into `sprites/` (`pix3-nodes` → "An SVG you write as a sprite") — or an image the
|
|
76
|
+
human generates. A label/text that is only emoji is refused — emoji are not art. List every
|
|
77
|
+
placeholder you leave.
|
|
85
78
|
|
|
86
79
|
## YAML essentials (`.pix3scene`) — details in `pix3-scene-format`
|
|
87
80
|
|
|
@@ -108,16 +101,15 @@ root:
|
|
|
108
101
|
properties: { visible: false }
|
|
109
102
|
```
|
|
110
103
|
|
|
111
|
-
- The sample assumes a 1080×1920 portrait 2D root; yours may not have one
|
|
112
|
-
`viewportBaseSize` and `projectType` in `pix3project.yaml
|
|
113
|
-
|
|
114
|
-
already exist (same parent, same anchoring), not to an assumed screen size.
|
|
104
|
+
- The sample assumes a 1080×1920 portrait 2D root; yours may not have one — read
|
|
105
|
+
`viewportBaseSize` and `projectType` in `pix3project.yaml`, and place new HUD relative to the
|
|
106
|
+
HUD that exists (`pix3-scene-format` → "2D transform").
|
|
115
107
|
- 2D space: design pixels, origin at the screen centre, **X right, Y up**. `position` is the
|
|
116
108
|
node's centre. Tree order is paint order: later/deeper draws on top.
|
|
117
109
|
- **Quote every colour**: `color: "#141a2e"`. Unquoted, `#` starts a YAML comment.
|
|
118
110
|
- Textures: `texture: { type: 'texture', url: 'res://sprites/ph-target.png' }`.
|
|
119
111
|
- `visible: false` on an overlay instance hides it **in the editor only**; play mode reads
|
|
120
|
-
`initiallyVisible` on the overlay file's root.
|
|
112
|
+
`initiallyVisible` on the overlay file's root. Set both.
|
|
121
113
|
- The loader is forgiving — unknown types, unknown keys and wrong value types load silently
|
|
122
114
|
as nothing. That is why rule 4 exists.
|
|
123
115
|
|
|
@@ -139,65 +131,65 @@ export class Combo extends Script {
|
|
|
139
131
|
}
|
|
140
132
|
```
|
|
141
133
|
|
|
142
|
-
- One mechanic = one new script of 70–140 lines.
|
|
143
|
-
|
|
144
|
-
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
(next section).
|
|
134
|
+
- One mechanic = one new script of 70–140 lines.
|
|
135
|
+
- Talk between scripts the way the project already does. In a new project use signals on nodes:
|
|
136
|
+
`node.emit('touch-scored', 1)` / `node.connect('touch-scored', this, fn)`; once named, never
|
|
137
|
+
rename a signal or a node id other scripts use. An existing game may use its own event bus or
|
|
138
|
+
store instead (next section).
|
|
148
139
|
- Transforms are mutated, never assigned: `node.position.set(x, y, 0)`, `node.rotation.z = rad`.
|
|
149
140
|
- Types come from `@pix3/runtime`: `pix3 check` type-checks against the bundled declarations in
|
|
150
141
|
`.pix3/types/` (or against your own `node_modules` when the project has its own `tsconfig.json`).
|
|
151
142
|
|
|
152
|
-
## Hosting an existing
|
|
143
|
+
## Hosting an existing game
|
|
153
144
|
|
|
154
|
-
A game that was not made from
|
|
155
|
-
second one
|
|
145
|
+
A game that was not made from `npm create pix3` has its own architecture; plug into it, do not
|
|
146
|
+
add a second one — its event bus or store, its own shake/sound/tween helpers, and cleanup by
|
|
147
|
+
hand of everything that is not a node signal (`pix3-scripts` → "Hosting an existing game").
|
|
156
148
|
|
|
157
|
-
- **Find its event bus / state store** before writing a script:
|
|
158
|
-
`grep -rn "CustomEvent\|dispatchEvent\|addEventListener\|subscribe(\|EventTarget\|emit(" src scripts`.
|
|
159
|
-
Window `CustomEvent`s, an `EventTarget` singleton, or a store with `subscribe()` are all
|
|
160
|
-
normal; node signals are only one option. Listen to what the game already emits.
|
|
161
|
-
- **Clean up by hand.** `Script.onDetach` auto-disconnects only **node signals** whose target is
|
|
162
|
-
the script (on its own node or any other). Window listeners, store subscriptions and timers
|
|
163
|
-
must be removed in `onDetach` (keep the handler in a field; call the
|
|
164
|
-
unsubscribe the store returned) — otherwise every play/stop in the editor leaves one more
|
|
165
|
-
live listener behind.
|
|
166
149
|
- **Two instruction files.** The project's own `AGENTS.md` wins on **process** (planning first,
|
|
167
150
|
where config and tests go, commit rules); this kit wins on **Pix3 facts** (the YAML format,
|
|
168
151
|
the runtime API, `pix3 check`).
|
|
169
152
|
- The project's own `package.json` means `npm install` before `pix3 check` can type-check.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
- `pix3
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
reach, else every top-level scene (`--all` forces that).
|
|
153
|
+
|
|
154
|
+
## The CLI and the editor bridge
|
|
155
|
+
|
|
156
|
+
A project made by `npm create pix3` has them as npm scripts: `npm run dev` (Vite: the game at
|
|
157
|
+
`/`, the editor at `/__pix3/`, on the port Vite got — 5173 only if it was free; read
|
|
158
|
+
`.pix3/dev.json`), `npm run editor` (`pix3 editor`), `npm run build` (`dist/`),
|
|
159
|
+
`npm run preview` (serve the build), `npm run check` (`pix3 check`), `npm run smoke`
|
|
160
|
+
(`pix3 smoke`; pass the scene after `--`). Elsewhere call `npx pix3 …` or read `package.json`.
|
|
161
|
+
|
|
162
|
+
- `pix3 check [--json]` — after every batch (rule 4); `--json` prints `files` (`{ file, sha256 }`)
|
|
163
|
+
for `pix3_sync`'s `expect`. It flushes the open editor's unsaved edits first (`--no-sync`
|
|
164
|
+
skips that). `pix3 validate [paths…]` — scenes only, no type-check.
|
|
165
|
+
- `pix3 smoke [scene] [--frames N] [--json]` — run a scene headless (no browser); exit 1 on a
|
|
166
|
+
script throw, `console.error` or unhandled rejection. Name the game scene.
|
|
185
167
|
- `pix3 tree [scene] [--types A,B] [--depth N] [--props] [--json]` — scene outline, one line
|
|
186
168
|
per node; no scene = project overview.
|
|
187
|
-
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
169
|
+
- `pix3 editor` — find (or start) the dev server and open the editor in a Chrome reachable only
|
|
170
|
+
through its token proxy; `pix3 agent-setup [claude|codex] [--repair]` — write the project's
|
|
171
|
+
MCP config for `chrome-devtools-mcp`, once (never commit it).
|
|
172
|
+
- `pix3 gap "<what was missing>" --kind capability|tool|node|doc|other [--detail "…"] [--context "<file or task>"]`
|
|
173
|
+
— when you had to **work around** something Pix3 does not have (an engine capability, a bridge
|
|
174
|
+
tool, a node type, a doc that was missing or wrong), record it once, after the workaround: one
|
|
175
|
+
line in `.pix3/gaps.jsonl` (local, read by the Pix3 team). Sparingly — not for your own
|
|
176
|
+
mistakes, a question to the human, or a feature the game itself should implement.
|
|
177
|
+
- **The editor bridge.** With the editor tab open, the `pix3-browser` MCP server (Chrome
|
|
178
|
+
DevTools) reaches it: `list_pages` → `select_page` → `list_3p_developer_tools` → the
|
|
179
|
+
`pix3_*` tools — sync the editor with the disk, play, step the game with predicates, read the
|
|
180
|
+
scene and the errors, prepare a screenshot. There is no scene-editing tool — you still edit
|
|
181
|
+
files. No `pix3-browser` server → `npx pix3 agent-setup`, then a new thread. The loop, the
|
|
182
|
+
not-ok answers and the inline fallback: `.claude/skills/pix3-editor/SKILL.md`.
|
|
192
183
|
|
|
193
184
|
## Skills (read the one you need, when you need it)
|
|
194
185
|
|
|
195
|
-
- `.claude/skills/pix3-scene-format/SKILL.md` — full YAML format, prefabs, overlays
|
|
186
|
+
- `.claude/skills/pix3-scene-format/SKILL.md` — full YAML format, prefabs, overlays; `.pix3anim` flipbooks and `pix3 character-compile` in `pix3anim.md` beside it; file and project operations the editor does not do in `project-files.md` beside it
|
|
196
187
|
- `.claude/skills/pix3-nodes/SKILL.md` — 2D node properties (Group2D, ColorRect2D, Sprite2D, Label2D, Button2D, Bar2D, CanvasLayer2D, PostProcess); every node in `reference.md` beside it
|
|
197
188
|
- `.claude/skills/pix3-scripts/SKILL.md` — Script API: lifecycle, schema, scene/input/juice/tween/audio/physics, `core:` components, traps
|
|
198
|
-
- `.claude/skills/pix3-
|
|
189
|
+
- `.claude/skills/pix3-editor/SKILL.md` — the editor bridge: find the tab, `pix3_sync` with `expect`, play ownership, `pix3_game_run`, screenshots, inline fallback
|
|
190
|
+
- `.claude/skills/pix3-verify/SKILL.md` — `pix3 check` / `validate` / `smoke`, the diagnostic codes, how to report what was verified
|
|
199
191
|
|
|
200
192
|
## Finish every turn with
|
|
201
193
|
|
|
202
|
-
What changed (files), what `pix3 check` said, whether you ran the game (and what `
|
|
194
|
+
What changed (files), what `pix3 check` said, whether you ran the game (and what `pix3_game_run`
|
|
203
195
|
answered) or what the human should press and see, placeholders left, and 2–3 concrete next steps.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Pix3 agent kit 2.0.0-alpha.0 — `pix3 kit --update` rewrites this file; do not edit.
|
|
2
|
+
//
|
|
3
|
+
// Types for the test policies in this folder (global: no import needed). A policy is
|
|
4
|
+
// one file exporting an object with a `tick(bot)`; the harness runs it once per logic
|
|
5
|
+
// tick while the game plays, through `pix3_game_run {bot: {name: '<file name without
|
|
6
|
+
// .ts>'}, …}`. Write it as
|
|
7
|
+
//
|
|
8
|
+
// export default {
|
|
9
|
+
// name: 'dodge',
|
|
10
|
+
// tick(bot) { … },
|
|
11
|
+
// } satisfies BotPolicy;
|
|
12
|
+
//
|
|
13
|
+
// so `bot` is a Pix3TestBot and `pix3 check` type-checks the policy.
|
|
14
|
+
//
|
|
15
|
+
// The timing contract, which decides whether a policy works: `tick` runs AFTER the
|
|
16
|
+
// game's tick, and every actuator lands on the NEXT tick. Observe frame N, act for
|
|
17
|
+
// frame N+1 — the same one-frame lag a human player has.
|
|
18
|
+
|
|
19
|
+
declare interface BotPoint {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
z?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** What a policy sees of one live node. */
|
|
26
|
+
declare interface BotNodeView {
|
|
27
|
+
nodeId: string;
|
|
28
|
+
name: string;
|
|
29
|
+
type: string;
|
|
30
|
+
/** The node's own flag. `false` means it is not on screen and cannot be tapped. */
|
|
31
|
+
visible: boolean;
|
|
32
|
+
position: { x: number; y: number; z: number };
|
|
33
|
+
worldPosition: { x: number; y: number; z: number };
|
|
34
|
+
/** The text the node renders, for nodes that render one. */
|
|
35
|
+
text?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare interface BotHit {
|
|
39
|
+
node: BotNodeView;
|
|
40
|
+
distance: number;
|
|
41
|
+
point: { x: number; y: number; z: number };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
declare interface Pix3TestBot {
|
|
45
|
+
/** Ticks this policy has been ticked for. 1 on the first tick. */
|
|
46
|
+
readonly frame: number;
|
|
47
|
+
|
|
48
|
+
// -- sensors ---------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
/** Live nodes answering a name, an id, or a type ('Sprite2D'). */
|
|
51
|
+
nodes(query: string): BotNodeView[];
|
|
52
|
+
/** Nearest live node of `type` to `from` (default: the world origin). */
|
|
53
|
+
nearest(type: string, from?: BotPoint): BotHit | null;
|
|
54
|
+
/** First live node struck by a ray. `dir` need not be normalised. */
|
|
55
|
+
raycast(from: BotPoint, dir: BotPoint): BotHit | null;
|
|
56
|
+
/** The game's own registerGameDebug() snapshot, or null when it registered none. */
|
|
57
|
+
gameState(): unknown;
|
|
58
|
+
|
|
59
|
+
// -- actuators -------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
/** Hold a key ('Key_ArrowLeft' or 'ArrowLeft') or a named button ('Action_Primary'). */
|
|
62
|
+
press(action: string, frames?: number): void;
|
|
63
|
+
/** Let go of something press() is holding. */
|
|
64
|
+
release(action: string): void;
|
|
65
|
+
/** Tap a control by node name/id: down now, up a few ticks later. */
|
|
66
|
+
tap(target: string): void;
|
|
67
|
+
/** Steer an input axis to -1..1. On physical-input this deflects the live joystick. */
|
|
68
|
+
axis(name: string, value: number): void;
|
|
69
|
+
/** Point the pointer at a world position (aim, hover, click-to-move). */
|
|
70
|
+
moveTo(point: BotPoint): void;
|
|
71
|
+
|
|
72
|
+
// -- protocol --------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
/** One line in the run report — how the policy explains its own reasoning. */
|
|
75
|
+
log(event: string): void;
|
|
76
|
+
/** End the run with the policy's verdict and the reason, in words. First call wins. */
|
|
77
|
+
done(pass: boolean, reason: string): void;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
declare interface BotPolicy {
|
|
81
|
+
/** Optional label for the report; the file name is used when absent. */
|
|
82
|
+
name?: string;
|
|
83
|
+
/** Runs once before the first tick. */
|
|
84
|
+
start?(bot: Pix3TestBot): void;
|
|
85
|
+
/** Runs once per logic tick until done() or the budget ends. */
|
|
86
|
+
tick(bot: Pix3TestBot): void;
|
|
87
|
+
/** Runs once after the last tick, whatever ended the run. */
|
|
88
|
+
end?(bot: Pix3TestBot): void;
|
|
89
|
+
}
|
package/kit/kit.json
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"format": 1,
|
|
3
|
-
"version": "
|
|
4
|
-
"inputsStamp": "
|
|
3
|
+
"version": "2.0.0-alpha.0",
|
|
4
|
+
"inputsStamp": "2191b8f1a8e23d36c45892f3616f747dd3f429eeb427c447163b16e4586e26dc",
|
|
5
5
|
"files": [
|
|
6
|
+
".claude/skills/pix3-editor/SKILL.md",
|
|
6
7
|
".claude/skills/pix3-nodes/SKILL.md",
|
|
7
8
|
".claude/skills/pix3-nodes/reference.md",
|
|
8
9
|
".claude/skills/pix3-scene-format/SKILL.md",
|
|
10
|
+
".claude/skills/pix3-scene-format/pix3anim.md",
|
|
11
|
+
".claude/skills/pix3-scene-format/project-files.md",
|
|
9
12
|
".claude/skills/pix3-scene-format/reference.md",
|
|
10
13
|
".claude/skills/pix3-scripts/SKILL.md",
|
|
11
14
|
".claude/skills/pix3-scripts/reference.md",
|
|
12
15
|
".claude/skills/pix3-verify/SKILL.md",
|
|
13
16
|
".claude/skills/pix3-verify/reference.md",
|
|
14
17
|
"AGENTS.md",
|
|
15
|
-
"CLAUDE.md"
|
|
18
|
+
"CLAUDE.md",
|
|
19
|
+
"design/tests/bots/pix3-test-bot.d.ts"
|
|
16
20
|
],
|
|
17
21
|
"sources": [
|
|
18
22
|
"docs/node-types-reference.md",
|
|
19
23
|
"docs/nodes-and-systems.md",
|
|
20
24
|
"docs/pix3-specification.md",
|
|
21
|
-
"packages/
|
|
22
|
-
"src/services/agent/agent-skills/engine-api-map.md"
|
|
25
|
+
"packages/cli/kit-includes/engine-api-map.md"
|
|
23
26
|
]
|
|
24
27
|
}
|
package/package.json
CHANGED
|
@@ -1,54 +1,62 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@pix3/cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Pix3 command line: create a project
|
|
5
|
-
"type": "module",
|
|
6
|
-
"repository": {
|
|
7
|
-
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/pix3dev/pix3.git",
|
|
9
|
-
"directory": "packages/
|
|
10
|
-
},
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"dist"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@pix3/cli",
|
|
3
|
+
"version": "2.0.0-alpha.0",
|
|
4
|
+
"description": "Pix3 command line: create a project, check and smoke-test it, open the editor in Chrome for your coding agent (Claude Code, Codex, ...) and configure chrome-devtools-mcp for it.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/pix3dev/pix3-core.git",
|
|
9
|
+
"directory": "packages/cli"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/pix3dev/pix3-core/tree/main/packages/cli#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/pix3dev/pix3-core/issues"
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"pix3": "dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"main": "dist/index.js",
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"templates",
|
|
22
|
+
"kit",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=24.15.0 <25"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"start": "node src/index.ts",
|
|
31
|
+
"build": "tsc -p tsconfig.build.json && node scripts/build-bin.mjs && node scripts/build-validate.mjs && node scripts/build-smoke.mjs",
|
|
32
|
+
"copy-templates": "node scripts/copy-templates.mjs",
|
|
33
|
+
"prepack": "npm run copy-templates && npm run build && npm run build-runtime-types && npm run build-kit",
|
|
34
|
+
"postpack": "node scripts/copy-templates.mjs --clean",
|
|
35
|
+
"type-check": "tsc --noEmit && tsc --noEmit -p tsconfig.build.json",
|
|
36
|
+
"build-kit": "node scripts/build-kit.mjs",
|
|
37
|
+
"build-runtime-types": "node scripts/build-runtime-types.mjs"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"pix3",
|
|
41
|
+
"cli",
|
|
42
|
+
"mcp",
|
|
43
|
+
"game-engine",
|
|
44
|
+
"agent"
|
|
45
|
+
],
|
|
46
|
+
"license": "Apache-2.0",
|
|
47
|
+
"optionalDependencies": {
|
|
48
|
+
"esbuild": "^0.27.3"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@pix3/runtime": "2.0.0-alpha.0",
|
|
52
|
+
"@types/node": "^24.5.2",
|
|
53
|
+
"@types/ws": "^8.18.1",
|
|
54
|
+
"typescript": "~5.8.3",
|
|
55
|
+
"ws": "^8.18.0",
|
|
56
|
+
"yaml": "^2.6.0"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public",
|
|
60
|
+
"tag": "next"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Pix3 Scene File (YAML). The entry scene of an empty 2D project: a root that stretches over the
|
|
2
|
+
# viewport (pix3project.yaml → viewportBaseSize) and a background. Add nodes under game-root.
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
metadata:
|
|
5
|
+
description: Entry scene
|
|
6
|
+
root:
|
|
7
|
+
- id: game-root
|
|
8
|
+
type: Group2D
|
|
9
|
+
name: Game Root
|
|
10
|
+
properties:
|
|
11
|
+
width: 1920
|
|
12
|
+
height: 1080
|
|
13
|
+
layout:
|
|
14
|
+
enabled: true
|
|
15
|
+
horizontalAlign: stretch
|
|
16
|
+
verticalAlign: stretch
|
|
17
|
+
children:
|
|
18
|
+
- id: background
|
|
19
|
+
type: ColorRect2D
|
|
20
|
+
name: Background
|
|
21
|
+
properties:
|
|
22
|
+
color: "#1a1a2e"
|
|
23
|
+
layout: # stretched over the root: the margins size it, no width/height
|
|
24
|
+
enabled: true
|
|
25
|
+
horizontalAlign: stretch
|
|
26
|
+
verticalAlign: stretch
|
|
27
|
+
left: 0
|
|
28
|
+
right: 0
|
|
29
|
+
top: 0
|
|
30
|
+
bottom: 0
|
|
31
|
+
children: []
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
id: 2d
|
|
2
|
+
title: Empty 2D
|
|
3
|
+
description: An empty 2D project — one scene with a stretched 2D root and a background, nothing that plays.
|
|
4
|
+
# Shared project files (package.json, vite.config.ts, index.html, src/main.ts, tsconfig.json …)
|
|
5
|
+
# come from templates/base; this layer adds the 2D scene.
|
|
6
|
+
extends: base
|
|
7
|
+
projectType: 2d
|
|
8
|
+
targetPlatform: universal
|
|
9
|
+
viewport: { width: 1920, height: 1080 }
|
|
10
|
+
entryScene: scenes/main.pix3scene
|
|
11
|
+
order: 10
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Pix3 Scene File (YAML). The entry scene of an empty 3D project: a camera, a key light and an
|
|
2
|
+
# ambient fill. Add meshes under game-root; 2D HUD nodes go beside it as top-level 2D nodes.
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
metadata:
|
|
5
|
+
description: Entry scene
|
|
6
|
+
root:
|
|
7
|
+
- id: game-root
|
|
8
|
+
type: Node3D
|
|
9
|
+
name: Game Root
|
|
10
|
+
properties:
|
|
11
|
+
transform:
|
|
12
|
+
position: [0, 0, 0]
|
|
13
|
+
rotationEuler: [0, 0, 0]
|
|
14
|
+
scale: [1, 1, 1]
|
|
15
|
+
children:
|
|
16
|
+
- id: main-camera
|
|
17
|
+
type: Camera3D
|
|
18
|
+
name: Main Camera
|
|
19
|
+
properties:
|
|
20
|
+
projection: perspective
|
|
21
|
+
fov: 60
|
|
22
|
+
near: 0.1
|
|
23
|
+
far: 1000
|
|
24
|
+
transform:
|
|
25
|
+
position: [0, 2, 6]
|
|
26
|
+
rotationEuler: [-10, 0, 0]
|
|
27
|
+
scale: [1, 1, 1]
|
|
28
|
+
children: []
|
|
29
|
+
- id: key-light
|
|
30
|
+
type: DirectionalLightNode
|
|
31
|
+
name: Key Light
|
|
32
|
+
properties:
|
|
33
|
+
intensity: 1.2
|
|
34
|
+
color: "#ffffff"
|
|
35
|
+
transform:
|
|
36
|
+
position: [5, 8, 3]
|
|
37
|
+
rotationEuler: [-45, 35, 0]
|
|
38
|
+
scale: [1, 1, 1]
|
|
39
|
+
children: []
|
|
40
|
+
- id: ambient-light
|
|
41
|
+
type: AmbientLightNode
|
|
42
|
+
name: Ambient Light
|
|
43
|
+
properties:
|
|
44
|
+
intensity: 0.5
|
|
45
|
+
color: "#ffffff"
|
|
46
|
+
transform:
|
|
47
|
+
position: [0, 0, 0]
|
|
48
|
+
rotationEuler: [0, 0, 0]
|
|
49
|
+
scale: [1, 1, 1]
|
|
50
|
+
children: []
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
id: 3d
|
|
2
|
+
title: Empty 3D
|
|
3
|
+
description: An empty 3D project — one scene with a camera and lights, nothing that plays.
|
|
4
|
+
# Shared project files (package.json, vite.config.ts, index.html, src/main.ts, tsconfig.json …)
|
|
5
|
+
# come from templates/base; this layer adds the 3D scene.
|
|
6
|
+
extends: base
|
|
7
|
+
projectType: 3d
|
|
8
|
+
targetPlatform: universal
|
|
9
|
+
viewport: { width: 1920, height: 1080 }
|
|
10
|
+
entryScene: scenes/main.pix3scene
|
|
11
|
+
order: 20
|