@pix3/cli 1.6.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 (155) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +754 -0
  3. package/dist/index.js +494 -0
  4. package/dist/runtime-types.json +1 -0
  5. package/dist/smoke/prebuilt/build-7MIXIMSZ.mjs +948 -0
  6. package/dist/smoke/prebuilt/chunk-J2SJVMDO.mjs +2 -0
  7. package/dist/smoke/prebuilt/chunk-OJXQXIIQ.mjs +239 -0
  8. package/dist/smoke/prebuilt/chunk-P2CBRXPJ.mjs +4050 -0
  9. package/dist/smoke/prebuilt/runtime.mjs +2 -0
  10. package/dist/smoke/prebuilt/smoke-worker.mjs +3 -0
  11. package/dist/smoke/prebuilt/three.mjs +2 -0
  12. package/dist/smoke/prebuilt/tree-defaults.mjs +2 -0
  13. package/dist/validate/prebuilt/build-AUGKXER3.js +948 -0
  14. package/dist/validate/prebuilt/bundle-main.js +24 -0
  15. package/dist/validate/prebuilt/chunk-6ACT6FNV.js +4050 -0
  16. package/dist/validate/prebuilt/chunk-BS2OZM7U.js +239 -0
  17. package/dist/validate/prebuilt/runtime.js +2 -0
  18. package/dist/validate/prebuilt/three.js +2 -0
  19. package/kit/files/.claude/skills/pix3-nodes/SKILL.md +210 -0
  20. package/kit/files/.claude/skills/pix3-nodes/reference.md +1331 -0
  21. package/kit/files/.claude/skills/pix3-scene-format/SKILL.md +235 -0
  22. package/kit/files/.claude/skills/pix3-scene-format/reference.md +176 -0
  23. package/kit/files/.claude/skills/pix3-scripts/SKILL.md +281 -0
  24. package/kit/files/.claude/skills/pix3-scripts/reference.md +638 -0
  25. package/kit/files/.claude/skills/pix3-verify/SKILL.md +386 -0
  26. package/kit/files/.claude/skills/pix3-verify/reference.md +21 -0
  27. package/kit/files/AGENTS.md +203 -0
  28. package/kit/files/CLAUDE.md +1 -0
  29. package/kit/kit.json +24 -0
  30. package/package.json +54 -0
  31. package/templates/empty-2d/files/README.md +20 -0
  32. package/templates/empty-2d/files/scenes/main.pix3scene +68 -0
  33. package/templates/empty-2d/files/sprites/pix3-logo.png +0 -0
  34. package/templates/empty-2d/template.yaml +7 -0
  35. package/templates/empty-3d/files/README.md +20 -0
  36. package/templates/empty-3d/files/scenes/main.pix3scene +108 -0
  37. package/templates/empty-3d/files/sprites/pix3-logo.png +0 -0
  38. package/templates/empty-3d/template.yaml +7 -0
  39. package/templates/idea-blank/files/README.md +22 -0
  40. package/templates/idea-blank/files/scenes/main.pix3scene +37 -0
  41. package/templates/idea-blank/template.yaml +10 -0
  42. package/templates/minigame-2d/files/README.md +44 -0
  43. package/templates/minigame-2d/files/design/tests/reachability.json +1 -0
  44. package/templates/minigame-2d/files/design/tests/routines/mute-music.json +44 -0
  45. package/templates/minigame-2d/files/scenes/main.pix3scene +84 -0
  46. package/templates/minigame-2d/files/scenes/menu.pix3scene +118 -0
  47. package/templates/minigame-2d/files/scenes/ui/settings-window.pix3scene +138 -0
  48. package/templates/minigame-2d/files/scripts/GameFlow.ts +133 -0
  49. package/templates/minigame-2d/files/scripts/MenuFlow.ts +217 -0
  50. package/templates/minigame-2d/files/scripts/SettingsWindow.ts +198 -0
  51. package/templates/minigame-2d/template.yaml +10 -0
  52. package/templates/playable-2d/files/README.md +30 -0
  53. package/templates/playable-2d/files/design/recipe.md +83 -0
  54. package/templates/playable-2d/files/design/tests/reachability.json +4 -0
  55. package/templates/playable-2d/files/design/tests/routines/intro-to-cta.json +32 -0
  56. package/templates/playable-2d/files/scenes/main.pix3scene +111 -0
  57. package/templates/playable-2d/files/scenes/ui/end-screen.pix3scene +91 -0
  58. package/templates/playable-2d/files/scenes/ui/intro.pix3scene +65 -0
  59. package/templates/playable-2d/files/scripts/CtaButton.ts +55 -0
  60. package/templates/playable-2d/files/scripts/GameFlow.ts +256 -0
  61. package/templates/playable-2d/files/sprites/pix3-logo.png +0 -0
  62. package/templates/playable-2d/template.yaml +9 -0
  63. package/templates/playable-3d/files/README.md +32 -0
  64. package/templates/playable-3d/files/design/recipe.md +127 -0
  65. package/templates/playable-3d/files/design/tests/reachability.json +4 -0
  66. package/templates/playable-3d/files/design/tests/routines/intro-to-cta.json +32 -0
  67. package/templates/playable-3d/files/scenes/main.pix3scene +230 -0
  68. package/templates/playable-3d/files/scenes/ui/end-screen.pix3scene +91 -0
  69. package/templates/playable-3d/files/scenes/ui/intro.pix3scene +65 -0
  70. package/templates/playable-3d/files/scripts/CtaButton.ts +55 -0
  71. package/templates/playable-3d/files/scripts/GameFlow.ts +309 -0
  72. package/templates/playable-3d/files/scripts/GameRules.ts +290 -0
  73. package/templates/playable-3d/files/scripts/ScoreHud.ts +113 -0
  74. package/templates/playable-3d/template.yaml +9 -0
  75. package/templates/recipe-arena-2d/files/README.md +48 -0
  76. package/templates/recipe-arena-2d/files/design/recipe.md +127 -0
  77. package/templates/recipe-arena-2d/files/design/tests/reachability.json +4 -0
  78. package/templates/recipe-arena-2d/files/design/tests/routines/terminal-retry.json +23 -0
  79. package/templates/recipe-arena-2d/files/scenes/main.pix3scene +292 -0
  80. package/templates/recipe-arena-2d/files/scenes/menu.pix3scene +100 -0
  81. package/templates/recipe-arena-2d/files/scenes/prefabs/hazard.pix3scene +42 -0
  82. package/templates/recipe-arena-2d/files/scenes/prefabs/pickup.pix3scene +45 -0
  83. package/templates/recipe-arena-2d/files/scenes/ui/result.pix3scene +85 -0
  84. package/templates/recipe-arena-2d/files/scripts/GameRules.ts +368 -0
  85. package/templates/recipe-arena-2d/files/scripts/MenuFlow.ts +106 -0
  86. package/templates/recipe-arena-2d/files/scripts/PlayerController.ts +151 -0
  87. package/templates/recipe-arena-2d/files/scripts/ScoreHud.ts +94 -0
  88. package/templates/recipe-arena-2d/files/scripts/Spawner.ts +214 -0
  89. package/templates/recipe-arena-2d/files/scripts/TouchRules.ts +174 -0
  90. package/templates/recipe-arena-2d/files/sprites/ph-avatar.png +0 -0
  91. package/templates/recipe-arena-2d/files/sprites/ph-hazard.png +0 -0
  92. package/templates/recipe-arena-2d/files/sprites/ph-pickup.png +0 -0
  93. package/templates/recipe-arena-2d/template.yaml +10 -0
  94. package/templates/recipe-blank-2d/files/README.md +61 -0
  95. package/templates/recipe-blank-2d/files/design/recipe.md +148 -0
  96. package/templates/recipe-blank-2d/files/design/tests/reachability.json +4 -0
  97. package/templates/recipe-blank-2d/files/design/tests/routines/restart.json +27 -0
  98. package/templates/recipe-blank-2d/files/design/tests/routines/terminal-retry.json +23 -0
  99. package/templates/recipe-blank-2d/files/scenes/main.pix3scene +224 -0
  100. package/templates/recipe-blank-2d/files/scenes/ui/result.pix3scene +85 -0
  101. package/templates/recipe-blank-2d/files/scripts/GameRules.ts +350 -0
  102. package/templates/recipe-blank-2d/files/scripts/ScoreHud.ts +110 -0
  103. package/templates/recipe-blank-2d/files/sprites/ph-bg.png +0 -0
  104. package/templates/recipe-blank-2d/files/sprites/ph-capsule.png +0 -0
  105. package/templates/recipe-blank-2d/files/sprites/ph-circle.png +0 -0
  106. package/templates/recipe-blank-2d/files/sprites/ph-orb.png +0 -0
  107. package/templates/recipe-blank-2d/files/sprites/ph-ring.png +0 -0
  108. package/templates/recipe-blank-2d/files/sprites/ph-star.png +0 -0
  109. package/templates/recipe-blank-2d/template.yaml +10 -0
  110. package/templates/recipe-bouncer-2d/files/README.md +81 -0
  111. package/templates/recipe-bouncer-2d/files/design/recipe.md +146 -0
  112. package/templates/recipe-bouncer-2d/files/design/tests/reachability.json +4 -0
  113. package/templates/recipe-bouncer-2d/files/design/tests/routines/terminal-retry.json +23 -0
  114. package/templates/recipe-bouncer-2d/files/scenes/main.pix3scene +615 -0
  115. package/templates/recipe-bouncer-2d/files/scenes/menu.pix3scene +191 -0
  116. package/templates/recipe-bouncer-2d/files/scenes/ui/result.pix3scene +87 -0
  117. package/templates/recipe-bouncer-2d/files/scripts/BallBody.ts +298 -0
  118. package/templates/recipe-bouncer-2d/files/scripts/GameRules.ts +377 -0
  119. package/templates/recipe-bouncer-2d/files/scripts/MenuFlow.ts +109 -0
  120. package/templates/recipe-bouncer-2d/files/scripts/PaddleController.ts +112 -0
  121. package/templates/recipe-bouncer-2d/files/scripts/ScoreHud.ts +94 -0
  122. package/templates/recipe-bouncer-2d/files/scripts/TouchRules.ts +263 -0
  123. package/templates/recipe-bouncer-2d/files/scripts/ball-collision.ts +307 -0
  124. package/templates/recipe-bouncer-2d/files/sprites/ph-ball.png +0 -0
  125. package/templates/recipe-bouncer-2d/files/sprites/ph-bg.png +0 -0
  126. package/templates/recipe-bouncer-2d/files/sprites/ph-bumper.png +0 -0
  127. package/templates/recipe-bouncer-2d/files/sprites/ph-paddle.png +0 -0
  128. package/templates/recipe-bouncer-2d/template.yaml +10 -0
  129. package/templates/recipe-grid-3d/files/README.md +22 -0
  130. package/templates/recipe-grid-3d/files/design/recipe.md +110 -0
  131. package/templates/recipe-grid-3d/files/scenes/main.pix3scene +169 -0
  132. package/templates/recipe-grid-3d/files/scenes/menu.pix3scene +100 -0
  133. package/templates/recipe-grid-3d/files/scenes/ui/result.pix3scene +105 -0
  134. package/templates/recipe-grid-3d/files/scripts/GridBoard.ts +319 -0
  135. package/templates/recipe-grid-3d/files/scripts/GridRules.ts +278 -0
  136. package/templates/recipe-grid-3d/files/scripts/MenuFlow.ts +106 -0
  137. package/templates/recipe-grid-3d/files/scripts/ScoreHud.ts +94 -0
  138. package/templates/recipe-grid-3d/template.yaml +10 -0
  139. package/templates/recipe-tapper-2d/files/README.md +39 -0
  140. package/templates/recipe-tapper-2d/files/design/recipe.md +132 -0
  141. package/templates/recipe-tapper-2d/files/design/tests/reachability.json +4 -0
  142. package/templates/recipe-tapper-2d/files/design/tests/routines/terminal-retry.json +23 -0
  143. package/templates/recipe-tapper-2d/files/scenes/main.pix3scene +269 -0
  144. package/templates/recipe-tapper-2d/files/scenes/menu.pix3scene +100 -0
  145. package/templates/recipe-tapper-2d/files/scenes/prefabs/hazard.pix3scene +42 -0
  146. package/templates/recipe-tapper-2d/files/scenes/prefabs/target.pix3scene +45 -0
  147. package/templates/recipe-tapper-2d/files/scenes/ui/result.pix3scene +85 -0
  148. package/templates/recipe-tapper-2d/files/scripts/GameRules.ts +368 -0
  149. package/templates/recipe-tapper-2d/files/scripts/MenuFlow.ts +106 -0
  150. package/templates/recipe-tapper-2d/files/scripts/ScoreHud.ts +94 -0
  151. package/templates/recipe-tapper-2d/files/scripts/Spawner.ts +214 -0
  152. package/templates/recipe-tapper-2d/files/scripts/TouchRules.ts +192 -0
  153. package/templates/recipe-tapper-2d/files/sprites/ph-hazard.png +0 -0
  154. package/templates/recipe-tapper-2d/files/sprites/ph-target.png +0 -0
  155. package/templates/recipe-tapper-2d/template.yaml +10 -0
@@ -0,0 +1,110 @@
1
+ # Recipe: recipe-grid-3d
2
+
3
+ ## What this is
4
+
5
+ The 3D carving shape: a solid block of cubes, a perspective camera looking at
6
+ it, and a tap that removes one cube. Some cubes are **core** — hitting one costs
7
+ a life. Clear every non-core cube and the run is won.
8
+
9
+ Voxel carving, 3D minesweeper, layer puzzles, tap-to-mine, "chip away to reveal
10
+ the shape". If the idea is a 3D thing you touch, start here; if it is a flat
11
+ board of tiles, `recipe-tapper-2d` is the cheaper shape.
12
+
13
+ **The cubes are generated, not authored.** `GridBoard` builds them under
14
+ `board-anchor` on start, so the board size is a config number
15
+ (`sizeX`/`sizeY`/`sizeZ`), not a scene edit. Do not hand-place cubes in the
16
+ scene — they would not be in the board's map and taps would ignore them.
17
+
18
+ **Picking is a 3D raycast.** `GridBoard` converts the pointer to normalized
19
+ device coordinates and calls `scene.raycastViewport(nx, ny)`. There are no
20
+ `Hitbox2D` groups on a mesh, so the 2D collision helpers do nothing here.
21
+
22
+ **Lighting is load-bearing.** `key-light` + `fill-light` are why the block is
23
+ visible; lit materials with no light render pure black, and the editor viewport
24
+ hides that by adding fallback lights the running game does not have. If
25
+ something comes out black, read `sceneIssues` in `scene_tree` / `game_observe`.
26
+
27
+ **Mobile is the default target.** Every cube is `material.type: lambert` — a
28
+ 4×4×4 board is 64 meshes, and PBR at that count is a phone's whole frame budget.
29
+ Past ~8³ move to an `InstancedMesh3D` before you reach for prettier materials.
30
+
31
+ ## Node map
32
+
33
+ | id | what |
34
+ | --- | --- |
35
+ | `game-root` | 3D scene root; hosts **both** `GridBoard` and `GridRules` |
36
+ | `main-camera` | `Camera3D`, perspective, framed on the block from `[6, 6, 8]` |
37
+ | `key-light` | `DirectionalLightNode` — the shading light |
38
+ | `fill-light` | `HemisphereLightNode` — keeps unlit faces readable |
39
+ | `board-anchor` | empty `Node3D` the generated cubes are parented to; the board centres itself on it |
40
+ | `hud-root` | 2D UI layer; hosts `ScoreHud` |
41
+ | `score-label` | cleared-cube counter |
42
+ | `lives-bar` | `Bar2D` driven by `lives-changed` |
43
+ | `result-overlay` → `result-dim`, `result-label`, `retry-button`, `menu-button` | end screen; own file `scenes/ui/result.pix3scene`, instanced into main with `visible: false` (editor-only hide — `GridRules` shows it) |
44
+
45
+ Signals, all emitted on `game-root` by `GridBoard` and consumed by `GridRules`:
46
+ `board-built` (clearable, cores) · `cell-cleared` (remaining) · `core-hit`
47
+ (remaining) · `board-cleared`.
48
+
49
+ ## Placeholders
50
+
51
+ | role | file | node |
52
+ | --- | --- | --- |
53
+ | cube | (none — generated `GeometryMesh`, coloured by `cellColor`) | `board-anchor` children |
54
+
55
+ ## Tunables
56
+
57
+ ```yaml
58
+ tunables:
59
+ sizeX: { node: game-root, component: "user:GridBoard", property: sizeX, min: 1, max: 10, default: 4 }
60
+ sizeY: { node: game-root, component: "user:GridBoard", property: sizeY, min: 1, max: 10, default: 4 }
61
+ sizeZ: { node: game-root, component: "user:GridBoard", property: sizeZ, min: 1, max: 10, default: 4 }
62
+ coreCount: { node: game-root, component: "user:GridBoard", property: coreCount, min: 0, max: 40, default: 6 }
63
+ cellSize: { node: game-root, component: "user:GridBoard", property: cellSize, min: 0.1, max: 3, default: 0.9 }
64
+ spacing: { node: game-root, component: "user:GridBoard", property: spacing, min: 0.1, max: 4, default: 1 }
65
+ cellColor: { node: game-root, component: "user:GridBoard", property: cellColor, default: "#3ee6c1" }
66
+ coreColor: { node: game-root, component: "user:GridBoard", property: coreColor, default: "#ff6b6b" }
67
+ revealCores: { node: game-root, component: "user:GridBoard", property: revealCores, default: false }
68
+ startingLives: { node: game-root, component: "user:GridRules", property: startingLives, min: 1, max: 9, default: 3 }
69
+ timeLimitSec: { node: game-root, component: "user:GridRules", property: timeLimitSec, min: 0, max: 600, default: 0 }
70
+ ```
71
+
72
+ `component` present → `set_component_property`; absent → `set_property`.
73
+
74
+ ## Extension points
75
+
76
+ - **A shape inside the block.** `pickCoreKeys` chooses cores at random from the
77
+ interior; replace it with a lookup into your own voxel shape and the game
78
+ becomes "carve until the statue appears".
79
+ - **Layer rules.** `GridBoard.removeCell` is the one place a removal happens —
80
+ add a cascade (remove neighbours), a combo counter, or a rule that only
81
+ exposed cubes may be tapped, all from there.
82
+ - **Camera moves.** Animate `main-camera`'s transform, or add a
83
+ `VirtualCamera3D` rig, to let the player orbit the block between taps.
84
+ - **Feel.** `clearSound` / `coreSound` take a `res://` audio path; the punch and
85
+ the red flash are already wired through `scene.juice`.
86
+
87
+ ## Do not touch
88
+
89
+ - **`key-light` / `fill-light`.** Remove them and every cube renders black.
90
+ - **`main-camera`.** No enabled `Camera3D` means nothing 3D is drawn at all, and
91
+ the raycast has no camera to shoot through — taps stop working too.
92
+ - **`board-anchor`'s id.** `GridBoard.boardAnchor` addresses it by name; renaming
93
+ one without the other leaves the board unbuilt (it logs a warning and stops).
94
+ - **The `game-root` id.** Portable tests and routines address the run through it.
95
+
96
+ ## Verify
97
+
98
+ - `play_start`, then `game_observe` — `sceneIssues` must be **absent**, and
99
+ `game.snapshot()` carries `remaining` (cubes still to clear).
100
+ - Tap the block: `game_input {type:'tap', x:0, y:0}` and assert `remaining` went
101
+ **down** in `game.changed`. That is the proof a tap reached the board — not a
102
+ screenshot, which the editor's fallback lighting can flatter. Note the units:
103
+ tap coordinates are 2D world space, which is **centred on the origin**, so the
104
+ middle of the screen is `(0, 0)` and not `(540, 960)`.
105
+ - Win: set `sizeX/sizeY/sizeZ: 1` and `coreCount: 0`, then one tap clears the
106
+ board. Read the *transition*, not the end state: the win overlay appears on the
107
+ pointer-DOWN that clears the last cube, so the matching pointer-UP can land on
108
+ the RETRY button underneath the finger and start a fresh run before you look.
109
+ Assert on `board-cleared` / `game-won`, or tap a last cube that is not under
110
+ the end screen's buttons.
@@ -0,0 +1,169 @@
1
+ # Pix3 Scene File (YAML)
2
+ # Grid 3D — the carving board. The cubes are NOT authored here: GridBoard builds
3
+ # them under `board-anchor` at start, so the board size is a tunable, not a
4
+ # hand-edited tree. Everything else (camera, lights, HUD) is authored here; the
5
+ # end screen lives in scenes/ui/result.pix3scene and is instanced in hidden
6
+ # (`visible: false` = editor only), so this scene opens on the board.
7
+ #
8
+ # Stable node ids (design/recipe.md is the contract — do not rename these):
9
+ # game-root, main-camera, key-light, fill-light, board-anchor,
10
+ # hud-root, score-label, lives-bar,
11
+ # result-overlay, result-label, retry-button, menu-button (scenes/ui/result.pix3scene)
12
+ version: 1.0.0
13
+ metadata:
14
+ author: Pix3 Template
15
+ description: Tap-to-carve 3D grid with a hidden core
16
+ root:
17
+ - id: game-root
18
+ type: Node3D
19
+ name: Game Root
20
+ properties:
21
+ transform:
22
+ position: [0, 0, 0]
23
+ rotationEuler: [0, 0, 0]
24
+ scale: [1, 1, 1]
25
+ components:
26
+ - id: grid-board
27
+ type: user:GridBoard
28
+ enabled: true
29
+ config:
30
+ boardAnchor: board-anchor
31
+ sizeX: 4
32
+ sizeY: 4
33
+ sizeZ: 4
34
+ cellSize: 0.9
35
+ spacing: 1
36
+ coreCount: 6
37
+ cellColor: "#3ee6c1"
38
+ coreColor: "#ff6b6b"
39
+ revealCores: false
40
+ - id: grid-rules
41
+ type: user:GridRules
42
+ enabled: true
43
+ config:
44
+ startingLives: 3
45
+ timeLimitSec: 0
46
+ resultNode: result-overlay
47
+ resultLabel: result-label
48
+ retryButton: retry-button
49
+ menuButton: menu-button
50
+ children:
51
+ - id: main-camera
52
+ type: Camera3D
53
+ name: Main Camera
54
+ properties:
55
+ projection: perspective
56
+ fov: 50
57
+ near: 0.1
58
+ far: 200
59
+ # Aimed exactly at the origin, where the board centres itself. Solved for the engine's
60
+ # XYZ Euler order (R = Rx·Ry), NOT the yaw-then-pitch YXZ order the numbers would have
61
+ # under a camera rig: pitch = -asin(0.6) = -36.87°, yaw = asin(6/|[6,6,8]|) = 30.96°.
62
+ # Swap the two and the view tilts off target — invisible on a full board (some cube
63
+ # still catches the centre ray) and fatal on a 1x1x1 one, which is why the recipe's
64
+ # Verify section shrinks the board.
65
+ transform:
66
+ position: [6, 6, 8]
67
+ rotationEuler: [-36.87, 30.96, 0]
68
+ scale: [1, 1, 1]
69
+ children: []
70
+ - id: key-light
71
+ type: DirectionalLightNode
72
+ name: Key Light
73
+ properties:
74
+ intensity: 1.1
75
+ color: "#ffffff"
76
+ transform:
77
+ position: [6, 9, 4]
78
+ rotationEuler: [-50, 30, 0]
79
+ scale: [1, 1, 1]
80
+ children: []
81
+ - id: fill-light
82
+ type: HemisphereLightNode
83
+ name: Fill Light
84
+ properties:
85
+ skyColor: "#e9f5ff"
86
+ groundColor: "#717786"
87
+ intensity: 0.7
88
+ transform:
89
+ position: [0, 0, 0]
90
+ rotationEuler: [0, 0, 0]
91
+ scale: [1, 1, 1]
92
+ children: []
93
+ - id: board-anchor
94
+ type: Node3D
95
+ name: Board Anchor
96
+ properties:
97
+ transform:
98
+ position: [0, 0, 0]
99
+ rotationEuler: [0, 0, 0]
100
+ scale: [1, 1, 1]
101
+ children: []
102
+
103
+ - id: hud-root
104
+ type: Group2D
105
+ name: HUD Root
106
+ properties:
107
+ width: 1080
108
+ height: 1920
109
+ layout:
110
+ enabled: true
111
+ horizontalAlign: stretch
112
+ verticalAlign: stretch
113
+ components:
114
+ - id: score-hud
115
+ type: user:ScoreHud
116
+ enabled: true
117
+ config:
118
+ sourceNode: game-root
119
+ scoreLabel: score-label
120
+ scoreFormat: "CLEARED {value}"
121
+ timeLabel: ""
122
+ livesBar: lives-bar
123
+ children:
124
+ - id: score-label
125
+ type: Label2D
126
+ name: Score Label
127
+ properties:
128
+ label: "CLEARED 0"
129
+ labelFontSize: 48
130
+ labelColor: "#f2f2f2"
131
+ labelAlign: center
132
+ transform:
133
+ position: [0, 820]
134
+ scale: [1, 1]
135
+ rotation: 0
136
+ layout:
137
+ enabled: true
138
+ horizontalAlign: center
139
+ verticalAlign: top
140
+ children: []
141
+ - id: lives-bar
142
+ type: Bar2D
143
+ name: Lives Bar
144
+ properties:
145
+ width: 360
146
+ height: 26
147
+ value: 3
148
+ maxValue: 3
149
+ barColor: "#ff6b6b"
150
+ backBackgroundColor: "#1b1f2a"
151
+ transform:
152
+ position: [0, 740]
153
+ scale: [1, 1]
154
+ rotation: 0
155
+ layout:
156
+ enabled: true
157
+ horizontalAlign: center
158
+ verticalAlign: top
159
+ children: []
160
+ # Win/lose screen — authored in scenes/ui/result.pix3scene so this scene
161
+ # opens on the BOARD, not on an end card. `visible: false` hides it in the
162
+ # EDITOR only; `initiallyVisible` (in the overlay file) is what play mode
163
+ # reads, and GridRules reveals it on the win/lose transition. Tick the eye
164
+ # to preview it composited over the board.
165
+ - id: result-overlay
166
+ name: Result Overlay
167
+ instance: res://scenes/ui/result.pix3scene
168
+ properties:
169
+ visible: false
@@ -0,0 +1,100 @@
1
+ # Pix3 Scene File (YAML)
2
+ # Grid 3D — the MENU scene. This is the project's ENTRY / export scene
3
+ # (Project Settings → Default Export Scene Path): a full build and "Play Game (Entry Scene)"
4
+ # boot here. PLAY transitions to the game scene (main.pix3scene) via a fade.
5
+ # Wired by scripts/MenuFlow.ts. Iterate on the GAME in main.pix3scene.
6
+ version: 1.0.0
7
+ metadata:
8
+ author: Pix3 Recipe
9
+ description: Menu scene — entry point; PLAY transitions to the carving board
10
+ root:
11
+ - id: menu-root
12
+ type: Group2D
13
+ name: Menu Root
14
+ properties:
15
+ width: 1080
16
+ height: 1920
17
+ layout:
18
+ enabled: true
19
+ horizontalAlign: stretch
20
+ verticalAlign: stretch
21
+ components:
22
+ - id: menu-flow
23
+ type: user:MenuFlow
24
+ enabled: true
25
+ config:
26
+ gameScene: res://scenes/main.pix3scene
27
+ playButton: play-button
28
+ children:
29
+ - id: menu-background
30
+ type: ColorRect2D
31
+ name: Menu Background
32
+ properties:
33
+ width: 1080
34
+ height: 1920
35
+ color: "#1b1f2a"
36
+ transform:
37
+ position: [0, 0]
38
+ scale: [1, 1]
39
+ rotation: 0
40
+ layout:
41
+ enabled: true
42
+ horizontalAlign: stretch
43
+ verticalAlign: stretch
44
+ children: []
45
+ - id: title-label
46
+ type: Label2D
47
+ name: Title Label
48
+ properties:
49
+ label: "{{PROJECT_NAME}}"
50
+ labelFontSize: 96
51
+ labelColor: "#ffffff"
52
+ labelAlign: center
53
+ transform:
54
+ position: [0, 420]
55
+ scale: [1, 1]
56
+ rotation: 0
57
+ layout:
58
+ enabled: true
59
+ horizontalAlign: center
60
+ verticalAlign: center
61
+ children: []
62
+ - id: subtitle-label
63
+ type: Label2D
64
+ name: Subtitle Label
65
+ properties:
66
+ label: "CARVE THE BLOCK. SPARE THE CORE."
67
+ labelFontSize: 40
68
+ labelColor: "#93a3c9"
69
+ labelAlign: center
70
+ transform:
71
+ position: [0, 300]
72
+ scale: [1, 1]
73
+ rotation: 0
74
+ layout:
75
+ enabled: true
76
+ horizontalAlign: center
77
+ verticalAlign: center
78
+ children: []
79
+ - id: play-button
80
+ type: Button2D
81
+ name: Play Button
82
+ properties:
83
+ width: 480
84
+ height: 140
85
+ label: "PLAY"
86
+ labelFontSize: 56
87
+ labelColor: "#141a2e"
88
+ backgroundColor: "#f5ae39"
89
+ hoverColor: "#ffc862"
90
+ pressedColor: "#d4922a"
91
+ buttonAction: play
92
+ transform:
93
+ position: [0, -60]
94
+ scale: [1, 1]
95
+ rotation: 0
96
+ layout:
97
+ enabled: true
98
+ horizontalAlign: center
99
+ verticalAlign: center
100
+ children: []
@@ -0,0 +1,105 @@
1
+ # Pix3 Scene File (YAML)
2
+ # Grid 3D — the RESULT overlay (win/lose), in its own file so the board scene
3
+ # opens clean. `main.pix3scene` carries it as a one-line `instance:` reference
4
+ # marked `visible: false`, which hides it in the EDITOR only; `user:GridRules`
5
+ # reveals it at run time by setting `visible`.
6
+ #
7
+ # Edit it here, full-screen, in its own tab. To preview it composited over the
8
+ # board, tick the eye on `result-overlay` in main.pix3scene — just do not commit
9
+ # that tick, or every iteration starts behind an end screen again.
10
+ #
11
+ # Stable node ids (design/recipe.md is the contract — do not rename these):
12
+ # result-overlay, result-label, retry-button, menu-button
13
+ version: 1.0.0
14
+ metadata:
15
+ author: Pix3 Template
16
+ description: Result overlay — dim, win/lose headline, RETRY and MENU buttons
17
+ root:
18
+ - id: result-overlay
19
+ type: Group2D
20
+ name: Result Overlay
21
+ properties:
22
+ width: 1080
23
+ height: 1920
24
+ initiallyVisible: false
25
+ layout:
26
+ enabled: true
27
+ horizontalAlign: stretch
28
+ verticalAlign: stretch
29
+ children:
30
+ - id: result-dim
31
+ type: ColorRect2D
32
+ name: Result Dim
33
+ properties:
34
+ width: 1080
35
+ height: 1920
36
+ color: "#0b0e14"
37
+ opacity: 0.78
38
+ transform:
39
+ position: [0, 0]
40
+ scale: [1, 1]
41
+ rotation: 0
42
+ layout:
43
+ enabled: true
44
+ horizontalAlign: stretch
45
+ verticalAlign: stretch
46
+ children: []
47
+ - id: result-label
48
+ type: Label2D
49
+ name: Result Label
50
+ properties:
51
+ label: "SHAPE REVEALED"
52
+ labelFontSize: 76
53
+ labelColor: "#3ee6c1"
54
+ labelAlign: center
55
+ transform:
56
+ position: [0, 220]
57
+ scale: [1, 1]
58
+ rotation: 0
59
+ layout:
60
+ enabled: true
61
+ horizontalAlign: center
62
+ verticalAlign: center
63
+ children: []
64
+ - id: retry-button
65
+ type: Button2D
66
+ name: Retry Button
67
+ properties:
68
+ width: 420
69
+ height: 130
70
+ label: "RETRY"
71
+ labelFontSize: 52
72
+ labelColor: "#0b0e14"
73
+ backgroundColor: "#3ee6c1"
74
+ hoverColor: "#63f0d3"
75
+ pressedColor: "#2bbfa0"
76
+ transform:
77
+ position: [0, -60]
78
+ scale: [1, 1]
79
+ rotation: 0
80
+ layout:
81
+ enabled: true
82
+ horizontalAlign: center
83
+ verticalAlign: center
84
+ children: []
85
+ - id: menu-button
86
+ type: Button2D
87
+ name: Menu Button
88
+ properties:
89
+ width: 420
90
+ height: 110
91
+ label: "MENU"
92
+ labelFontSize: 44
93
+ labelColor: "#f2f2f2"
94
+ backgroundColor: "#1b1f2a"
95
+ hoverColor: "#2a3040"
96
+ pressedColor: "#141821"
97
+ transform:
98
+ position: [0, -220]
99
+ scale: [1, 1]
100
+ rotation: 0
101
+ layout:
102
+ enabled: true
103
+ horizontalAlign: center
104
+ verticalAlign: center
105
+ children: []