@pix3/cli 1.6.0 → 1.6.2

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 (126) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +788 -754
  3. package/dist/index.js +208 -203
  4. package/dist/runtime-types.json +1 -1
  5. package/dist/smoke/prebuilt/{chunk-J2SJVMDO.mjs → chunk-7MZGPAUK.mjs} +1 -1
  6. package/dist/smoke/prebuilt/chunk-7WOFGLW3.mjs +239 -0
  7. package/dist/smoke/prebuilt/runtime.mjs +1 -1
  8. package/dist/smoke/prebuilt/smoke-worker.mjs +1 -1
  9. package/dist/smoke/prebuilt/tree-defaults.mjs +1 -1
  10. package/dist/validate/prebuilt/bundle-main.js +13 -13
  11. package/dist/validate/prebuilt/chunk-HKG6YI6Y.js +239 -0
  12. package/dist/validate/prebuilt/runtime.js +1 -1
  13. package/kit/files/.claude/skills/pix3-nodes/SKILL.md +210 -210
  14. package/kit/files/.claude/skills/pix3-nodes/reference.md +32 -24
  15. package/kit/files/.claude/skills/pix3-scene-format/SKILL.md +238 -235
  16. package/kit/files/.claude/skills/pix3-scene-format/reference.md +28 -28
  17. package/kit/files/.claude/skills/pix3-scripts/SKILL.md +285 -281
  18. package/kit/files/.claude/skills/pix3-scripts/reference.md +69 -52
  19. package/kit/files/.claude/skills/pix3-verify/SKILL.md +298 -256
  20. package/kit/files/.claude/skills/pix3-verify/reference.md +21 -21
  21. package/kit/files/AGENTS.md +203 -203
  22. package/kit/files/CLAUDE.md +1 -1
  23. package/kit/kit.json +2 -2
  24. package/package.json +54 -54
  25. package/templates/empty-2d/files/README.md +20 -20
  26. package/templates/empty-2d/files/scenes/main.pix3scene +68 -68
  27. package/templates/empty-2d/template.yaml +7 -7
  28. package/templates/empty-3d/files/README.md +20 -20
  29. package/templates/empty-3d/files/scenes/main.pix3scene +108 -108
  30. package/templates/empty-3d/template.yaml +7 -7
  31. package/templates/idea-blank/files/README.md +22 -22
  32. package/templates/idea-blank/files/scenes/main.pix3scene +37 -37
  33. package/templates/idea-blank/template.yaml +10 -10
  34. package/templates/minigame-2d/files/README.md +44 -44
  35. package/templates/minigame-2d/files/design/tests/reachability.json +1 -1
  36. package/templates/minigame-2d/files/design/tests/routines/mute-music.json +44 -44
  37. package/templates/minigame-2d/files/scenes/main.pix3scene +84 -84
  38. package/templates/minigame-2d/files/scenes/menu.pix3scene +118 -118
  39. package/templates/minigame-2d/files/scenes/ui/settings-window.pix3scene +138 -138
  40. package/templates/minigame-2d/files/scripts/GameFlow.ts +133 -133
  41. package/templates/minigame-2d/files/scripts/MenuFlow.ts +217 -217
  42. package/templates/minigame-2d/files/scripts/SettingsWindow.ts +198 -198
  43. package/templates/minigame-2d/template.yaml +10 -10
  44. package/templates/playable-2d/files/README.md +30 -30
  45. package/templates/playable-2d/files/design/recipe.md +83 -83
  46. package/templates/playable-2d/files/design/tests/reachability.json +4 -4
  47. package/templates/playable-2d/files/design/tests/routines/intro-to-cta.json +32 -32
  48. package/templates/playable-2d/files/scenes/main.pix3scene +111 -111
  49. package/templates/playable-2d/files/scenes/ui/end-screen.pix3scene +91 -91
  50. package/templates/playable-2d/files/scenes/ui/intro.pix3scene +65 -65
  51. package/templates/playable-2d/files/scripts/GameFlow.ts +256 -256
  52. package/templates/playable-2d/template.yaml +9 -9
  53. package/templates/playable-3d/files/README.md +32 -32
  54. package/templates/playable-3d/files/design/recipe.md +127 -127
  55. package/templates/playable-3d/files/design/tests/reachability.json +4 -4
  56. package/templates/playable-3d/files/design/tests/routines/intro-to-cta.json +32 -32
  57. package/templates/playable-3d/files/scenes/main.pix3scene +230 -230
  58. package/templates/playable-3d/files/scenes/ui/end-screen.pix3scene +91 -91
  59. package/templates/playable-3d/files/scenes/ui/intro.pix3scene +65 -65
  60. package/templates/playable-3d/files/scripts/GameFlow.ts +309 -309
  61. package/templates/playable-3d/files/scripts/GameRules.ts +290 -290
  62. package/templates/playable-3d/files/scripts/ScoreHud.ts +113 -113
  63. package/templates/playable-3d/template.yaml +9 -9
  64. package/templates/recipe-arena-2d/files/README.md +48 -48
  65. package/templates/recipe-arena-2d/files/design/recipe.md +127 -127
  66. package/templates/recipe-arena-2d/files/scenes/main.pix3scene +292 -292
  67. package/templates/recipe-arena-2d/files/scenes/menu.pix3scene +100 -100
  68. package/templates/recipe-arena-2d/files/scenes/prefabs/hazard.pix3scene +42 -42
  69. package/templates/recipe-arena-2d/files/scenes/prefabs/pickup.pix3scene +45 -45
  70. package/templates/recipe-arena-2d/files/scenes/ui/result.pix3scene +85 -85
  71. package/templates/recipe-arena-2d/files/scripts/GameRules.ts +368 -368
  72. package/templates/recipe-arena-2d/files/scripts/MenuFlow.ts +106 -106
  73. package/templates/recipe-arena-2d/files/scripts/PlayerController.ts +151 -151
  74. package/templates/recipe-arena-2d/files/scripts/ScoreHud.ts +94 -94
  75. package/templates/recipe-arena-2d/files/scripts/Spawner.ts +214 -214
  76. package/templates/recipe-arena-2d/files/scripts/TouchRules.ts +174 -174
  77. package/templates/recipe-arena-2d/template.yaml +10 -10
  78. package/templates/recipe-blank-2d/files/README.md +61 -61
  79. package/templates/recipe-blank-2d/files/design/recipe.md +148 -148
  80. package/templates/recipe-blank-2d/files/design/tests/reachability.json +4 -4
  81. package/templates/recipe-blank-2d/files/design/tests/routines/restart.json +27 -27
  82. package/templates/recipe-blank-2d/files/scenes/main.pix3scene +224 -224
  83. package/templates/recipe-blank-2d/files/scenes/ui/result.pix3scene +85 -85
  84. package/templates/recipe-blank-2d/files/scripts/GameRules.ts +350 -350
  85. package/templates/recipe-blank-2d/files/scripts/ScoreHud.ts +110 -110
  86. package/templates/recipe-blank-2d/template.yaml +10 -10
  87. package/templates/recipe-bouncer-2d/files/README.md +81 -81
  88. package/templates/recipe-bouncer-2d/files/design/recipe.md +146 -146
  89. package/templates/recipe-bouncer-2d/files/scenes/main.pix3scene +615 -615
  90. package/templates/recipe-bouncer-2d/files/scenes/menu.pix3scene +191 -191
  91. package/templates/recipe-bouncer-2d/files/scenes/ui/result.pix3scene +87 -87
  92. package/templates/recipe-bouncer-2d/files/scripts/BallBody.ts +298 -298
  93. package/templates/recipe-bouncer-2d/files/scripts/GameRules.ts +377 -377
  94. package/templates/recipe-bouncer-2d/files/scripts/MenuFlow.ts +109 -109
  95. package/templates/recipe-bouncer-2d/files/scripts/PaddleController.ts +112 -112
  96. package/templates/recipe-bouncer-2d/files/scripts/ScoreHud.ts +94 -94
  97. package/templates/recipe-bouncer-2d/files/scripts/TouchRules.ts +263 -263
  98. package/templates/recipe-bouncer-2d/files/scripts/ball-collision.ts +307 -307
  99. package/templates/recipe-bouncer-2d/template.yaml +10 -10
  100. package/templates/recipe-grid-3d/files/README.md +22 -22
  101. package/templates/recipe-grid-3d/files/design/recipe.md +110 -110
  102. package/templates/recipe-grid-3d/files/scenes/main.pix3scene +169 -169
  103. package/templates/recipe-grid-3d/files/scenes/menu.pix3scene +100 -100
  104. package/templates/recipe-grid-3d/files/scenes/ui/result.pix3scene +105 -105
  105. package/templates/recipe-grid-3d/files/scripts/GridBoard.ts +319 -319
  106. package/templates/recipe-grid-3d/files/scripts/GridRules.ts +278 -278
  107. package/templates/recipe-grid-3d/files/scripts/MenuFlow.ts +106 -106
  108. package/templates/recipe-grid-3d/files/scripts/ScoreHud.ts +94 -94
  109. package/templates/recipe-grid-3d/template.yaml +10 -10
  110. package/templates/recipe-tapper-2d/files/README.md +39 -39
  111. package/templates/recipe-tapper-2d/files/design/recipe.md +132 -132
  112. package/templates/recipe-tapper-2d/files/design/tests/reachability.json +4 -4
  113. package/templates/recipe-tapper-2d/files/design/tests/routines/terminal-retry.json +23 -23
  114. package/templates/recipe-tapper-2d/files/scenes/main.pix3scene +269 -269
  115. package/templates/recipe-tapper-2d/files/scenes/menu.pix3scene +100 -100
  116. package/templates/recipe-tapper-2d/files/scenes/prefabs/hazard.pix3scene +42 -42
  117. package/templates/recipe-tapper-2d/files/scenes/prefabs/target.pix3scene +45 -45
  118. package/templates/recipe-tapper-2d/files/scenes/ui/result.pix3scene +85 -85
  119. package/templates/recipe-tapper-2d/files/scripts/GameRules.ts +368 -368
  120. package/templates/recipe-tapper-2d/files/scripts/MenuFlow.ts +106 -106
  121. package/templates/recipe-tapper-2d/files/scripts/ScoreHud.ts +94 -94
  122. package/templates/recipe-tapper-2d/files/scripts/Spawner.ts +214 -214
  123. package/templates/recipe-tapper-2d/files/scripts/TouchRules.ts +192 -192
  124. package/templates/recipe-tapper-2d/template.yaml +10 -10
  125. package/dist/smoke/prebuilt/chunk-OJXQXIIQ.mjs +0 -239
  126. package/dist/validate/prebuilt/chunk-BS2OZM7U.js +0 -239
@@ -1,615 +1,615 @@
1
- # Pix3 Scene File (YAML)
2
- # Bouncer 2D — the GAME scene, and the editor's startup scene: iterate here.
3
- # A full build boots the MENU (menu.pix3scene), whose PLAY transitions here.
4
- #
5
- # The physics is NOT engine physics. `scripts/BallBody.ts` runs a swept
6
- # (continuous) circle solver and reads its colliders from the LIVE WORLD
7
- # TRANSFORMS of the marker nodes below — so rotating `paddle` (or adding
8
- # flippers) works with no extra code, and no `core:Hitbox2D` is involved:
9
- # walls/* -> oriented boxes bumpers/* -> circles
10
- # paddles/* -> oriented boxes drain -> trigger box (lose a ball)
11
- # `board-trim` is DECORATION ONLY — it hangs off `board`, not off `walls`, so
12
- # its strips are not colliders. Never move a visual into a collider group.
13
- #
14
- # The neon look is three cheap ingredients, all authored here:
15
- # 1. `post-fx` (PostProcess, affect2D) — bloom picks up whatever is bright
16
- # (cyan trim, gold paddle, white ball, bumper cores) + a light vignette.
17
- # 2. `bg-glow` — a near-white radial-gradient placeholder tinted violet, over
18
- # the darkest ColorRect (`game-background`). ColorRect2D has no gradient.
19
- # 3. HUD `Label2D` glow (`glowColor`/`glowStrength`): the HUD is a
20
- # CanvasLayer2D, drawn AFTER post-processing, so it can never bloom —
21
- # its glow is canvas-drawn instead. (`outlineColor`/`outlineWidth` are the
22
- # matching knobs for text that has to sit over busy gameplay; the HUD here
23
- # sits over plain background, so glow alone carries it.)
24
- #
25
- # Stable node ids (design/recipe.md is the contract — do not rename these):
26
- # post-fx, game-root, game-background, bg-glow, board, board-floor,
27
- # board-trim, walls, wall-left, wall-right, wall-top, bumpers, bumper-a,
28
- # bumper-b, bumper-c, paddles, paddle, ball, drain,
29
- # hud, score-label, time-label, lives-bar, menu-button,
30
- # result-overlay, result-label, retry-button (scenes/ui/result.pix3scene)
31
- #
32
- # Full-screen UI lives in its own file under scenes/ui/ and is instanced here
33
- # hidden (`visible: false` = editor only), so opening this scene shows the game
34
- # rather than a GAME OVER card.
35
- #
36
- # 2D coordinates: origin at the canvas centre, X right, Y UP. Node order in the
37
- # tree is paint order (later/deeper draws on top). `rotation` here is DEGREES.
38
- version: 1.0.0
39
- metadata:
40
- author: Pix3 Recipe
41
- description: Bouncer gameplay — a ball under gravity, a paddle, bumpers and a drain
42
- root:
43
- # Renders nothing; the renderer picks it up and builds the effect stack.
44
- # `bloomIntensity` is a recipe tunable (design/recipe.md) — the Flow theme
45
- # pack turns it up for neon; a pastel / light look RAISES `bloomThreshold`
46
- # (~0.9) instead — a pale ground over 0.58 blooms the whole screen.
47
- - id: post-fx
48
- type: PostProcess
49
- name: Post FX
50
- properties:
51
- affect2D: true
52
- bloomEnabled: true
53
- bloomIntensity: 0.9
54
- bloomThreshold: 0.58
55
- bloomSmoothing: 0.2
56
- bloomRadius: 0.78
57
- vignetteEnabled: true
58
- vignetteOffset: 0.3
59
- vignetteDarkness: 0.5
60
- chromaticAberrationEnabled: false
61
- children: []
62
- - id: game-root
63
- type: Group2D
64
- name: Game Root
65
- properties:
66
- width: 1080
67
- height: 1920
68
- layout:
69
- enabled: true
70
- horizontalAlign: stretch
71
- verticalAlign: stretch
72
- components:
73
- - id: game-rules
74
- type: user:GameRules
75
- enabled: true
76
- config:
77
- winMode: score
78
- targetScore: 1500
79
- timeLimitSec: 0
80
- startingLives: 3
81
- resultNode: result-overlay
82
- resultLabel: result-label
83
- winText: "YOU WIN!"
84
- loseText: "GAME OVER"
85
- retryButton: retry-button
86
- menuButton: menu-button
87
- menuScene: res://scenes/menu.pix3scene
88
- gameScene: res://scenes/main.pix3scene
89
- freezeNodes: ball,paddle
90
- - id: touch-rules
91
- type: user:TouchRules
92
- enabled: true
93
- config:
94
- ballNode: ball
95
- rules: "bumper:score:100;paddle:score:10;drain:damage:1"
96
- minImpactSpeed: 60
97
- punchAmount: 0.34
98
- hitstopMs: 50
99
- burstCount: 18
100
- popupFormat: "+{value}"
101
- feedbackColor: "#ffe066"
102
- sfxEnabled: true
103
- scoreSound: ""
104
- damageSound: ""
105
- children:
106
- - id: game-background
107
- type: ColorRect2D
108
- name: Game Background
109
- properties:
110
- width: 1080
111
- height: 1920
112
- color: "#05030f"
113
- transform:
114
- position: [0, 0]
115
- scale: [1, 1]
116
- rotation: 0
117
- layout:
118
- enabled: true
119
- horizontalAlign: stretch
120
- verticalAlign: stretch
121
- children: []
122
- - id: bg-glow
123
- type: Sprite2D
124
- name: Background Glow
125
- properties:
126
- texture: { type: 'texture', url: 'res://sprites/ph-bg.png' }
127
- width: 1080
128
- height: 1920
129
- effects:
130
- - type: core:tint
131
- params: { color: "#5a2df0", amount: 1 }
132
- transform:
133
- position: [0, 0]
134
- scale: [1, 1]
135
- rotation: 0
136
- layout:
137
- enabled: true
138
- horizontalAlign: stretch
139
- verticalAlign: stretch
140
- children: []
141
- - id: board
142
- type: Group2D
143
- name: Board
144
- properties:
145
- width: 1000
146
- height: 1600
147
- transform:
148
- position: [0, -60]
149
- scale: [1, 1]
150
- rotation: 0
151
- children:
152
- # Translucent so the background glow reads through the playfield.
153
- - id: board-floor
154
- type: ColorRect2D
155
- name: Board Floor
156
- properties:
157
- width: 1000
158
- height: 1600
159
- color: "#120a33"
160
- opacity: 0.62
161
- transform:
162
- position: [0, 0]
163
- scale: [1, 1]
164
- rotation: 0
165
- children: []
166
- - id: drain
167
- type: ColorRect2D
168
- name: Drain
169
- properties:
170
- width: 1000
171
- height: 160
172
- color: "#ff2d6f"
173
- opacity: 0.18
174
- transform:
175
- position: [0, -760]
176
- scale: [1, 1]
177
- rotation: 0
178
- children: []
179
- - id: walls
180
- type: Group2D
181
- name: Walls
182
- properties:
183
- width: 1000
184
- height: 1600
185
- transform:
186
- position: [0, 0]
187
- scale: [1, 1]
188
- rotation: 0
189
- children:
190
- - id: wall-left
191
- type: ColorRect2D
192
- name: Wall Left
193
- properties:
194
- width: 40
195
- height: 1600
196
- color: "#1c1245"
197
- transform:
198
- position: [-480, 0]
199
- scale: [1, 1]
200
- rotation: 0
201
- children: []
202
- - id: wall-right
203
- type: ColorRect2D
204
- name: Wall Right
205
- properties:
206
- width: 40
207
- height: 1600
208
- color: "#1c1245"
209
- transform:
210
- position: [480, 0]
211
- scale: [1, 1]
212
- rotation: 0
213
- children: []
214
- - id: wall-top
215
- type: ColorRect2D
216
- name: Wall Top
217
- properties:
218
- width: 1000
219
- height: 40
220
- color: "#1c1245"
221
- transform:
222
- position: [0, 780]
223
- scale: [1, 1]
224
- rotation: 0
225
- children: []
226
- # Decoration only (see the header): thin bright strips hugging the
227
- # inner faces of the walls. Bright enough to cross the bloom
228
- # threshold, thin enough to read as a neon tube rather than a slab.
229
- - id: board-trim
230
- type: Group2D
231
- name: Board Trim
232
- properties:
233
- width: 1000
234
- height: 1600
235
- transform:
236
- position: [0, 0]
237
- scale: [1, 1]
238
- rotation: 0
239
- children:
240
- - id: trim-left
241
- type: ColorRect2D
242
- name: Trim Left
243
- properties:
244
- width: 10
245
- height: 1560
246
- color: "#2ef2ff"
247
- transform:
248
- position: [-455, -20]
249
- scale: [1, 1]
250
- rotation: 0
251
- children: []
252
- - id: trim-right
253
- type: ColorRect2D
254
- name: Trim Right
255
- properties:
256
- width: 10
257
- height: 1560
258
- color: "#2ef2ff"
259
- transform:
260
- position: [455, -20]
261
- scale: [1, 1]
262
- rotation: 0
263
- children: []
264
- - id: trim-top
265
- type: ColorRect2D
266
- name: Trim Top
267
- properties:
268
- width: 920
269
- height: 10
270
- color: "#2ef2ff"
271
- transform:
272
- position: [0, 755]
273
- scale: [1, 1]
274
- rotation: 0
275
- children: []
276
- - id: trim-drain
277
- type: ColorRect2D
278
- name: Trim Drain Line
279
- properties:
280
- width: 920
281
- height: 6
282
- color: "#ff2d6f"
283
- transform:
284
- position: [0, -676]
285
- scale: [1, 1]
286
- rotation: 0
287
- children: []
288
- # Each bumper is a Group2D so its collider stays one circle
289
- # (radius = width/2) while the visual is two concentric rings: a
290
- # magenta corona and a bright core that bloom-glows. `punchScale`
291
- # on the group pops both together.
292
- - id: bumpers
293
- type: Group2D
294
- name: Bumpers
295
- properties:
296
- width: 1000
297
- height: 1600
298
- transform:
299
- position: [0, 0]
300
- scale: [1, 1]
301
- rotation: 0
302
- children:
303
- - id: bumper-a
304
- type: Group2D
305
- name: Bumper A
306
- properties:
307
- width: 160
308
- height: 160
309
- transform:
310
- position: [-230, 260]
311
- scale: [1, 1]
312
- rotation: 0
313
- children:
314
- - id: bumper-a-halo
315
- type: Sprite2D
316
- name: Bumper A Halo
317
- properties:
318
- texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
319
- width: 216
320
- height: 216
321
- opacity: 0.55
322
- effects:
323
- - type: core:tint
324
- params: { color: "#ff6cf2", amount: 1 }
325
- transform:
326
- position: [0, 0]
327
- scale: [1, 1]
328
- rotation: 0
329
- children: []
330
- - id: bumper-a-core
331
- type: Sprite2D
332
- name: Bumper A Core
333
- properties:
334
- texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
335
- width: 160
336
- height: 160
337
- effects:
338
- - type: core:tint
339
- params: { color: "#8ffcff", amount: 1 }
340
- transform:
341
- position: [0, 0]
342
- scale: [1, 1]
343
- rotation: 0
344
- children: []
345
- - id: bumper-b
346
- type: Group2D
347
- name: Bumper B
348
- properties:
349
- width: 160
350
- height: 160
351
- transform:
352
- position: [230, 260]
353
- scale: [1, 1]
354
- rotation: 0
355
- children:
356
- - id: bumper-b-halo
357
- type: Sprite2D
358
- name: Bumper B Halo
359
- properties:
360
- texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
361
- width: 216
362
- height: 216
363
- opacity: 0.55
364
- effects:
365
- - type: core:tint
366
- params: { color: "#ff6cf2", amount: 1 }
367
- transform:
368
- position: [0, 0]
369
- scale: [1, 1]
370
- rotation: 0
371
- children: []
372
- - id: bumper-b-core
373
- type: Sprite2D
374
- name: Bumper B Core
375
- properties:
376
- texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
377
- width: 160
378
- height: 160
379
- effects:
380
- - type: core:tint
381
- params: { color: "#8ffcff", amount: 1 }
382
- transform:
383
- position: [0, 0]
384
- scale: [1, 1]
385
- rotation: 0
386
- children: []
387
- - id: bumper-c
388
- type: Group2D
389
- name: Bumper C
390
- properties:
391
- width: 160
392
- height: 160
393
- transform:
394
- position: [0, 520]
395
- scale: [1, 1]
396
- rotation: 0
397
- children:
398
- - id: bumper-c-halo
399
- type: Sprite2D
400
- name: Bumper C Halo
401
- properties:
402
- texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
403
- width: 216
404
- height: 216
405
- opacity: 0.55
406
- effects:
407
- - type: core:tint
408
- params: { color: "#ff6cf2", amount: 1 }
409
- transform:
410
- position: [0, 0]
411
- scale: [1, 1]
412
- rotation: 0
413
- children: []
414
- - id: bumper-c-core
415
- type: Sprite2D
416
- name: Bumper C Core
417
- properties:
418
- texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
419
- width: 160
420
- height: 160
421
- effects:
422
- - type: core:tint
423
- params: { color: "#8ffcff", amount: 1 }
424
- transform:
425
- position: [0, 0]
426
- scale: [1, 1]
427
- rotation: 0
428
- children: []
429
- - id: paddles
430
- type: Group2D
431
- name: Paddles
432
- properties:
433
- width: 1000
434
- height: 1600
435
- transform:
436
- position: [0, 0]
437
- scale: [1, 1]
438
- rotation: 0
439
- children:
440
- - id: paddle
441
- type: Sprite2D
442
- name: Paddle
443
- properties:
444
- texture: { type: 'texture', url: 'res://sprites/ph-paddle.png' }
445
- width: 300
446
- height: 60
447
- effects:
448
- - type: core:tint
449
- params: { color: "#ffd23f", amount: 1 }
450
- transform:
451
- position: [0, -620]
452
- scale: [1, 1]
453
- rotation: 0
454
- components:
455
- - id: paddle-controller
456
- type: user:PaddleController
457
- enabled: true
458
- config:
459
- mode: pointer
460
- speed: 1800
461
- halfWidth: 150
462
- boundsNode: board
463
- children: []
464
- - id: ball
465
- type: Sprite2D
466
- name: Ball
467
- properties:
468
- texture: { type: 'texture', url: 'res://sprites/ph-ball.png' }
469
- width: 60
470
- height: 60
471
- effects:
472
- - type: core:tint
473
- params: { color: "#ffffff", amount: 1 }
474
- transform:
475
- position: [0, 120]
476
- scale: [1, 1]
477
- rotation: 0
478
- components:
479
- - id: ball-body
480
- type: user:BallBody
481
- enabled: true
482
- config:
483
- radius: 30
484
- gravity: -1600
485
- maxSpeed: 1900
486
- minSpeed: 380
487
- damping: 0.999
488
- substeps: 4
489
- launchSpeed: 900
490
- launchAngleDeg: 72
491
- wallsNode: walls
492
- paddlesNode: paddles
493
- bumpersNode: bumpers
494
- drainNode: drain
495
- wallRestitution: 1
496
- paddleRestitution: 1.05
497
- bumperRestitution: 1.3
498
- resetDelaySec: 0.7
499
- children: []
500
- # A CanvasLayer2D is drawn after post-processing and is never bloomed —
501
- # that is deliberate (HUD text stays crisp). Its glow comes from
502
- # Label2D's own canvas-drawn `glowColor`/`glowStrength`.
503
- - id: hud
504
- type: CanvasLayer2D
505
- name: HUD
506
- properties:
507
- width: 1080
508
- height: 1920
509
- layout:
510
- enabled: true
511
- horizontalAlign: stretch
512
- verticalAlign: stretch
513
- components:
514
- - id: score-hud
515
- type: user:ScoreHud
516
- enabled: true
517
- config:
518
- sourceNode: game-root
519
- scoreLabel: score-label
520
- scoreFormat: "SCORE {value}"
521
- timeLabel: time-label
522
- timeFormat: "{value}s"
523
- livesBar: lives-bar
524
- children:
525
- - id: score-label
526
- type: Label2D
527
- name: Score Label
528
- properties:
529
- label: "SCORE 0"
530
- labelFontSize: 56
531
- labelColor: "#ffffff"
532
- labelAlign: left
533
- glowColor: "#2ef2ff"
534
- glowStrength: 2
535
- transform:
536
- position: [-340, 880]
537
- scale: [1, 1]
538
- rotation: 0
539
- layout:
540
- enabled: true
541
- horizontalAlign: left
542
- verticalAlign: top
543
- children: []
544
- - id: time-label
545
- type: Label2D
546
- name: Time Label
547
- properties:
548
- label: "0s"
549
- labelFontSize: 46
550
- labelColor: "#ffe066"
551
- labelAlign: center
552
- glowColor: "#ffd23f"
553
- glowStrength: 1.5
554
- transform:
555
- position: [0, 880]
556
- scale: [1, 1]
557
- rotation: 0
558
- layout:
559
- enabled: true
560
- horizontalAlign: center
561
- verticalAlign: top
562
- children: []
563
- - id: lives-bar
564
- type: Bar2D
565
- name: Lives Bar
566
- properties:
567
- width: 240
568
- height: 28
569
- minValue: 0
570
- maxValue: 3
571
- value: 3
572
- barColor: "#ff2d6f"
573
- backBackgroundColor: "#1c1245"
574
- showBorder: false
575
- transform:
576
- position: [340, 885]
577
- scale: [1, 1]
578
- rotation: 0
579
- layout:
580
- enabled: true
581
- horizontalAlign: right
582
- verticalAlign: top
583
- children: []
584
- - id: menu-button
585
- type: Button2D
586
- name: Menu Button
587
- properties:
588
- width: 200
589
- height: 72
590
- label: "MENU"
591
- labelFontSize: 30
592
- labelColor: "#8ffcff"
593
- backgroundColor: "#1c1245"
594
- hoverColor: "#2a1a63"
595
- pressedColor: "#0d0724"
596
- buttonAction: back-to-menu
597
- transform:
598
- position: [-400, -900]
599
- scale: [1, 1]
600
- rotation: 0
601
- layout:
602
- enabled: true
603
- horizontalAlign: left
604
- verticalAlign: bottom
605
- children: []
606
- # Win/lose screen — authored in scenes/ui/result.pix3scene so this
607
- # scene opens on the GAME, not on a GAME OVER card. `visible: false`
608
- # hides it in the EDITOR only; `initiallyVisible` (in the overlay
609
- # file) is what play mode reads, and GameRules reveals it on the
610
- # win/lose transition. Tick the eye to preview it over the field.
611
- - id: result-overlay
612
- name: Result Overlay
613
- instance: res://scenes/ui/result.pix3scene
614
- properties:
615
- visible: false
1
+ # Pix3 Scene File (YAML)
2
+ # Bouncer 2D — the GAME scene, and the editor's startup scene: iterate here.
3
+ # A full build boots the MENU (menu.pix3scene), whose PLAY transitions here.
4
+ #
5
+ # The physics is NOT engine physics. `scripts/BallBody.ts` runs a swept
6
+ # (continuous) circle solver and reads its colliders from the LIVE WORLD
7
+ # TRANSFORMS of the marker nodes below — so rotating `paddle` (or adding
8
+ # flippers) works with no extra code, and no `core:Hitbox2D` is involved:
9
+ # walls/* -> oriented boxes bumpers/* -> circles
10
+ # paddles/* -> oriented boxes drain -> trigger box (lose a ball)
11
+ # `board-trim` is DECORATION ONLY — it hangs off `board`, not off `walls`, so
12
+ # its strips are not colliders. Never move a visual into a collider group.
13
+ #
14
+ # The neon look is three cheap ingredients, all authored here:
15
+ # 1. `post-fx` (PostProcess, affect2D) — bloom picks up whatever is bright
16
+ # (cyan trim, gold paddle, white ball, bumper cores) + a light vignette.
17
+ # 2. `bg-glow` — a near-white radial-gradient placeholder tinted violet, over
18
+ # the darkest ColorRect (`game-background`). ColorRect2D has no gradient.
19
+ # 3. HUD `Label2D` glow (`glowColor`/`glowStrength`): the HUD is a
20
+ # CanvasLayer2D, drawn AFTER post-processing, so it can never bloom —
21
+ # its glow is canvas-drawn instead. (`outlineColor`/`outlineWidth` are the
22
+ # matching knobs for text that has to sit over busy gameplay; the HUD here
23
+ # sits over plain background, so glow alone carries it.)
24
+ #
25
+ # Stable node ids (design/recipe.md is the contract — do not rename these):
26
+ # post-fx, game-root, game-background, bg-glow, board, board-floor,
27
+ # board-trim, walls, wall-left, wall-right, wall-top, bumpers, bumper-a,
28
+ # bumper-b, bumper-c, paddles, paddle, ball, drain,
29
+ # hud, score-label, time-label, lives-bar, menu-button,
30
+ # result-overlay, result-label, retry-button (scenes/ui/result.pix3scene)
31
+ #
32
+ # Full-screen UI lives in its own file under scenes/ui/ and is instanced here
33
+ # hidden (`visible: false` = editor only), so opening this scene shows the game
34
+ # rather than a GAME OVER card.
35
+ #
36
+ # 2D coordinates: origin at the canvas centre, X right, Y UP. Node order in the
37
+ # tree is paint order (later/deeper draws on top). `rotation` here is DEGREES.
38
+ version: 1.0.0
39
+ metadata:
40
+ author: Pix3 Recipe
41
+ description: Bouncer gameplay — a ball under gravity, a paddle, bumpers and a drain
42
+ root:
43
+ # Renders nothing; the renderer picks it up and builds the effect stack.
44
+ # `bloomIntensity` is a recipe tunable (design/recipe.md) — the Flow theme
45
+ # pack turns it up for neon; a pastel / light look RAISES `bloomThreshold`
46
+ # (~0.9) instead — a pale ground over 0.58 blooms the whole screen.
47
+ - id: post-fx
48
+ type: PostProcess
49
+ name: Post FX
50
+ properties:
51
+ affect2D: true
52
+ bloomEnabled: true
53
+ bloomIntensity: 0.9
54
+ bloomThreshold: 0.58
55
+ bloomSmoothing: 0.2
56
+ bloomRadius: 0.78
57
+ vignetteEnabled: true
58
+ vignetteOffset: 0.3
59
+ vignetteDarkness: 0.5
60
+ chromaticAberrationEnabled: false
61
+ children: []
62
+ - id: game-root
63
+ type: Group2D
64
+ name: Game Root
65
+ properties:
66
+ width: 1080
67
+ height: 1920
68
+ layout:
69
+ enabled: true
70
+ horizontalAlign: stretch
71
+ verticalAlign: stretch
72
+ components:
73
+ - id: game-rules
74
+ type: user:GameRules
75
+ enabled: true
76
+ config:
77
+ winMode: score
78
+ targetScore: 1500
79
+ timeLimitSec: 0
80
+ startingLives: 3
81
+ resultNode: result-overlay
82
+ resultLabel: result-label
83
+ winText: "YOU WIN!"
84
+ loseText: "GAME OVER"
85
+ retryButton: retry-button
86
+ menuButton: menu-button
87
+ menuScene: res://scenes/menu.pix3scene
88
+ gameScene: res://scenes/main.pix3scene
89
+ freezeNodes: ball,paddle
90
+ - id: touch-rules
91
+ type: user:TouchRules
92
+ enabled: true
93
+ config:
94
+ ballNode: ball
95
+ rules: "bumper:score:100;paddle:score:10;drain:damage:1"
96
+ minImpactSpeed: 60
97
+ punchAmount: 0.34
98
+ hitstopMs: 50
99
+ burstCount: 18
100
+ popupFormat: "+{value}"
101
+ feedbackColor: "#ffe066"
102
+ sfxEnabled: true
103
+ scoreSound: ""
104
+ damageSound: ""
105
+ children:
106
+ - id: game-background
107
+ type: ColorRect2D
108
+ name: Game Background
109
+ properties:
110
+ width: 1080
111
+ height: 1920
112
+ color: "#05030f"
113
+ transform:
114
+ position: [0, 0]
115
+ scale: [1, 1]
116
+ rotation: 0
117
+ layout:
118
+ enabled: true
119
+ horizontalAlign: stretch
120
+ verticalAlign: stretch
121
+ children: []
122
+ - id: bg-glow
123
+ type: Sprite2D
124
+ name: Background Glow
125
+ properties:
126
+ texture: { type: 'texture', url: 'res://sprites/ph-bg.png' }
127
+ width: 1080
128
+ height: 1920
129
+ effects:
130
+ - type: core:tint
131
+ params: { color: "#5a2df0", amount: 1 }
132
+ transform:
133
+ position: [0, 0]
134
+ scale: [1, 1]
135
+ rotation: 0
136
+ layout:
137
+ enabled: true
138
+ horizontalAlign: stretch
139
+ verticalAlign: stretch
140
+ children: []
141
+ - id: board
142
+ type: Group2D
143
+ name: Board
144
+ properties:
145
+ width: 1000
146
+ height: 1600
147
+ transform:
148
+ position: [0, -60]
149
+ scale: [1, 1]
150
+ rotation: 0
151
+ children:
152
+ # Translucent so the background glow reads through the playfield.
153
+ - id: board-floor
154
+ type: ColorRect2D
155
+ name: Board Floor
156
+ properties:
157
+ width: 1000
158
+ height: 1600
159
+ color: "#120a33"
160
+ opacity: 0.62
161
+ transform:
162
+ position: [0, 0]
163
+ scale: [1, 1]
164
+ rotation: 0
165
+ children: []
166
+ - id: drain
167
+ type: ColorRect2D
168
+ name: Drain
169
+ properties:
170
+ width: 1000
171
+ height: 160
172
+ color: "#ff2d6f"
173
+ opacity: 0.18
174
+ transform:
175
+ position: [0, -760]
176
+ scale: [1, 1]
177
+ rotation: 0
178
+ children: []
179
+ - id: walls
180
+ type: Group2D
181
+ name: Walls
182
+ properties:
183
+ width: 1000
184
+ height: 1600
185
+ transform:
186
+ position: [0, 0]
187
+ scale: [1, 1]
188
+ rotation: 0
189
+ children:
190
+ - id: wall-left
191
+ type: ColorRect2D
192
+ name: Wall Left
193
+ properties:
194
+ width: 40
195
+ height: 1600
196
+ color: "#1c1245"
197
+ transform:
198
+ position: [-480, 0]
199
+ scale: [1, 1]
200
+ rotation: 0
201
+ children: []
202
+ - id: wall-right
203
+ type: ColorRect2D
204
+ name: Wall Right
205
+ properties:
206
+ width: 40
207
+ height: 1600
208
+ color: "#1c1245"
209
+ transform:
210
+ position: [480, 0]
211
+ scale: [1, 1]
212
+ rotation: 0
213
+ children: []
214
+ - id: wall-top
215
+ type: ColorRect2D
216
+ name: Wall Top
217
+ properties:
218
+ width: 1000
219
+ height: 40
220
+ color: "#1c1245"
221
+ transform:
222
+ position: [0, 780]
223
+ scale: [1, 1]
224
+ rotation: 0
225
+ children: []
226
+ # Decoration only (see the header): thin bright strips hugging the
227
+ # inner faces of the walls. Bright enough to cross the bloom
228
+ # threshold, thin enough to read as a neon tube rather than a slab.
229
+ - id: board-trim
230
+ type: Group2D
231
+ name: Board Trim
232
+ properties:
233
+ width: 1000
234
+ height: 1600
235
+ transform:
236
+ position: [0, 0]
237
+ scale: [1, 1]
238
+ rotation: 0
239
+ children:
240
+ - id: trim-left
241
+ type: ColorRect2D
242
+ name: Trim Left
243
+ properties:
244
+ width: 10
245
+ height: 1560
246
+ color: "#2ef2ff"
247
+ transform:
248
+ position: [-455, -20]
249
+ scale: [1, 1]
250
+ rotation: 0
251
+ children: []
252
+ - id: trim-right
253
+ type: ColorRect2D
254
+ name: Trim Right
255
+ properties:
256
+ width: 10
257
+ height: 1560
258
+ color: "#2ef2ff"
259
+ transform:
260
+ position: [455, -20]
261
+ scale: [1, 1]
262
+ rotation: 0
263
+ children: []
264
+ - id: trim-top
265
+ type: ColorRect2D
266
+ name: Trim Top
267
+ properties:
268
+ width: 920
269
+ height: 10
270
+ color: "#2ef2ff"
271
+ transform:
272
+ position: [0, 755]
273
+ scale: [1, 1]
274
+ rotation: 0
275
+ children: []
276
+ - id: trim-drain
277
+ type: ColorRect2D
278
+ name: Trim Drain Line
279
+ properties:
280
+ width: 920
281
+ height: 6
282
+ color: "#ff2d6f"
283
+ transform:
284
+ position: [0, -676]
285
+ scale: [1, 1]
286
+ rotation: 0
287
+ children: []
288
+ # Each bumper is a Group2D so its collider stays one circle
289
+ # (radius = width/2) while the visual is two concentric rings: a
290
+ # magenta corona and a bright core that bloom-glows. `punchScale`
291
+ # on the group pops both together.
292
+ - id: bumpers
293
+ type: Group2D
294
+ name: Bumpers
295
+ properties:
296
+ width: 1000
297
+ height: 1600
298
+ transform:
299
+ position: [0, 0]
300
+ scale: [1, 1]
301
+ rotation: 0
302
+ children:
303
+ - id: bumper-a
304
+ type: Group2D
305
+ name: Bumper A
306
+ properties:
307
+ width: 160
308
+ height: 160
309
+ transform:
310
+ position: [-230, 260]
311
+ scale: [1, 1]
312
+ rotation: 0
313
+ children:
314
+ - id: bumper-a-halo
315
+ type: Sprite2D
316
+ name: Bumper A Halo
317
+ properties:
318
+ texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
319
+ width: 216
320
+ height: 216
321
+ opacity: 0.55
322
+ effects:
323
+ - type: core:tint
324
+ params: { color: "#ff6cf2", amount: 1 }
325
+ transform:
326
+ position: [0, 0]
327
+ scale: [1, 1]
328
+ rotation: 0
329
+ children: []
330
+ - id: bumper-a-core
331
+ type: Sprite2D
332
+ name: Bumper A Core
333
+ properties:
334
+ texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
335
+ width: 160
336
+ height: 160
337
+ effects:
338
+ - type: core:tint
339
+ params: { color: "#8ffcff", amount: 1 }
340
+ transform:
341
+ position: [0, 0]
342
+ scale: [1, 1]
343
+ rotation: 0
344
+ children: []
345
+ - id: bumper-b
346
+ type: Group2D
347
+ name: Bumper B
348
+ properties:
349
+ width: 160
350
+ height: 160
351
+ transform:
352
+ position: [230, 260]
353
+ scale: [1, 1]
354
+ rotation: 0
355
+ children:
356
+ - id: bumper-b-halo
357
+ type: Sprite2D
358
+ name: Bumper B Halo
359
+ properties:
360
+ texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
361
+ width: 216
362
+ height: 216
363
+ opacity: 0.55
364
+ effects:
365
+ - type: core:tint
366
+ params: { color: "#ff6cf2", amount: 1 }
367
+ transform:
368
+ position: [0, 0]
369
+ scale: [1, 1]
370
+ rotation: 0
371
+ children: []
372
+ - id: bumper-b-core
373
+ type: Sprite2D
374
+ name: Bumper B Core
375
+ properties:
376
+ texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
377
+ width: 160
378
+ height: 160
379
+ effects:
380
+ - type: core:tint
381
+ params: { color: "#8ffcff", amount: 1 }
382
+ transform:
383
+ position: [0, 0]
384
+ scale: [1, 1]
385
+ rotation: 0
386
+ children: []
387
+ - id: bumper-c
388
+ type: Group2D
389
+ name: Bumper C
390
+ properties:
391
+ width: 160
392
+ height: 160
393
+ transform:
394
+ position: [0, 520]
395
+ scale: [1, 1]
396
+ rotation: 0
397
+ children:
398
+ - id: bumper-c-halo
399
+ type: Sprite2D
400
+ name: Bumper C Halo
401
+ properties:
402
+ texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
403
+ width: 216
404
+ height: 216
405
+ opacity: 0.55
406
+ effects:
407
+ - type: core:tint
408
+ params: { color: "#ff6cf2", amount: 1 }
409
+ transform:
410
+ position: [0, 0]
411
+ scale: [1, 1]
412
+ rotation: 0
413
+ children: []
414
+ - id: bumper-c-core
415
+ type: Sprite2D
416
+ name: Bumper C Core
417
+ properties:
418
+ texture: { type: 'texture', url: 'res://sprites/ph-bumper.png' }
419
+ width: 160
420
+ height: 160
421
+ effects:
422
+ - type: core:tint
423
+ params: { color: "#8ffcff", amount: 1 }
424
+ transform:
425
+ position: [0, 0]
426
+ scale: [1, 1]
427
+ rotation: 0
428
+ children: []
429
+ - id: paddles
430
+ type: Group2D
431
+ name: Paddles
432
+ properties:
433
+ width: 1000
434
+ height: 1600
435
+ transform:
436
+ position: [0, 0]
437
+ scale: [1, 1]
438
+ rotation: 0
439
+ children:
440
+ - id: paddle
441
+ type: Sprite2D
442
+ name: Paddle
443
+ properties:
444
+ texture: { type: 'texture', url: 'res://sprites/ph-paddle.png' }
445
+ width: 300
446
+ height: 60
447
+ effects:
448
+ - type: core:tint
449
+ params: { color: "#ffd23f", amount: 1 }
450
+ transform:
451
+ position: [0, -620]
452
+ scale: [1, 1]
453
+ rotation: 0
454
+ components:
455
+ - id: paddle-controller
456
+ type: user:PaddleController
457
+ enabled: true
458
+ config:
459
+ mode: pointer
460
+ speed: 1800
461
+ halfWidth: 150
462
+ boundsNode: board
463
+ children: []
464
+ - id: ball
465
+ type: Sprite2D
466
+ name: Ball
467
+ properties:
468
+ texture: { type: 'texture', url: 'res://sprites/ph-ball.png' }
469
+ width: 60
470
+ height: 60
471
+ effects:
472
+ - type: core:tint
473
+ params: { color: "#ffffff", amount: 1 }
474
+ transform:
475
+ position: [0, 120]
476
+ scale: [1, 1]
477
+ rotation: 0
478
+ components:
479
+ - id: ball-body
480
+ type: user:BallBody
481
+ enabled: true
482
+ config:
483
+ radius: 30
484
+ gravity: -1600
485
+ maxSpeed: 1900
486
+ minSpeed: 380
487
+ damping: 0.999
488
+ substeps: 4
489
+ launchSpeed: 900
490
+ launchAngleDeg: 72
491
+ wallsNode: walls
492
+ paddlesNode: paddles
493
+ bumpersNode: bumpers
494
+ drainNode: drain
495
+ wallRestitution: 1
496
+ paddleRestitution: 1.05
497
+ bumperRestitution: 1.3
498
+ resetDelaySec: 0.7
499
+ children: []
500
+ # A CanvasLayer2D is drawn after post-processing and is never bloomed —
501
+ # that is deliberate (HUD text stays crisp). Its glow comes from
502
+ # Label2D's own canvas-drawn `glowColor`/`glowStrength`.
503
+ - id: hud
504
+ type: CanvasLayer2D
505
+ name: HUD
506
+ properties:
507
+ width: 1080
508
+ height: 1920
509
+ layout:
510
+ enabled: true
511
+ horizontalAlign: stretch
512
+ verticalAlign: stretch
513
+ components:
514
+ - id: score-hud
515
+ type: user:ScoreHud
516
+ enabled: true
517
+ config:
518
+ sourceNode: game-root
519
+ scoreLabel: score-label
520
+ scoreFormat: "SCORE {value}"
521
+ timeLabel: time-label
522
+ timeFormat: "{value}s"
523
+ livesBar: lives-bar
524
+ children:
525
+ - id: score-label
526
+ type: Label2D
527
+ name: Score Label
528
+ properties:
529
+ label: "SCORE 0"
530
+ labelFontSize: 56
531
+ labelColor: "#ffffff"
532
+ labelAlign: left
533
+ glowColor: "#2ef2ff"
534
+ glowStrength: 2
535
+ transform:
536
+ position: [-340, 880]
537
+ scale: [1, 1]
538
+ rotation: 0
539
+ layout:
540
+ enabled: true
541
+ horizontalAlign: left
542
+ verticalAlign: top
543
+ children: []
544
+ - id: time-label
545
+ type: Label2D
546
+ name: Time Label
547
+ properties:
548
+ label: "0s"
549
+ labelFontSize: 46
550
+ labelColor: "#ffe066"
551
+ labelAlign: center
552
+ glowColor: "#ffd23f"
553
+ glowStrength: 1.5
554
+ transform:
555
+ position: [0, 880]
556
+ scale: [1, 1]
557
+ rotation: 0
558
+ layout:
559
+ enabled: true
560
+ horizontalAlign: center
561
+ verticalAlign: top
562
+ children: []
563
+ - id: lives-bar
564
+ type: Bar2D
565
+ name: Lives Bar
566
+ properties:
567
+ width: 240
568
+ height: 28
569
+ minValue: 0
570
+ maxValue: 3
571
+ value: 3
572
+ barColor: "#ff2d6f"
573
+ backBackgroundColor: "#1c1245"
574
+ showBorder: false
575
+ transform:
576
+ position: [340, 885]
577
+ scale: [1, 1]
578
+ rotation: 0
579
+ layout:
580
+ enabled: true
581
+ horizontalAlign: right
582
+ verticalAlign: top
583
+ children: []
584
+ - id: menu-button
585
+ type: Button2D
586
+ name: Menu Button
587
+ properties:
588
+ width: 200
589
+ height: 72
590
+ label: "MENU"
591
+ labelFontSize: 30
592
+ labelColor: "#8ffcff"
593
+ backgroundColor: "#1c1245"
594
+ hoverColor: "#2a1a63"
595
+ pressedColor: "#0d0724"
596
+ buttonAction: back-to-menu
597
+ transform:
598
+ position: [-400, -900]
599
+ scale: [1, 1]
600
+ rotation: 0
601
+ layout:
602
+ enabled: true
603
+ horizontalAlign: left
604
+ verticalAlign: bottom
605
+ children: []
606
+ # Win/lose screen — authored in scenes/ui/result.pix3scene so this
607
+ # scene opens on the GAME, not on a GAME OVER card. `visible: false`
608
+ # hides it in the EDITOR only; `initiallyVisible` (in the overlay
609
+ # file) is what play mode reads, and GameRules reveals it on the
610
+ # win/lose transition. Tick the eye to preview it over the field.
611
+ - id: result-overlay
612
+ name: Result Overlay
613
+ instance: res://scenes/ui/result.pix3scene
614
+ properties:
615
+ visible: false