@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.
- package/LICENSE +201 -201
- package/README.md +788 -754
- package/dist/index.js +208 -203
- package/dist/runtime-types.json +1 -1
- package/dist/smoke/prebuilt/{chunk-J2SJVMDO.mjs → chunk-7MZGPAUK.mjs} +1 -1
- package/dist/smoke/prebuilt/chunk-7WOFGLW3.mjs +239 -0
- package/dist/smoke/prebuilt/runtime.mjs +1 -1
- package/dist/smoke/prebuilt/smoke-worker.mjs +1 -1
- package/dist/smoke/prebuilt/tree-defaults.mjs +1 -1
- package/dist/validate/prebuilt/bundle-main.js +13 -13
- package/dist/validate/prebuilt/chunk-HKG6YI6Y.js +239 -0
- package/dist/validate/prebuilt/runtime.js +1 -1
- package/kit/files/.claude/skills/pix3-nodes/SKILL.md +210 -210
- package/kit/files/.claude/skills/pix3-nodes/reference.md +32 -24
- package/kit/files/.claude/skills/pix3-scene-format/SKILL.md +238 -235
- package/kit/files/.claude/skills/pix3-scene-format/reference.md +28 -28
- package/kit/files/.claude/skills/pix3-scripts/SKILL.md +285 -281
- package/kit/files/.claude/skills/pix3-scripts/reference.md +69 -52
- package/kit/files/.claude/skills/pix3-verify/SKILL.md +298 -256
- package/kit/files/.claude/skills/pix3-verify/reference.md +21 -21
- package/kit/files/AGENTS.md +203 -203
- package/kit/files/CLAUDE.md +1 -1
- package/kit/kit.json +2 -2
- package/package.json +54 -54
- package/templates/empty-2d/files/README.md +20 -20
- package/templates/empty-2d/files/scenes/main.pix3scene +68 -68
- package/templates/empty-2d/template.yaml +7 -7
- package/templates/empty-3d/files/README.md +20 -20
- package/templates/empty-3d/files/scenes/main.pix3scene +108 -108
- package/templates/empty-3d/template.yaml +7 -7
- package/templates/idea-blank/files/README.md +22 -22
- package/templates/idea-blank/files/scenes/main.pix3scene +37 -37
- package/templates/idea-blank/template.yaml +10 -10
- package/templates/minigame-2d/files/README.md +44 -44
- package/templates/minigame-2d/files/design/tests/reachability.json +1 -1
- package/templates/minigame-2d/files/design/tests/routines/mute-music.json +44 -44
- package/templates/minigame-2d/files/scenes/main.pix3scene +84 -84
- package/templates/minigame-2d/files/scenes/menu.pix3scene +118 -118
- package/templates/minigame-2d/files/scenes/ui/settings-window.pix3scene +138 -138
- package/templates/minigame-2d/files/scripts/GameFlow.ts +133 -133
- package/templates/minigame-2d/files/scripts/MenuFlow.ts +217 -217
- package/templates/minigame-2d/files/scripts/SettingsWindow.ts +198 -198
- package/templates/minigame-2d/template.yaml +10 -10
- package/templates/playable-2d/files/README.md +30 -30
- package/templates/playable-2d/files/design/recipe.md +83 -83
- package/templates/playable-2d/files/design/tests/reachability.json +4 -4
- package/templates/playable-2d/files/design/tests/routines/intro-to-cta.json +32 -32
- package/templates/playable-2d/files/scenes/main.pix3scene +111 -111
- package/templates/playable-2d/files/scenes/ui/end-screen.pix3scene +91 -91
- package/templates/playable-2d/files/scenes/ui/intro.pix3scene +65 -65
- package/templates/playable-2d/files/scripts/GameFlow.ts +256 -256
- package/templates/playable-2d/template.yaml +9 -9
- package/templates/playable-3d/files/README.md +32 -32
- package/templates/playable-3d/files/design/recipe.md +127 -127
- package/templates/playable-3d/files/design/tests/reachability.json +4 -4
- package/templates/playable-3d/files/design/tests/routines/intro-to-cta.json +32 -32
- package/templates/playable-3d/files/scenes/main.pix3scene +230 -230
- package/templates/playable-3d/files/scenes/ui/end-screen.pix3scene +91 -91
- package/templates/playable-3d/files/scenes/ui/intro.pix3scene +65 -65
- package/templates/playable-3d/files/scripts/GameFlow.ts +309 -309
- package/templates/playable-3d/files/scripts/GameRules.ts +290 -290
- package/templates/playable-3d/files/scripts/ScoreHud.ts +113 -113
- package/templates/playable-3d/template.yaml +9 -9
- package/templates/recipe-arena-2d/files/README.md +48 -48
- package/templates/recipe-arena-2d/files/design/recipe.md +127 -127
- package/templates/recipe-arena-2d/files/scenes/main.pix3scene +292 -292
- package/templates/recipe-arena-2d/files/scenes/menu.pix3scene +100 -100
- package/templates/recipe-arena-2d/files/scenes/prefabs/hazard.pix3scene +42 -42
- package/templates/recipe-arena-2d/files/scenes/prefabs/pickup.pix3scene +45 -45
- package/templates/recipe-arena-2d/files/scenes/ui/result.pix3scene +85 -85
- package/templates/recipe-arena-2d/files/scripts/GameRules.ts +368 -368
- package/templates/recipe-arena-2d/files/scripts/MenuFlow.ts +106 -106
- package/templates/recipe-arena-2d/files/scripts/PlayerController.ts +151 -151
- package/templates/recipe-arena-2d/files/scripts/ScoreHud.ts +94 -94
- package/templates/recipe-arena-2d/files/scripts/Spawner.ts +214 -214
- package/templates/recipe-arena-2d/files/scripts/TouchRules.ts +174 -174
- package/templates/recipe-arena-2d/template.yaml +10 -10
- package/templates/recipe-blank-2d/files/README.md +61 -61
- package/templates/recipe-blank-2d/files/design/recipe.md +148 -148
- package/templates/recipe-blank-2d/files/design/tests/reachability.json +4 -4
- package/templates/recipe-blank-2d/files/design/tests/routines/restart.json +27 -27
- package/templates/recipe-blank-2d/files/scenes/main.pix3scene +224 -224
- package/templates/recipe-blank-2d/files/scenes/ui/result.pix3scene +85 -85
- package/templates/recipe-blank-2d/files/scripts/GameRules.ts +350 -350
- package/templates/recipe-blank-2d/files/scripts/ScoreHud.ts +110 -110
- package/templates/recipe-blank-2d/template.yaml +10 -10
- package/templates/recipe-bouncer-2d/files/README.md +81 -81
- package/templates/recipe-bouncer-2d/files/design/recipe.md +146 -146
- package/templates/recipe-bouncer-2d/files/scenes/main.pix3scene +615 -615
- package/templates/recipe-bouncer-2d/files/scenes/menu.pix3scene +191 -191
- package/templates/recipe-bouncer-2d/files/scenes/ui/result.pix3scene +87 -87
- package/templates/recipe-bouncer-2d/files/scripts/BallBody.ts +298 -298
- package/templates/recipe-bouncer-2d/files/scripts/GameRules.ts +377 -377
- package/templates/recipe-bouncer-2d/files/scripts/MenuFlow.ts +109 -109
- package/templates/recipe-bouncer-2d/files/scripts/PaddleController.ts +112 -112
- package/templates/recipe-bouncer-2d/files/scripts/ScoreHud.ts +94 -94
- package/templates/recipe-bouncer-2d/files/scripts/TouchRules.ts +263 -263
- package/templates/recipe-bouncer-2d/files/scripts/ball-collision.ts +307 -307
- package/templates/recipe-bouncer-2d/template.yaml +10 -10
- package/templates/recipe-grid-3d/files/README.md +22 -22
- package/templates/recipe-grid-3d/files/design/recipe.md +110 -110
- package/templates/recipe-grid-3d/files/scenes/main.pix3scene +169 -169
- package/templates/recipe-grid-3d/files/scenes/menu.pix3scene +100 -100
- package/templates/recipe-grid-3d/files/scenes/ui/result.pix3scene +105 -105
- package/templates/recipe-grid-3d/files/scripts/GridBoard.ts +319 -319
- package/templates/recipe-grid-3d/files/scripts/GridRules.ts +278 -278
- package/templates/recipe-grid-3d/files/scripts/MenuFlow.ts +106 -106
- package/templates/recipe-grid-3d/files/scripts/ScoreHud.ts +94 -94
- package/templates/recipe-grid-3d/template.yaml +10 -10
- package/templates/recipe-tapper-2d/files/README.md +39 -39
- package/templates/recipe-tapper-2d/files/design/recipe.md +132 -132
- package/templates/recipe-tapper-2d/files/design/tests/reachability.json +4 -4
- package/templates/recipe-tapper-2d/files/design/tests/routines/terminal-retry.json +23 -23
- package/templates/recipe-tapper-2d/files/scenes/main.pix3scene +269 -269
- package/templates/recipe-tapper-2d/files/scenes/menu.pix3scene +100 -100
- package/templates/recipe-tapper-2d/files/scenes/prefabs/hazard.pix3scene +42 -42
- package/templates/recipe-tapper-2d/files/scenes/prefabs/target.pix3scene +45 -45
- package/templates/recipe-tapper-2d/files/scenes/ui/result.pix3scene +85 -85
- package/templates/recipe-tapper-2d/files/scripts/GameRules.ts +368 -368
- package/templates/recipe-tapper-2d/files/scripts/MenuFlow.ts +106 -106
- package/templates/recipe-tapper-2d/files/scripts/ScoreHud.ts +94 -94
- package/templates/recipe-tapper-2d/files/scripts/Spawner.ts +214 -214
- package/templates/recipe-tapper-2d/files/scripts/TouchRules.ts +192 -192
- package/templates/recipe-tapper-2d/template.yaml +10 -10
- package/dist/smoke/prebuilt/chunk-OJXQXIIQ.mjs +0 -239
- 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
|