@pix3/cli 1.6.3 → 2.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -201
- package/README.md +722 -788
- package/dist/index.js +557 -421
- package/dist/runtime-types.json +1 -1
- package/dist/smoke/prebuilt/{build-7MIXIMSZ.mjs → build-7REMSA2S.mjs} +52 -52
- package/dist/smoke/prebuilt/chunk-4DGG2BKR.mjs +2 -0
- package/dist/smoke/prebuilt/chunk-YLBMUJ2H.mjs +238 -0
- package/dist/smoke/prebuilt/runtime.mjs +1 -1
- package/dist/smoke/prebuilt/smoke-worker.mjs +211 -2
- package/dist/smoke/prebuilt/tree-defaults.mjs +1 -1
- package/dist/validate/prebuilt/{build-AUGKXER3.js → build-ADF5EEE2.js} +52 -52
- package/dist/validate/prebuilt/bundle-main.js +223 -18
- package/dist/validate/prebuilt/chunk-VIHIF4G2.js +238 -0
- package/dist/validate/prebuilt/runtime.js +1 -1
- package/kit/files/.claude/skills/pix3-editor/SKILL.md +200 -0
- package/kit/files/.claude/skills/pix3-nodes/SKILL.md +13 -15
- package/kit/files/.claude/skills/pix3-nodes/reference.md +77 -71
- package/kit/files/.claude/skills/pix3-scene-format/SKILL.md +38 -41
- package/kit/files/.claude/skills/pix3-scene-format/pix3anim.md +185 -0
- package/kit/files/.claude/skills/pix3-scene-format/project-files.md +244 -0
- package/kit/files/.claude/skills/pix3-scene-format/reference.md +28 -16
- package/kit/files/.claude/skills/pix3-scripts/SKILL.md +34 -24
- package/kit/files/.claude/skills/pix3-scripts/reference.md +68 -141
- package/kit/files/.claude/skills/pix3-verify/SKILL.md +65 -326
- package/kit/files/.claude/skills/pix3-verify/reference.md +2 -14
- package/kit/files/AGENTS.md +76 -84
- package/kit/files/design/tests/bots/pix3-test-bot.d.ts +89 -0
- package/kit/kit.json +8 -5
- package/package.json +62 -54
- package/templates/2d/files/scenes/main.pix3scene +31 -0
- package/templates/2d/template.yaml +11 -0
- package/templates/3d/files/scenes/main.pix3scene +50 -0
- package/templates/3d/template.yaml +11 -0
- package/templates/base/files/README.md +39 -0
- package/templates/base/files/gitignore +11 -0
- package/templates/base/files/index.html +23 -0
- package/templates/base/files/package.json +28 -0
- package/templates/base/files/src/main.ts +3 -0
- package/templates/base/files/tsconfig.json +17 -0
- package/templates/base/files/vite.config.ts +10 -0
- package/dist/smoke/prebuilt/chunk-CBFYKDS7.mjs +0 -2
- package/dist/smoke/prebuilt/chunk-VJHJ5BCO.mjs +0 -239
- package/dist/validate/prebuilt/chunk-CFQFEI52.js +0 -239
- package/templates/empty-2d/files/README.md +0 -20
- package/templates/empty-2d/files/scenes/main.pix3scene +0 -68
- package/templates/empty-2d/files/sprites/pix3-logo.png +0 -0
- package/templates/empty-2d/template.yaml +0 -7
- package/templates/empty-3d/files/README.md +0 -20
- package/templates/empty-3d/files/scenes/main.pix3scene +0 -108
- package/templates/empty-3d/files/sprites/pix3-logo.png +0 -0
- package/templates/empty-3d/template.yaml +0 -7
- package/templates/idea-blank/files/README.md +0 -22
- package/templates/idea-blank/files/scenes/main.pix3scene +0 -37
- package/templates/idea-blank/template.yaml +0 -10
- package/templates/minigame-2d/files/README.md +0 -44
- package/templates/minigame-2d/files/design/tests/reachability.json +0 -1
- package/templates/minigame-2d/files/design/tests/routines/mute-music.json +0 -44
- package/templates/minigame-2d/files/scenes/main.pix3scene +0 -84
- package/templates/minigame-2d/files/scenes/menu.pix3scene +0 -118
- package/templates/minigame-2d/files/scenes/ui/settings-window.pix3scene +0 -138
- package/templates/minigame-2d/files/scripts/GameFlow.ts +0 -133
- package/templates/minigame-2d/files/scripts/MenuFlow.ts +0 -217
- package/templates/minigame-2d/files/scripts/SettingsWindow.ts +0 -198
- package/templates/minigame-2d/template.yaml +0 -10
- package/templates/playable-2d/files/README.md +0 -30
- package/templates/playable-2d/files/design/recipe.md +0 -83
- package/templates/playable-2d/files/design/tests/reachability.json +0 -4
- package/templates/playable-2d/files/design/tests/routines/intro-to-cta.json +0 -32
- package/templates/playable-2d/files/scenes/main.pix3scene +0 -111
- package/templates/playable-2d/files/scenes/ui/end-screen.pix3scene +0 -91
- package/templates/playable-2d/files/scenes/ui/intro.pix3scene +0 -65
- package/templates/playable-2d/files/scripts/CtaButton.ts +0 -55
- package/templates/playable-2d/files/scripts/GameFlow.ts +0 -256
- package/templates/playable-2d/files/sprites/pix3-logo.png +0 -0
- package/templates/playable-2d/template.yaml +0 -9
- package/templates/playable-3d/files/README.md +0 -32
- package/templates/playable-3d/files/design/recipe.md +0 -127
- package/templates/playable-3d/files/design/tests/reachability.json +0 -4
- package/templates/playable-3d/files/design/tests/routines/intro-to-cta.json +0 -32
- package/templates/playable-3d/files/scenes/main.pix3scene +0 -230
- package/templates/playable-3d/files/scenes/ui/end-screen.pix3scene +0 -91
- package/templates/playable-3d/files/scenes/ui/intro.pix3scene +0 -65
- package/templates/playable-3d/files/scripts/CtaButton.ts +0 -55
- package/templates/playable-3d/files/scripts/GameFlow.ts +0 -309
- package/templates/playable-3d/files/scripts/GameRules.ts +0 -290
- package/templates/playable-3d/files/scripts/ScoreHud.ts +0 -113
- package/templates/playable-3d/template.yaml +0 -9
- package/templates/recipe-arena-2d/files/README.md +0 -48
- package/templates/recipe-arena-2d/files/design/recipe.md +0 -127
- package/templates/recipe-arena-2d/files/design/tests/reachability.json +0 -4
- package/templates/recipe-arena-2d/files/design/tests/routines/terminal-retry.json +0 -23
- package/templates/recipe-arena-2d/files/scenes/main.pix3scene +0 -292
- package/templates/recipe-arena-2d/files/scenes/menu.pix3scene +0 -100
- package/templates/recipe-arena-2d/files/scenes/prefabs/hazard.pix3scene +0 -42
- package/templates/recipe-arena-2d/files/scenes/prefabs/pickup.pix3scene +0 -45
- package/templates/recipe-arena-2d/files/scenes/ui/result.pix3scene +0 -85
- package/templates/recipe-arena-2d/files/scripts/GameRules.ts +0 -368
- package/templates/recipe-arena-2d/files/scripts/MenuFlow.ts +0 -106
- package/templates/recipe-arena-2d/files/scripts/PlayerController.ts +0 -151
- package/templates/recipe-arena-2d/files/scripts/ScoreHud.ts +0 -94
- package/templates/recipe-arena-2d/files/scripts/Spawner.ts +0 -214
- package/templates/recipe-arena-2d/files/scripts/TouchRules.ts +0 -174
- package/templates/recipe-arena-2d/files/sprites/ph-avatar.png +0 -0
- package/templates/recipe-arena-2d/files/sprites/ph-hazard.png +0 -0
- package/templates/recipe-arena-2d/files/sprites/ph-pickup.png +0 -0
- package/templates/recipe-arena-2d/template.yaml +0 -10
- package/templates/recipe-blank-2d/files/README.md +0 -61
- package/templates/recipe-blank-2d/files/design/recipe.md +0 -148
- package/templates/recipe-blank-2d/files/design/tests/reachability.json +0 -4
- package/templates/recipe-blank-2d/files/design/tests/routines/restart.json +0 -27
- package/templates/recipe-blank-2d/files/design/tests/routines/terminal-retry.json +0 -23
- package/templates/recipe-blank-2d/files/scenes/main.pix3scene +0 -224
- package/templates/recipe-blank-2d/files/scenes/ui/result.pix3scene +0 -85
- package/templates/recipe-blank-2d/files/scripts/GameRules.ts +0 -350
- package/templates/recipe-blank-2d/files/scripts/ScoreHud.ts +0 -110
- package/templates/recipe-blank-2d/files/sprites/ph-bg.png +0 -0
- package/templates/recipe-blank-2d/files/sprites/ph-capsule.png +0 -0
- package/templates/recipe-blank-2d/files/sprites/ph-circle.png +0 -0
- package/templates/recipe-blank-2d/files/sprites/ph-orb.png +0 -0
- package/templates/recipe-blank-2d/files/sprites/ph-ring.png +0 -0
- package/templates/recipe-blank-2d/files/sprites/ph-star.png +0 -0
- package/templates/recipe-blank-2d/template.yaml +0 -10
- package/templates/recipe-bouncer-2d/files/README.md +0 -81
- package/templates/recipe-bouncer-2d/files/design/recipe.md +0 -146
- package/templates/recipe-bouncer-2d/files/design/tests/reachability.json +0 -4
- package/templates/recipe-bouncer-2d/files/design/tests/routines/terminal-retry.json +0 -23
- package/templates/recipe-bouncer-2d/files/scenes/main.pix3scene +0 -615
- package/templates/recipe-bouncer-2d/files/scenes/menu.pix3scene +0 -191
- package/templates/recipe-bouncer-2d/files/scenes/ui/result.pix3scene +0 -87
- package/templates/recipe-bouncer-2d/files/scripts/BallBody.ts +0 -298
- package/templates/recipe-bouncer-2d/files/scripts/GameRules.ts +0 -377
- package/templates/recipe-bouncer-2d/files/scripts/MenuFlow.ts +0 -109
- package/templates/recipe-bouncer-2d/files/scripts/PaddleController.ts +0 -112
- package/templates/recipe-bouncer-2d/files/scripts/ScoreHud.ts +0 -94
- package/templates/recipe-bouncer-2d/files/scripts/TouchRules.ts +0 -263
- package/templates/recipe-bouncer-2d/files/scripts/ball-collision.ts +0 -307
- package/templates/recipe-bouncer-2d/files/sprites/ph-ball.png +0 -0
- package/templates/recipe-bouncer-2d/files/sprites/ph-bg.png +0 -0
- package/templates/recipe-bouncer-2d/files/sprites/ph-bumper.png +0 -0
- package/templates/recipe-bouncer-2d/files/sprites/ph-paddle.png +0 -0
- package/templates/recipe-bouncer-2d/template.yaml +0 -10
- package/templates/recipe-grid-3d/files/README.md +0 -22
- package/templates/recipe-grid-3d/files/design/recipe.md +0 -110
- package/templates/recipe-grid-3d/files/scenes/main.pix3scene +0 -169
- package/templates/recipe-grid-3d/files/scenes/menu.pix3scene +0 -100
- package/templates/recipe-grid-3d/files/scenes/ui/result.pix3scene +0 -105
- package/templates/recipe-grid-3d/files/scripts/GridBoard.ts +0 -319
- package/templates/recipe-grid-3d/files/scripts/GridRules.ts +0 -278
- package/templates/recipe-grid-3d/files/scripts/MenuFlow.ts +0 -106
- package/templates/recipe-grid-3d/files/scripts/ScoreHud.ts +0 -94
- package/templates/recipe-grid-3d/template.yaml +0 -10
- package/templates/recipe-tapper-2d/files/README.md +0 -39
- package/templates/recipe-tapper-2d/files/design/recipe.md +0 -132
- package/templates/recipe-tapper-2d/files/design/tests/reachability.json +0 -4
- package/templates/recipe-tapper-2d/files/design/tests/routines/terminal-retry.json +0 -23
- package/templates/recipe-tapper-2d/files/scenes/main.pix3scene +0 -269
- package/templates/recipe-tapper-2d/files/scenes/menu.pix3scene +0 -100
- package/templates/recipe-tapper-2d/files/scenes/prefabs/hazard.pix3scene +0 -42
- package/templates/recipe-tapper-2d/files/scenes/prefabs/target.pix3scene +0 -45
- package/templates/recipe-tapper-2d/files/scenes/ui/result.pix3scene +0 -85
- package/templates/recipe-tapper-2d/files/scripts/GameRules.ts +0 -368
- package/templates/recipe-tapper-2d/files/scripts/MenuFlow.ts +0 -106
- package/templates/recipe-tapper-2d/files/scripts/ScoreHud.ts +0 -94
- package/templates/recipe-tapper-2d/files/scripts/Spawner.ts +0 -214
- package/templates/recipe-tapper-2d/files/scripts/TouchRules.ts +0 -192
- package/templates/recipe-tapper-2d/files/sprites/ph-hazard.png +0 -0
- package/templates/recipe-tapper-2d/files/sprites/ph-target.png +0 -0
- package/templates/recipe-tapper-2d/template.yaml +0 -10
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ScoreHud — signal-driven HUD. Display only, no game logic.
|
|
3
|
-
*
|
|
4
|
-
* Listens on `sourceNode` (the node carrying `GameRules`) for:
|
|
5
|
-
* `score-changed` (score)
|
|
6
|
-
* `lives-changed` (lives, maxLives)
|
|
7
|
-
* `time-changed` (seconds)
|
|
8
|
-
*
|
|
9
|
-
* If a HUD widget is missing from the scene it is quietly skipped, so you can
|
|
10
|
-
* delete the timer or the lives bar without touching any script.
|
|
11
|
-
*/
|
|
12
|
-
import { Bar2D, Label2D, Script, type PropertySchema } from '@pix3/runtime';
|
|
13
|
-
|
|
14
|
-
export class ScoreHud extends Script {
|
|
15
|
-
constructor(id: string, type: string) {
|
|
16
|
-
super(id, type);
|
|
17
|
-
this.config = {
|
|
18
|
-
// Node that emits the HUD signals (the GameRules host).
|
|
19
|
-
sourceNode: 'game-root',
|
|
20
|
-
scoreLabel: 'score-label',
|
|
21
|
-
scoreFormat: 'SCORE {value}',
|
|
22
|
-
timeLabel: 'time-label',
|
|
23
|
-
timeFormat: '{value}',
|
|
24
|
-
livesBar: 'lives-bar',
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static getPropertySchema(): PropertySchema {
|
|
29
|
-
const str = (name: string, label: string, description?: string) => ({
|
|
30
|
-
name,
|
|
31
|
-
type: 'string' as const,
|
|
32
|
-
ui: { label, group: 'HUD', description },
|
|
33
|
-
getValue: (s: unknown) => (s as ScoreHud).config[name],
|
|
34
|
-
setValue: (s: unknown, v: unknown) => {
|
|
35
|
-
(s as ScoreHud).config[name] = typeof v === 'string' ? v : '';
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
nodeType: 'ScoreHud',
|
|
41
|
-
properties: [
|
|
42
|
-
str('sourceNode', 'Source Node', 'Node that emits score-changed / lives-changed / time-changed'),
|
|
43
|
-
str('scoreLabel', 'Score Label'),
|
|
44
|
-
str('scoreFormat', 'Score Format', '{value} is replaced by the score'),
|
|
45
|
-
str('timeLabel', 'Time Label'),
|
|
46
|
-
str('timeFormat', 'Time Format', '{value} is replaced by whole seconds'),
|
|
47
|
-
str('livesBar', 'Lives Bar'),
|
|
48
|
-
],
|
|
49
|
-
groups: { HUD: { label: 'HUD', expanded: true } },
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
onStart(): void {
|
|
54
|
-
const source = this.findNode(String(this.config.sourceNode ?? ''));
|
|
55
|
-
if (!source) {
|
|
56
|
-
console.warn(`[ScoreHud] Source node "${this.config.sourceNode}" not found.`);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
source.connect('score-changed', this, (...args: unknown[]) => this.setScore(Number(args[0]) || 0));
|
|
60
|
-
source.connect('time-changed', this, (...args: unknown[]) => this.setTime(Number(args[0]) || 0));
|
|
61
|
-
source.connect('lives-changed', this, (...args: unknown[]) =>
|
|
62
|
-
this.setLives(Number(args[0]) || 0, Number(args[1]) || 0)
|
|
63
|
-
);
|
|
64
|
-
// Ask for the opening values now that the listeners are live: GameRules
|
|
65
|
-
// starts before this HUD (parent components tick before children).
|
|
66
|
-
source.emit('hud-ready');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
private setScore(score: number): void {
|
|
70
|
-
const label = this.findNode(String(this.config.scoreLabel ?? ''));
|
|
71
|
-
if (label instanceof Label2D) {
|
|
72
|
-
label.setText(String(this.config.scoreFormat ?? '{value}').replace('{value}', String(Math.round(score))));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
private setTime(seconds: number): void {
|
|
77
|
-
const label = this.findNode(String(this.config.timeLabel ?? ''));
|
|
78
|
-
if (label instanceof Label2D) {
|
|
79
|
-
label.setText(
|
|
80
|
-
String(this.config.timeFormat ?? '{value}').replace('{value}', String(Math.max(0, Math.ceil(seconds))))
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
private setLives(lives: number, maxLives: number): void {
|
|
86
|
-
const bar = this.findNode(String(this.config.livesBar ?? ''));
|
|
87
|
-
if (bar instanceof Bar2D) {
|
|
88
|
-
if (maxLives > 0) {
|
|
89
|
-
bar.maxValue = maxLives;
|
|
90
|
-
}
|
|
91
|
-
bar.setValue(lives);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
id: recipe-grid-3d
|
|
2
|
-
title: Grid 3D
|
|
3
|
-
description: A solid block of cubes you carve by tapping — clear every cube except the hidden core ones. Voxel carving, 3D minesweeper, layer puzzles, tap-to-mine.
|
|
4
|
-
projectType: 3d
|
|
5
|
-
targetPlatform: mobile
|
|
6
|
-
viewport: { width: 1080, height: 1920 }
|
|
7
|
-
# The build/full-run entry scene (Project Settings → Default Export Scene Path).
|
|
8
|
-
# The menu boots first; PLAY transitions to main.pix3scene (the board).
|
|
9
|
-
entryScene: scenes/menu.pix3scene
|
|
10
|
-
order: 63
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# Tapper 2D
|
|
2
|
-
|
|
3
|
-
A playable skeleton: objects fall into the field, tapping them is the whole
|
|
4
|
-
game, one bad type punishes, and a countdown ends the run. It plays as
|
|
5
|
-
shipped — press play in `scenes/main.pix3scene` before changing anything.
|
|
6
|
-
|
|
7
|
-
**`design/recipe.md` is the contract.** Stable node ids, tunables with ranges,
|
|
8
|
-
extension points and what must not be renamed. Read it first.
|
|
9
|
-
|
|
10
|
-
## Layout
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
scenes/menu.pix3scene entry / export scene — PLAY transitions to the game
|
|
14
|
-
scenes/main.pix3scene the GAME (editor startup scene — iterate here)
|
|
15
|
-
scenes/ui/result.pix3scene win/lose overlay, instanced into main hidden (editor-only)
|
|
16
|
-
scenes/prefabs/*.pix3scene what the spawners instantiate
|
|
17
|
-
scripts/Spawner.ts timed instantiate + drift + despawn
|
|
18
|
-
scripts/TouchRules.ts a tap → semantic signals
|
|
19
|
-
scripts/ScoreHud.ts signals → HUD widgets
|
|
20
|
-
scripts/GameRules.ts score / lives / timer / win / lose / end flow
|
|
21
|
-
scripts/MenuFlow.ts menu PLAY button
|
|
22
|
-
sprites/ph-*.png near-white placeholders (tinted via core:tint)
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Same script names and roles as the other recipes — `Spawner`, `TouchRules`,
|
|
26
|
-
`ScoreHud`, `GameRules` mean the same thing everywhere, only their contact
|
|
27
|
-
source differs (here: a pointer-down hit-test instead of a proximity test).
|
|
28
|
-
|
|
29
|
-
## The rule that keeps it workable
|
|
30
|
-
|
|
31
|
-
One file, one responsibility, 70–140 lines. Small files can be edited
|
|
32
|
-
surgically; monoliths get rewritten wholesale and lose the changes that were
|
|
33
|
-
already working. When you add a mechanic, add a script.
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
TouchRules --touch-scored/touch-damaged--> GameRules --score-changed--> ScoreHud
|
|
37
|
-
--lives-changed-->
|
|
38
|
-
--time-changed-->
|
|
39
|
-
```
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
# Recipe: recipe-tapper-2d
|
|
2
|
-
|
|
3
|
-
## What this is
|
|
4
|
-
|
|
5
|
-
Objects fall into a field; tapping them is the whole game. One "bad" type
|
|
6
|
-
punishes instead of scoring. A countdown ends the run and a target score decides
|
|
7
|
-
win or lose. Playable before any edit.
|
|
8
|
-
|
|
9
|
-
Same script names and roles as the other recipes — `Spawner`, `TouchRules`,
|
|
10
|
-
`ScoreHud`, `GameRules` — so what you learn here transfers.
|
|
11
|
-
|
|
12
|
-
## Node map
|
|
13
|
-
|
|
14
|
-
| id | what |
|
|
15
|
-
| --- | --- |
|
|
16
|
-
| `game-root` | root; hosts `GameRules` + `TouchRules`; all HUD signals emitted here |
|
|
17
|
-
| `game-background` | full-screen `ColorRect2D` (palette background) |
|
|
18
|
-
| `board` | the field (`Group2D`) |
|
|
19
|
-
| `board-floor` | the field's visible plate |
|
|
20
|
-
| `spawner-targets` | spawn band for tappable things; hosts `Spawner` |
|
|
21
|
-
| `spawner-hazards` | spawn band for the bad type; hosts `Spawner` |
|
|
22
|
-
| `hud` | `CanvasLayer2D` overlay, hosts `ScoreHud` |
|
|
23
|
-
| `score-label` / `time-label` / `lives-bar` / `menu-button` | HUD |
|
|
24
|
-
| `result-overlay` / `result-label` / `retry-button` | end screen in `scenes/ui/result.pix3scene`, instanced into main hidden (`visible: false` is editor-only) |
|
|
25
|
-
|
|
26
|
-
Signals: `TouchRules` emits `touch-scored` / `touch-damaged` on `game-root`;
|
|
27
|
-
`GameRules` answers `score-changed`, `lives-changed`, `time-changed`,
|
|
28
|
-
`game-won` / `game-lost`.
|
|
29
|
-
|
|
30
|
-
## Placeholders
|
|
31
|
-
|
|
32
|
-
Near-white PNGs carrying a `core:tint` effect: set `effects[0].params.color` and
|
|
33
|
-
the multiply gives you that palette colour.
|
|
34
|
-
|
|
35
|
-
| role | file | node/prefab |
|
|
36
|
-
| --- | --- | --- |
|
|
37
|
-
| collectible | `sprites/ph-target.png` | `prefabs/target.pix3scene` |
|
|
38
|
-
| threat | `sprites/ph-hazard.png` | `prefabs/hazard.pix3scene` |
|
|
39
|
-
|
|
40
|
-
## Tunables
|
|
41
|
-
|
|
42
|
-
```yaml
|
|
43
|
-
tunables:
|
|
44
|
-
targetRate: { node: spawner-targets, component: "user:Spawner", property: intervalSec, min: 0.05, max: 20, default: 0.85 }
|
|
45
|
-
targetMaxAlive: { node: spawner-targets, component: "user:Spawner", property: maxAlive, min: 1, max: 200, default: 8 }
|
|
46
|
-
targetFallSpeed: { node: spawner-targets, component: "user:Spawner", property: driftY, min: -3000, max: 3000, default: -230 }
|
|
47
|
-
targetLifetime: { node: spawner-targets, component: "user:Spawner", property: lifetimeSec, min: 0, max: 120, default: 8 }
|
|
48
|
-
hazardRate: { node: spawner-hazards, component: "user:Spawner", property: intervalSec, min: 0.05, max: 20, default: 2.2 }
|
|
49
|
-
hazardFallSpeed: { node: spawner-hazards, component: "user:Spawner", property: driftY, min: -3000, max: 3000, default: -260 }
|
|
50
|
-
tapRadius: { node: game-root, component: "user:TouchRules", property: tapRadius, min: 0, max: 400, default: 40 }
|
|
51
|
-
missPenalty: { node: game-root, component: "user:TouchRules", property: missPenalty, min: 0, max: 10, default: 0 }
|
|
52
|
-
touchRules: { node: game-root, component: "user:TouchRules", property: rules, default: "target:score:1;hazard:damage:1" }
|
|
53
|
-
winMode: { node: game-root, component: "user:GameRules", property: winMode, default: time }
|
|
54
|
-
targetScore: { node: game-root, component: "user:GameRules", property: targetScore, min: 1, max: 99999, default: 18 }
|
|
55
|
-
timeLimitSec: { node: game-root, component: "user:GameRules", property: timeLimitSec, min: 0, max: 600, default: 30 }
|
|
56
|
-
startingLives: { node: game-root, component: "user:GameRules", property: startingLives, min: 1, max: 20, default: 3 }
|
|
57
|
-
bgColor: { node: game-background, property: color, default: "#141a2e" }
|
|
58
|
-
boardColor: { node: board-floor, property: color, default: "#1d2743" }
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
`component` present → `set_component_property`; absent → `set_property`. The
|
|
62
|
-
schema clamps out-of-range values rather than rejecting them.
|
|
63
|
-
|
|
64
|
-
## Extension points
|
|
65
|
-
|
|
66
|
-
- **Popping instead of falling (whack-a-mole).** Set `targetFallSpeed: 0` and
|
|
67
|
-
`targetLifetime` to ~1.2 s: things appear in place and vanish if not tapped.
|
|
68
|
-
Set `gridSnap` on the spawner (e.g. 220) and raise `spawnHeight` to get a mole
|
|
69
|
-
grid instead of a band.
|
|
70
|
-
- **Combos / multipliers.** A new script on `hud` that listens for
|
|
71
|
-
`touch-scored` on `game-root`, counts hits inside a time window, and adds
|
|
72
|
-
only the **extra** points: `game-root.emit('touch-scored', amount * (m - 1), x, y)`
|
|
73
|
-
under a re-entrancy guard (`if (this.emitting) return; this.emitting = true;
|
|
74
|
-
try { emit(...) } finally { this.emitting = false; }`). `GameRules` already
|
|
75
|
-
counted the base `amount` and needs no change. Show the multiplier through a
|
|
76
|
-
signal of its own (`combo-changed`), never through `touch-scored`.
|
|
77
|
-
**The trap:** a listener on `touch-scored` that emits `touch-scored` on the
|
|
78
|
-
same node is called again by its own emit — without the guard, the first tap
|
|
79
|
-
recurses until the stack overflows (and re-emitting the *full* amount would
|
|
80
|
-
double-count the base). No offline check sees it: `pix3 check` and
|
|
81
|
-
`pix3 smoke` are green, because smoke taps nothing. Say so, and have the human
|
|
82
|
-
tap three targets in a row.
|
|
83
|
-
- **A third type.** Copy a prefab, give its `core:Hitbox2D` a new group, add a
|
|
84
|
-
node with a third `Spawner` (`create_node` + `add_component`), and append
|
|
85
|
-
`<group>:score:5` to `touchRules`.
|
|
86
|
-
- **Punish misses.** Raise `missPenalty` — a tap that hits nothing then costs a
|
|
87
|
-
life, which turns a relaxed collector into a precision game.
|
|
88
|
-
- **Sudden death.** `startingLives: 1`, or `winMode: survive` with a longer
|
|
89
|
-
`timeLimitSec` so surviving the clock is the win.
|
|
90
|
-
|
|
91
|
-
Replacing a whole script the list above names is expected: use `fs_write` with
|
|
92
|
-
`overwrite: true` and a short `reason` (the size guard only blocks *silent*
|
|
93
|
-
wholesale rewrites).
|
|
94
|
-
|
|
95
|
-
## Ending a run belongs to GameRules
|
|
96
|
-
|
|
97
|
-
The result overlay and RETRY are **owned by `GameRules`**: it hides the overlay on
|
|
98
|
-
start and keeps `retry-button` **disabled**, then `finish(won)` shows the overlay,
|
|
99
|
-
writes the result text, enables RETRY and freezes the `freezeNodes` subtrees
|
|
100
|
-
(every component on them and on what they spawned). For a custom
|
|
101
|
-
win/lose condition call `finish(true|false)` on that component — do NOT show the
|
|
102
|
-
overlay yourself. A hand-rolled ending leaves RETRY on screen with its handler bound
|
|
103
|
-
and `enabled: false`, i.e. a button that can never be pressed (`game_observe` reports
|
|
104
|
-
`control: { enabled: false }`; that is the tell).
|
|
105
|
-
|
|
106
|
-
## Do not touch
|
|
107
|
-
|
|
108
|
-
- The node ids above (rename `name`, never `id`), and the signal names.
|
|
109
|
-
- Component config on a **prefab instance** — the editor locks it. Prefabs carry
|
|
110
|
-
fixed defaults only (their hitbox group); tunables live on plain nodes in
|
|
111
|
-
`main.pix3scene`.
|
|
112
|
-
- The prefab hitbox groups must stay in sync with `touchRules`; the group is the
|
|
113
|
-
only thing that separates "good" from "bad".
|
|
114
|
-
|
|
115
|
-
## Playtest contract
|
|
116
|
-
|
|
117
|
-
terminalVisual: static
|
|
118
|
-
terminalRestartRoutine: terminal-retry
|
|
119
|
-
|
|
120
|
-
After the result overlay appears, the screen should remain still until RETRY. The
|
|
121
|
-
playtest samples five rendered frames at 15-frame intervals after the terminal
|
|
122
|
-
phase has held for 120 frames. The `terminal-retry` routine physically taps RETRY
|
|
123
|
-
and checks that the game returns to its playing phase.
|
|
124
|
-
|
|
125
|
-
## Verify
|
|
126
|
-
|
|
127
|
-
1. `play_start` on `scenes/main.pix3scene`.
|
|
128
|
-
2. After ~2 s, children exist under `spawner-targets` and are falling.
|
|
129
|
-
3. `game_input` a tap on one of them → it disappears, `score-label` climbs, and
|
|
130
|
-
the punch-scale fires.
|
|
131
|
-
4. Tap three hazards → `lives-bar` empties and `result-overlay` shows
|
|
132
|
-
`GAME OVER`; `retry-button` restarts the scene.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "terminal-retry",
|
|
3
|
-
"description": "From the result screen, physically tap RETRY and check that play resumes.",
|
|
4
|
-
"scope": "scenes/main.pix3scene",
|
|
5
|
-
"params": {},
|
|
6
|
-
"uses": ["result-overlay", "retry-button"],
|
|
7
|
-
"steps": [
|
|
8
|
-
{
|
|
9
|
-
"type": "tap",
|
|
10
|
-
"target": "retry-button",
|
|
11
|
-
"holdMs": 200,
|
|
12
|
-
"why": "A real pointer press proves the button is visible, enabled and reachable."
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"type": "wait",
|
|
16
|
-
"frames": 30,
|
|
17
|
-
"why": "Let the scene transition finish before reading the new game's phase."
|
|
18
|
-
}
|
|
19
|
-
],
|
|
20
|
-
"expect": [
|
|
21
|
-
{ "kind": "gameState", "path": "phase", "op": "eq", "value": "playing" }
|
|
22
|
-
]
|
|
23
|
-
}
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
# Pix3 Scene File (YAML)
|
|
2
|
-
# Tapper 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
|
-
# Objects fall into the board; tapping them is the whole game. A tap is
|
|
6
|
-
# hit-tested (scripts/TouchRules.ts) against the `core:Hitbox2D` group each
|
|
7
|
-
# prefab carries: `target` scores, `hazard` costs a life.
|
|
8
|
-
#
|
|
9
|
-
# Stable node ids (design/recipe.md is the contract — do not rename these):
|
|
10
|
-
# game-root, game-background, board, spawner-targets, spawner-hazards,
|
|
11
|
-
# hud, score-label, time-label, lives-bar, menu-button,
|
|
12
|
-
# result-overlay, result-label, retry-button (scenes/ui/result.pix3scene)
|
|
13
|
-
#
|
|
14
|
-
# Full-screen UI lives in its own file under scenes/ui/ and is instanced here
|
|
15
|
-
# hidden (`visible: false` = editor only), so opening this scene shows the game
|
|
16
|
-
# rather than a GAME OVER card.
|
|
17
|
-
#
|
|
18
|
-
# 2D coordinates: origin at the canvas centre, X right, Y UP. Node order in the
|
|
19
|
-
# tree is paint order (later/deeper draws on top).
|
|
20
|
-
version: 1.0.0
|
|
21
|
-
metadata:
|
|
22
|
-
author: Pix3 Recipe
|
|
23
|
-
description: Tapper gameplay — falling objects, tap the good ones, avoid the bad
|
|
24
|
-
root:
|
|
25
|
-
- id: game-root
|
|
26
|
-
type: Group2D
|
|
27
|
-
name: Game Root
|
|
28
|
-
properties:
|
|
29
|
-
width: 1080
|
|
30
|
-
height: 1920
|
|
31
|
-
layout:
|
|
32
|
-
enabled: true
|
|
33
|
-
horizontalAlign: stretch
|
|
34
|
-
verticalAlign: stretch
|
|
35
|
-
components:
|
|
36
|
-
- id: game-rules
|
|
37
|
-
type: user:GameRules
|
|
38
|
-
enabled: true
|
|
39
|
-
config:
|
|
40
|
-
winMode: time
|
|
41
|
-
targetScore: 18
|
|
42
|
-
timeLimitSec: 30
|
|
43
|
-
startingLives: 3
|
|
44
|
-
resultNode: result-overlay
|
|
45
|
-
resultLabel: result-label
|
|
46
|
-
winText: "YOU WIN!"
|
|
47
|
-
loseText: "GAME OVER"
|
|
48
|
-
retryButton: retry-button
|
|
49
|
-
menuButton: menu-button
|
|
50
|
-
menuScene: res://scenes/menu.pix3scene
|
|
51
|
-
gameScene: res://scenes/main.pix3scene
|
|
52
|
-
freezeNodes: spawner-targets,spawner-hazards
|
|
53
|
-
- id: touch-rules
|
|
54
|
-
type: user:TouchRules
|
|
55
|
-
enabled: true
|
|
56
|
-
config:
|
|
57
|
-
rules: "target:score:1;hazard:damage:1"
|
|
58
|
-
tapRadius: 40
|
|
59
|
-
missPenalty: 0
|
|
60
|
-
consume: true
|
|
61
|
-
scoreSound: ""
|
|
62
|
-
damageSound: ""
|
|
63
|
-
children:
|
|
64
|
-
- id: game-background
|
|
65
|
-
type: ColorRect2D
|
|
66
|
-
name: Game Background
|
|
67
|
-
properties:
|
|
68
|
-
width: 1080
|
|
69
|
-
height: 1920
|
|
70
|
-
color: "#141a2e"
|
|
71
|
-
transform:
|
|
72
|
-
position: [0, 0]
|
|
73
|
-
scale: [1, 1]
|
|
74
|
-
rotation: 0
|
|
75
|
-
layout:
|
|
76
|
-
enabled: true
|
|
77
|
-
horizontalAlign: stretch
|
|
78
|
-
verticalAlign: stretch
|
|
79
|
-
children: []
|
|
80
|
-
- id: board
|
|
81
|
-
type: Group2D
|
|
82
|
-
name: Board
|
|
83
|
-
properties:
|
|
84
|
-
width: 980
|
|
85
|
-
height: 1480
|
|
86
|
-
transform:
|
|
87
|
-
position: [0, -80]
|
|
88
|
-
scale: [1, 1]
|
|
89
|
-
rotation: 0
|
|
90
|
-
children:
|
|
91
|
-
- id: board-floor
|
|
92
|
-
type: ColorRect2D
|
|
93
|
-
name: Board Floor
|
|
94
|
-
properties:
|
|
95
|
-
width: 980
|
|
96
|
-
height: 1480
|
|
97
|
-
color: "#1d2743"
|
|
98
|
-
transform:
|
|
99
|
-
position: [0, 0]
|
|
100
|
-
scale: [1, 1]
|
|
101
|
-
rotation: 0
|
|
102
|
-
children: []
|
|
103
|
-
- id: spawner-targets
|
|
104
|
-
type: Group2D
|
|
105
|
-
name: Spawner Targets
|
|
106
|
-
properties:
|
|
107
|
-
width: 900
|
|
108
|
-
height: 60
|
|
109
|
-
transform:
|
|
110
|
-
position: [0, 690]
|
|
111
|
-
scale: [1, 1]
|
|
112
|
-
rotation: 0
|
|
113
|
-
components:
|
|
114
|
-
- id: target-spawner
|
|
115
|
-
type: user:Spawner
|
|
116
|
-
enabled: true
|
|
117
|
-
config:
|
|
118
|
-
prefab: res://scenes/prefabs/target.pix3scene
|
|
119
|
-
parentNode: ""
|
|
120
|
-
intervalSec: 0.85
|
|
121
|
-
intervalJitter: 0.3
|
|
122
|
-
maxAlive: 8
|
|
123
|
-
spawnWidth: 820
|
|
124
|
-
spawnHeight: 60
|
|
125
|
-
gridSnap: 0
|
|
126
|
-
driftX: 0
|
|
127
|
-
driftY: -230
|
|
128
|
-
lifetimeSec: 8
|
|
129
|
-
despawnRadius: 1450
|
|
130
|
-
startDelaySec: 0.3
|
|
131
|
-
children: []
|
|
132
|
-
- id: spawner-hazards
|
|
133
|
-
type: Group2D
|
|
134
|
-
name: Spawner Hazards
|
|
135
|
-
properties:
|
|
136
|
-
width: 900
|
|
137
|
-
height: 60
|
|
138
|
-
transform:
|
|
139
|
-
position: [0, 690]
|
|
140
|
-
scale: [1, 1]
|
|
141
|
-
rotation: 0
|
|
142
|
-
components:
|
|
143
|
-
- id: hazard-spawner
|
|
144
|
-
type: user:Spawner
|
|
145
|
-
enabled: true
|
|
146
|
-
config:
|
|
147
|
-
prefab: res://scenes/prefabs/hazard.pix3scene
|
|
148
|
-
parentNode: ""
|
|
149
|
-
intervalSec: 2.2
|
|
150
|
-
intervalJitter: 0.8
|
|
151
|
-
maxAlive: 5
|
|
152
|
-
spawnWidth: 820
|
|
153
|
-
spawnHeight: 60
|
|
154
|
-
gridSnap: 0
|
|
155
|
-
driftX: 0
|
|
156
|
-
driftY: -260
|
|
157
|
-
lifetimeSec: 8
|
|
158
|
-
despawnRadius: 1450
|
|
159
|
-
startDelaySec: 1.5
|
|
160
|
-
children: []
|
|
161
|
-
- id: hud
|
|
162
|
-
type: CanvasLayer2D
|
|
163
|
-
name: HUD
|
|
164
|
-
properties:
|
|
165
|
-
width: 1080
|
|
166
|
-
height: 1920
|
|
167
|
-
layout:
|
|
168
|
-
enabled: true
|
|
169
|
-
horizontalAlign: stretch
|
|
170
|
-
verticalAlign: stretch
|
|
171
|
-
components:
|
|
172
|
-
- id: score-hud
|
|
173
|
-
type: user:ScoreHud
|
|
174
|
-
enabled: true
|
|
175
|
-
config:
|
|
176
|
-
sourceNode: game-root
|
|
177
|
-
scoreLabel: score-label
|
|
178
|
-
scoreFormat: "SCORE {value}"
|
|
179
|
-
timeLabel: time-label
|
|
180
|
-
timeFormat: "{value}"
|
|
181
|
-
livesBar: lives-bar
|
|
182
|
-
children:
|
|
183
|
-
- id: score-label
|
|
184
|
-
type: Label2D
|
|
185
|
-
name: Score Label
|
|
186
|
-
properties:
|
|
187
|
-
label: "SCORE 0"
|
|
188
|
-
labelFontSize: 44
|
|
189
|
-
labelColor: "#ffffff"
|
|
190
|
-
labelAlign: left
|
|
191
|
-
transform:
|
|
192
|
-
position: [-340, 850]
|
|
193
|
-
scale: [1, 1]
|
|
194
|
-
rotation: 0
|
|
195
|
-
layout:
|
|
196
|
-
enabled: true
|
|
197
|
-
horizontalAlign: left
|
|
198
|
-
verticalAlign: top
|
|
199
|
-
children: []
|
|
200
|
-
- id: time-label
|
|
201
|
-
type: Label2D
|
|
202
|
-
name: Time Label
|
|
203
|
-
properties:
|
|
204
|
-
label: "30"
|
|
205
|
-
labelFontSize: 44
|
|
206
|
-
labelColor: "#f5ae39"
|
|
207
|
-
labelAlign: center
|
|
208
|
-
transform:
|
|
209
|
-
position: [0, 850]
|
|
210
|
-
scale: [1, 1]
|
|
211
|
-
rotation: 0
|
|
212
|
-
layout:
|
|
213
|
-
enabled: true
|
|
214
|
-
horizontalAlign: center
|
|
215
|
-
verticalAlign: top
|
|
216
|
-
children: []
|
|
217
|
-
- id: lives-bar
|
|
218
|
-
type: Bar2D
|
|
219
|
-
name: Lives Bar
|
|
220
|
-
properties:
|
|
221
|
-
width: 240
|
|
222
|
-
height: 28
|
|
223
|
-
minValue: 0
|
|
224
|
-
maxValue: 3
|
|
225
|
-
value: 3
|
|
226
|
-
barColor: "#ff4d6d"
|
|
227
|
-
backBackgroundColor: "#2a3352"
|
|
228
|
-
showBorder: false
|
|
229
|
-
transform:
|
|
230
|
-
position: [340, 855]
|
|
231
|
-
scale: [1, 1]
|
|
232
|
-
rotation: 0
|
|
233
|
-
layout:
|
|
234
|
-
enabled: true
|
|
235
|
-
horizontalAlign: right
|
|
236
|
-
verticalAlign: top
|
|
237
|
-
children: []
|
|
238
|
-
- id: menu-button
|
|
239
|
-
type: Button2D
|
|
240
|
-
name: Menu Button
|
|
241
|
-
properties:
|
|
242
|
-
width: 200
|
|
243
|
-
height: 72
|
|
244
|
-
label: "MENU"
|
|
245
|
-
labelFontSize: 30
|
|
246
|
-
labelColor: "#ffffff"
|
|
247
|
-
backgroundColor: "#2a3352"
|
|
248
|
-
hoverColor: "#3a446b"
|
|
249
|
-
pressedColor: "#1d2743"
|
|
250
|
-
buttonAction: back-to-menu
|
|
251
|
-
transform:
|
|
252
|
-
position: [-400, -880]
|
|
253
|
-
scale: [1, 1]
|
|
254
|
-
rotation: 0
|
|
255
|
-
layout:
|
|
256
|
-
enabled: true
|
|
257
|
-
horizontalAlign: left
|
|
258
|
-
verticalAlign: bottom
|
|
259
|
-
children: []
|
|
260
|
-
# Win/lose screen — authored in scenes/ui/result.pix3scene so this
|
|
261
|
-
# scene opens on the GAME, not on a GAME OVER card. `visible: false`
|
|
262
|
-
# hides it in the EDITOR only; `initiallyVisible` (in the overlay
|
|
263
|
-
# file) is what play mode reads, and GameRules reveals it on the
|
|
264
|
-
# win/lose transition. Tick the eye to preview it over the field.
|
|
265
|
-
- id: result-overlay
|
|
266
|
-
name: Result Overlay
|
|
267
|
-
instance: res://scenes/ui/result.pix3scene
|
|
268
|
-
properties:
|
|
269
|
-
visible: false
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# Pix3 Scene File (YAML)
|
|
2
|
-
# Tapper 2D — 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 game
|
|
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: "#141a2e"
|
|
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: "TAP FAST. MISS NOTHING."
|
|
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: []
|