@playcraft/cli 0.0.39 → 0.0.41
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/README.md +66 -3
- package/dist/atom-plan/validate-atom-plan.js +298 -0
- package/dist/cli-root-help.js +1 -1
- package/dist/commands/3d.js +363 -0
- package/dist/commands/create.js +337 -0
- package/dist/commands/fix-ids.js +17 -3
- package/dist/commands/fix-ids.test.js +264 -0
- package/dist/commands/image.js +1337 -43
- package/dist/commands/login.js +60 -2
- package/dist/commands/recommend.js +1 -1
- package/dist/commands/remix.js +213 -0
- package/dist/commands/skills.js +1379 -0
- package/dist/commands/tools-3d.js +473 -0
- package/dist/commands/tools-generation.js +454 -0
- package/dist/commands/tools-project.js +400 -0
- package/dist/commands/tools-research.js +37 -0
- package/dist/commands/tools-research.test.js +216 -0
- package/dist/commands/tools-utils.js +164 -0
- package/dist/commands/tools.js +7 -616
- package/dist/config.js +2 -0
- package/dist/index.js +20 -2
- package/dist/utils/agent-api-client.js +52 -16
- package/package.json +9 -3
- package/project-template/.claude/agents/designer.md +116 -0
- package/project-template/.claude/agents/developer.md +133 -0
- package/project-template/.claude/agents/pm.md +164 -0
- package/project-template/.claude/agents/refs/README.md +67 -0
- package/project-template/.claude/agents/refs/designer-art-style-catalog.md +533 -0
- package/project-template/.claude/agents/refs/designer-color-audio-recipes.md +153 -0
- package/project-template/.claude/agents/refs/designer-deliverable-spec.md +167 -0
- package/project-template/.claude/agents/refs/designer-dimension-axis.md +27 -0
- package/project-template/.claude/agents/refs/designer-handoff-v2-checklist.md +68 -0
- package/project-template/.claude/agents/refs/designer-master-composite-recipes.md +216 -0
- package/project-template/.claude/agents/refs/designer-style-exploration-flow.md +37 -0
- package/project-template/.claude/agents/refs/developer-dev-handoff.md +109 -0
- package/project-template/.claude/agents/refs/developer-impl-cookbook.md +134 -0
- package/project-template/.claude/agents/refs/developer-phase1-flow.md +211 -0
- package/project-template/.claude/agents/refs/pm-workflow-detail.md +545 -0
- package/project-template/.claude/agents/refs/reviewer-six-dimension-eval.md +286 -0
- package/project-template/.claude/agents/refs/ta-3d-flip-recipe.md +85 -0
- package/project-template/.claude/agents/refs/ta-atlas-deliverable-standard.md +46 -0
- package/project-template/.claude/agents/refs/ta-batch-pipeline-recipes.md +120 -0
- package/project-template/.claude/agents/refs/ta-image-generation-detail.md +356 -0
- package/project-template/.claude/agents/refs/ta-image-ops-reference.md +495 -0
- package/project-template/.claude/agents/refs/ta-pipeline-cookbook.md +699 -0
- package/project-template/.claude/agents/refs/ta-tools-reference.md +111 -0
- package/project-template/.claude/agents/refs/ta-vfx-preset-catalog.md +365 -0
- package/project-template/.claude/agents/reviewer.md +103 -0
- package/project-template/.claude/agents/technical-artist.md +111 -0
- package/project-template/.claude/hooks/README.md +36 -0
- package/project-template/.claude/hooks/validate-atom-plan.mjs +224 -0
- package/project-template/.claude/hooks/validate-workflow-stop.mjs +258 -0
- package/project-template/.claude/settings.json +32 -0
- package/project-template/.claude/settings.local.json +4 -0
- package/project-template/.claude/skills/playcraft-ad-psychology/SKILL.md +182 -0
- package/project-template/.claude/skills/playcraft-art-style-guide/SKILL.md +123 -0
- package/project-template/.claude/skills/playcraft-asset-state-sheet/SKILL.md +141 -0
- package/project-template/.claude/skills/playcraft-audio-generation/SKILL.md +280 -0
- package/project-template/.claude/skills/playcraft-batch-pipeline/SKILL.md +184 -0
- package/project-template/.claude/skills/playcraft-build-optimizer/SKILL.md +306 -0
- package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +229 -0
- package/project-template/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +123 -0
- package/project-template/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +254 -0
- package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +235 -0
- package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +97 -0
- package/project-template/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +118 -0
- package/project-template/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +137 -0
- package/project-template/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +397 -0
- package/project-template/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +296 -0
- package/project-template/.claude/skills/playcraft-image-ops/SKILL.md +122 -0
- package/project-template/.claude/skills/playcraft-masking/SKILL.md +373 -0
- package/project-template/.claude/skills/playcraft-research/SKILL.md +212 -0
- package/project-template/.claude/skills/playcraft-sprite-generation/SKILL.md +423 -0
- package/project-template/.claude/skills/playcraft-storyboard/SKILL.md +148 -0
- package/project-template/.claude/skills/playcraft-style-qa/SKILL.md +270 -0
- package/project-template/.claude/skills/playcraft-text-rendering/SKILL.md +236 -0
- package/project-template/.claude/skills/playcraft-vfx-animation/SKILL.md +130 -0
- package/project-template/.claude/skills/playcraft-workflow/SKILL.md +396 -0
- package/project-template/.cursor/hooks.json +17 -0
- package/project-template/.cursor/rules/playcraft-orchestrator.mdc +87 -0
- package/project-template/.cursor/rules/playcraft-subagent-boundary.mdc +18 -0
- package/project-template/CLAUDE.md +240 -0
- package/project-template/assets/audio/bgm/.gitkeep +0 -0
- package/project-template/assets/audio/sfx/.gitkeep +0 -0
- package/project-template/assets/bundles/.gitkeep +0 -0
- package/project-template/assets/images/bg/.gitkeep +0 -0
- package/project-template/assets/images/reference/.gitkeep +0 -0
- package/project-template/assets/images/storyboard/.gitkeep +0 -0
- package/project-template/assets/images/tiles/.gitkeep +0 -0
- package/project-template/assets/images/ui/.gitkeep +0 -0
- package/project-template/assets/images/vfx/.gitkeep +0 -0
- package/project-template/assets/models/.gitkeep +0 -0
- package/project-template/docs/team/agent-conduct.md +105 -0
- package/project-template/docs/team/agent-runtime-matrix.md +62 -0
- package/project-template/docs/team/atom-plan-format.md +74 -0
- package/project-template/docs/team/collaboration.md +288 -0
- package/project-template/docs/team/core-model.md +50 -0
- package/project-template/docs/team/platform-capabilities.md +15 -0
- package/project-template/docs/team/workflow-changelog.md +51 -0
- package/project-template/docs/team/workflow-consistency-checklist.md +128 -0
- package/project-template/game/config/.gitkeep +0 -0
- package/project-template/game/gameplay/.gitkeep +0 -0
- package/project-template/game/scenes/.gitkeep +0 -0
- package/project-template/logs/.gitkeep +0 -0
- package/project-template/ta-workspace/logs/.gitkeep +0 -0
- package/project-template/ta-workspace/scripts/.gitkeep +0 -0
- package/project-template/ta-workspace/tmp/.gitkeep +0 -0
- package/project-template/templates/atom-plan.template.json +26 -0
- package/project-template/templates/atom-plan.template.md +76 -0
- package/project-template/templates/design-brief.template.md +195 -0
- package/project-template/templates/design-lens-checklist.reference.md +117 -0
- package/project-template/templates/design-methodology.md +99 -0
- package/project-template/templates/designer-log.template.md +98 -0
- package/project-template/templates/developer-log.template.md +140 -0
- package/project-template/templates/five-axis-framework.md +186 -0
- package/project-template/templates/intent-clarifications.template.md +58 -0
- package/project-template/templates/layout-spec.template.md +132 -0
- package/project-template/templates/project-state.template.md +219 -0
- package/project-template/templates/review-report.template.md +166 -0
- package/project-template/templates/style-exploration.template.md +93 -0
- package/project-template/templates/ta-log.template.md +205 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: playcraft-build-optimizer
|
|
3
|
+
description: 可玩广告构建优化与平台合规验证完整指南。涵盖 playcraft build 全部优化参数(图片压缩/WebP转换/模型压缩/JS混淆)、正确的优化执行顺序(避免多次有损压缩)、各平台合规验证清单(文件大小/外部请求/CTA API/音频自动播放)、Base64 膨胀系数计算。供未来 Optimizer Agent 使用。
|
|
4
|
+
triggers: 构建优化,build optimizer,压缩,compress,WebP,pngquant,文件大小,file size,合规验证,compliance,CTA API,FbPlayableAd,ExitApi,外部请求,external request,体积,5MB限制,build参数,optimize,minify
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 可玩广告构建优化与合规验证指南
|
|
8
|
+
|
|
9
|
+
> **使用时机**:在 Developer Phase 2(集成构建)完成、产出 index.html 之后执行。优化是最后一步,不在生产阶段执行。
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 0. 关键数字速查
|
|
14
|
+
|
|
15
|
+
| 约束项 | 数值 | 说明 |
|
|
16
|
+
| ---------------- | --------------------------- | ---------------------------------------- |
|
|
17
|
+
| 最终文件大小上限 | 5 MB | Meta/Google/AppLovin/IronSource 统一标准 |
|
|
18
|
+
| 原始资产建议上限 | 3.75 MB | Base64 编码后膨胀 ×1.33,需提前预留空间 |
|
|
19
|
+
| 触控目标最小尺寸 | 48×48 px | 防止误触,符合 WCAG 可访问性标准 |
|
|
20
|
+
| CTA 对比度下限 | 4.5:1 | WCAG AA 标准(CTA 按钮与背景) |
|
|
21
|
+
| Meta CTA API | `FbPlayableAd.onCTAClick()` | 必须实现,否则审核拒绝 |
|
|
22
|
+
| Google CTA API | `ExitApi.exit()` | 必须实现,否则审核拒绝 |
|
|
23
|
+
| 音频自动播放 | 禁止 | 必须等用户交互后才能播放 |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. 合规验证清单(构建后必须执行)
|
|
28
|
+
|
|
29
|
+
### 1.1 文件大小验证
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# 检查最终输出文件大小
|
|
33
|
+
playcraft image info --input dist/index.html --json # 不适用,用 shell
|
|
34
|
+
|
|
35
|
+
# Shell 方法:检查文件大小(字节)
|
|
36
|
+
du -sh dist/index.html
|
|
37
|
+
ls -lh dist/index.html
|
|
38
|
+
|
|
39
|
+
# 计算:若当前原始资产总大小为 X MB
|
|
40
|
+
# 预计最终 HTML 大小 ≈ X × 1.33(Base64 膨胀)
|
|
41
|
+
# 若预计超过 5 MB,需要压缩
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Base64 膨胀系数说明**:`playcraft build` 会将所有资产(图片、音频、模型)内嵌到单个 HTML 文件中,编码为 Base64。Base64 编码会使数据体积增加约 33%。
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
原始资产总大小 × 1.33 ≈ 最终 HTML 文件大小
|
|
48
|
+
→ 要保证最终 < 5 MB,原始资产须 < 3.75 MB
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 1.2 外部请求检查
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# 在项目代码中搜索外部请求(构建前检查)
|
|
55
|
+
grep -r "fetch(" game/ --include="*.js" --include="*.ts"
|
|
56
|
+
grep -r "XMLHttpRequest" game/ --include="*.js" --include="*.ts"
|
|
57
|
+
grep -r "https://" game/ --include="*.js" --include="*.ts"
|
|
58
|
+
grep -r "http://" game/ --include="*.js" --include="*.ts"
|
|
59
|
+
grep -r "<script src=" game/ --include="*.html"
|
|
60
|
+
grep -r "<link href=" game/ --include="*.html"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**零外部请求要求**:最终 HTML 不得包含任何外部 URL(CDN、API、图片链接等)。所有资源必须内嵌。
|
|
64
|
+
|
|
65
|
+
### 1.3 CTA API 实现验证
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# 检查 Meta CTA API 实现
|
|
69
|
+
grep -r "FbPlayableAd.onCTAClick" game/ --include="*.js" --include="*.ts"
|
|
70
|
+
# 若无匹配 → CTA 功能不完整,需要 Developer 补充
|
|
71
|
+
|
|
72
|
+
# 检查 Google CTA API 实现
|
|
73
|
+
grep -r "ExitApi.exit" game/ --include="*.js" --include="*.ts"
|
|
74
|
+
# 若无匹配 → Google Ads 版本缺少 CTA,需要 Developer 补充
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**CTA API 标准实现**(供 Developer 参考):
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
// 多平台兼容 CTA 处理
|
|
81
|
+
function handleCTAClick() {
|
|
82
|
+
// Meta / Facebook
|
|
83
|
+
if (typeof FbPlayableAd !== "undefined") {
|
|
84
|
+
FbPlayableAd.onCTAClick();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Google Ads / AdMob
|
|
88
|
+
if (typeof ExitApi !== "undefined") {
|
|
89
|
+
ExitApi.exit();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// AppLovin / IronSource / 其他
|
|
93
|
+
if (typeof mraid !== "undefined") {
|
|
94
|
+
mraid.open(STORE_URL);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// Fallback
|
|
98
|
+
window.open(STORE_URL, "_blank");
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 1.4 音频自动播放检查
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# 检查是否有自动播放的音频
|
|
106
|
+
grep -r "autoplay" game/ --include="*.js" --include="*.ts" --include="*.html"
|
|
107
|
+
grep -r "\.play()" game/ --include="*.js" --include="*.ts"
|
|
108
|
+
# 所有 .play() 调用必须在用户交互事件(click/touchstart)的回调内
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 2. playcraft build 优化参数
|
|
114
|
+
|
|
115
|
+
### 完整优化构建命令
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# 标准优化构建(Meta 平台)
|
|
119
|
+
playcraft build . \
|
|
120
|
+
--platform facebook \
|
|
121
|
+
--compress-images \
|
|
122
|
+
--image-quality 85 \
|
|
123
|
+
--convert-webp \
|
|
124
|
+
--js-minify \
|
|
125
|
+
--css-minify \
|
|
126
|
+
--output dist/
|
|
127
|
+
|
|
128
|
+
# 带 3D 模型压缩的构建
|
|
129
|
+
playcraft build . \
|
|
130
|
+
--platform facebook \
|
|
131
|
+
--compress-images \
|
|
132
|
+
--image-quality 80 \
|
|
133
|
+
--convert-webp \
|
|
134
|
+
--compress-models \
|
|
135
|
+
--model-compression draco \
|
|
136
|
+
--js-minify \
|
|
137
|
+
--output dist/
|
|
138
|
+
|
|
139
|
+
# 分析体积占用(不构建,只分析)
|
|
140
|
+
playcraft build . \
|
|
141
|
+
--platform facebook \
|
|
142
|
+
--analyze
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### 图片优化参数
|
|
146
|
+
|
|
147
|
+
| 参数 | 说明 | 默认 |
|
|
148
|
+
| ------------------------- | ------------------------- | ---------- |
|
|
149
|
+
| `--compress-images` | 启用图片压缩(pngquant) | 需显式开启 |
|
|
150
|
+
| `--image-quality <0-100>` | 压缩质量(底层 pngquant) | 85 |
|
|
151
|
+
| `--convert-webp` | 将 PNG/JPG 转换为 WebP | 默认开启 |
|
|
152
|
+
| `--no-convert-webp` | 禁用 WebP 转换 | — |
|
|
153
|
+
|
|
154
|
+
**pngquant 说明**:`--compress-images` 使用 `imagemin-pngquant` 进行 PNG 调色板量化,可减少 30-50% 体积,无明显视觉损失(对像素艺术效果更好)。
|
|
155
|
+
|
|
156
|
+
**WebP 说明**:`--convert-webp` 将图片转换为 WebP 格式,比 PNG 减少 60-75%,比 JPG 减少 25-34%,且支持透明通道。现代移动端浏览器均支持。
|
|
157
|
+
|
|
158
|
+
### 模型优化参数
|
|
159
|
+
|
|
160
|
+
| 参数 | 说明 |
|
|
161
|
+
| ----------------------------- | ------------------------------------- |
|
|
162
|
+
| `--compress-models` | 启用 3D 模型压缩 |
|
|
163
|
+
| `--model-compression draco` | 使用 Draco 几何压缩(通用,广泛支持) |
|
|
164
|
+
| `--model-compression meshopt` | 使用 MeshOptimizer(更高压缩比) |
|
|
165
|
+
|
|
166
|
+
### JS/CSS 优化参数
|
|
167
|
+
|
|
168
|
+
| 参数 | 说明 |
|
|
169
|
+
| -------------- | ----------------------------- |
|
|
170
|
+
| `--js-minify` | 启用 JS 压缩(Terser + 混淆) |
|
|
171
|
+
| `--css-minify` | 启用 CSS 压缩 |
|
|
172
|
+
|
|
173
|
+
### 多平台批量构建
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# 同时构建多个平台版本
|
|
177
|
+
playcraft build-all . \
|
|
178
|
+
--platforms facebook,google,applovin \
|
|
179
|
+
--compress-images \
|
|
180
|
+
--image-quality 85 \
|
|
181
|
+
--convert-webp \
|
|
182
|
+
--js-minify \
|
|
183
|
+
--output dist/
|
|
184
|
+
|
|
185
|
+
# 或按平台组
|
|
186
|
+
playcraft build-all . \
|
|
187
|
+
--group mainstream \ # 主流平台
|
|
188
|
+
--compress-images \
|
|
189
|
+
--convert-webp
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 3. 正确的优化执行顺序
|
|
195
|
+
|
|
196
|
+
**关键原则**:避免对同一文件多次执行有损压缩(每次有损压缩都会叠加质量损失)。
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
正确顺序:
|
|
200
|
+
1. 检查原始资产总大小
|
|
201
|
+
↓
|
|
202
|
+
2. 3D 模型压缩(draco/meshopt)— 无损几何优化
|
|
203
|
+
↓
|
|
204
|
+
3. playcraft build --convert-webp — PNG→WebP(一次有损转换)
|
|
205
|
+
↓
|
|
206
|
+
4. playcraft build --compress-images --image-quality 85 — pngquant(针对非 WebP 的 PNG)
|
|
207
|
+
↓
|
|
208
|
+
5. playcraft build --js-minify --css-minify — 代码压缩
|
|
209
|
+
↓
|
|
210
|
+
6. 检查最终文件大小(必须 < 5 MB)
|
|
211
|
+
↓
|
|
212
|
+
7. 合规验证清单(§1)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**禁止行为**:
|
|
216
|
+
|
|
217
|
+
- 不要先用 `playcraft image convert --format webp` 手动转换,再用 `--convert-webp` 构建(双重转换)
|
|
218
|
+
- 不要对同一图片多次运行 `--compress-images`(每次都会损失质量)
|
|
219
|
+
- 生产阶段(Designer/TA)产出应保持 PNG 格式,优化阶段统一转换
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## 4. 单文件优化(构建后问题文件处理)
|
|
224
|
+
|
|
225
|
+
当某个文件体积异常大时,可单独优化:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
# 查看问题文件大小
|
|
229
|
+
playcraft image info --input assets/images/bg/background.png --json
|
|
230
|
+
|
|
231
|
+
# 单文件转 WebP(有损,质量 85)
|
|
232
|
+
playcraft image convert \
|
|
233
|
+
--input assets/images/bg/background.png \
|
|
234
|
+
--output assets/images/bg/background.webp \
|
|
235
|
+
--format webp \
|
|
236
|
+
--quality 85
|
|
237
|
+
|
|
238
|
+
# 单文件转 WebP(无损,适合 UI 元素和像素艺术)
|
|
239
|
+
playcraft image convert \
|
|
240
|
+
--input assets/images/ui/button.png \
|
|
241
|
+
--output assets/images/ui/button.webp \
|
|
242
|
+
--format webp \
|
|
243
|
+
--lossless
|
|
244
|
+
|
|
245
|
+
# 音频压缩(降低比特率)
|
|
246
|
+
playcraft audio compress \
|
|
247
|
+
--input assets/audio/bgm/main_theme.mp3 \
|
|
248
|
+
--output assets/audio/bgm/main_theme_compressed.mp3 \
|
|
249
|
+
--bitrate 96k \
|
|
250
|
+
--mono
|
|
251
|
+
|
|
252
|
+
# 3D 模型优化
|
|
253
|
+
playcraft 3d optimize \
|
|
254
|
+
--input assets/models/character.glb \
|
|
255
|
+
--output assets/models/character_optimized.glb \
|
|
256
|
+
--texture-size 512
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## 5. 优化报告格式
|
|
262
|
+
|
|
263
|
+
完成优化后,写入 `logs/optimizer-log.md`:
|
|
264
|
+
|
|
265
|
+
```markdown
|
|
266
|
+
# Optimizer Log
|
|
267
|
+
|
|
268
|
+
## 构建信息
|
|
269
|
+
|
|
270
|
+
- 平台:{{platform}}
|
|
271
|
+
- 构建时间:{{timestamp}}
|
|
272
|
+
- 最终文件大小:{{size_mb}} MB(限制:5 MB)
|
|
273
|
+
- 构建状态:{{pass/fail}}
|
|
274
|
+
|
|
275
|
+
## 资产优化摘要
|
|
276
|
+
|
|
277
|
+
| 资产类型 | 优化前总大小 | 优化后总大小 | 压缩率 |
|
|
278
|
+
| ------------------ | ------------- | ------------ | ---------- |
|
|
279
|
+
| 图片(PNG → WebP) | {{before}} MB | {{after}} MB | {{ratio}}% |
|
|
280
|
+
| 3D 模型 | {{before}} MB | {{after}} MB | {{ratio}}% |
|
|
281
|
+
| 音频 | {{before}} MB | {{after}} MB | {{ratio}}% |
|
|
282
|
+
| JS/CSS | {{before}} KB | {{after}} KB | {{ratio}}% |
|
|
283
|
+
|
|
284
|
+
## 合规验证结果
|
|
285
|
+
|
|
286
|
+
- [ ] 文件大小 ≤ 5 MB
|
|
287
|
+
- [ ] 零外部请求
|
|
288
|
+
- [ ] Meta CTA API 实现(FbPlayableAd.onCTAClick)
|
|
289
|
+
- [ ] Google CTA API 实现(ExitApi.exit)
|
|
290
|
+
- [ ] 音频无自动播放
|
|
291
|
+
|
|
292
|
+
## 问题与建议
|
|
293
|
+
|
|
294
|
+
{{如有超限或合规问题,在此列出并给出修复建议}}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## 6. 常见审核被拒原因速查
|
|
300
|
+
|
|
301
|
+
| 被拒原因 | 占比 | 检查方法 | 修复方法 |
|
|
302
|
+
| ----------------- | ---- | ------------------------ | ------------------------------------------------------- |
|
|
303
|
+
| 文件大小超过 5 MB | 45% | `ls -lh dist/index.html` | `--compress-images --convert-webp` 或降低 image-quality |
|
|
304
|
+
| 包含外部请求 | 30% | `grep -r "https://"` | Developer 将外部资源内嵌 |
|
|
305
|
+
| CTA 未实现 | 15% | `grep "FbPlayableAd"` | Developer 添加平台 CTA API |
|
|
306
|
+
| 音频自动播放 | 10% | `grep "autoplay"` | Developer 改为用户交互触发 |
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: playcraft-image-generation
|
|
3
|
+
description: PlayCraft AI 图片生成核心决策指南。涵盖模型选择决策树、核心命令模板、背景处理决策树(绿幕策略)、脚本决策规则。精灵图直出/Edit 模型/错误恢复/批量实践等进阶内容见 refs/ta-image-generation-detail.md。
|
|
4
|
+
triggers: 生成图片,generate image,选模型,model selection,reference image,参考图,风格一致,图生图,文生图,AI生图,图片质量,模型选择,500错误,模型失败,generate-image,list-image-models,ta-workspace,batch,批量,脚本,nodejs,edit模型,变体,绿幕,去背景,透明PNG,prompt,提示词,prompt套路,提示词技巧
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# PlayCraft AI 图片生成指南
|
|
8
|
+
|
|
9
|
+
## 0. 开始前必读
|
|
10
|
+
|
|
11
|
+
生图前**必须先运行模型发现命令**:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
playcraft tools list-image-models
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
输出示例:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
MODEL CAPABILITY ALPHA PROVIDERS
|
|
21
|
+
gpt-image-2 text+image no 3 (iegg-litellm, mulerouter, 302)
|
|
22
|
+
gemini-3.1-flash-image-preview text+image no 2 (google, iegg-litellm)
|
|
23
|
+
hy-image-v3.0 text+image no 1 (tencent-cloud)
|
|
24
|
+
flux-kontext-pro text+image no 1 (302)
|
|
25
|
+
qwen-image-edit-max image→image no 1 (mulerouter)
|
|
26
|
+
...
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**列说明**:
|
|
30
|
+
|
|
31
|
+
- `CAPABILITY`:`text→image` 仅文生图 / `image→image` 仅图生图 / `text+image` 两者均支持
|
|
32
|
+
- `ALPHA`:`yes` = 原生透明 PNG;`no` = 需使用绿幕策略(见第 3 节)
|
|
33
|
+
- `PROVIDERS`:支持该模型的 provider 数量,多个 provider 时后端按优先级自动 fallback(顺序尝试,首个成功即返回)
|
|
34
|
+
|
|
35
|
+
**Prompt 套路速查**:[reference/prompt-cookbook.md](reference/prompt-cookbook.md)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 1. 模型选择决策树
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
需要生图?
|
|
43
|
+
├─ 追求最高质量(概念图、精品单图)?
|
|
44
|
+
│ └─ gpt-image-2(3 个 provider 自动 fallback:iegg-litellm → mulerouter → 302)
|
|
45
|
+
│
|
|
46
|
+
├─ 需要 --reference-image(风格一致性批量生产)?
|
|
47
|
+
│ └─ 必须选 CAPABILITY = text+image 或 image→image 的模型
|
|
48
|
+
│
|
|
49
|
+
├─ 同类元素批量生成(<=16 个)?
|
|
50
|
+
│ └─ 精灵图直出策略(见进阶参考)
|
|
51
|
+
│
|
|
52
|
+
├─ 结构相似的变体集(换花色/换数字/换颜色)?
|
|
53
|
+
│ └─ Edit 模型工作流(见进阶参考)
|
|
54
|
+
│
|
|
55
|
+
└─ 不确定?
|
|
56
|
+
└─ 先试 gpt-image-2,失败换 gemini-3.1-flash-image-preview
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 主要模型特性
|
|
60
|
+
|
|
61
|
+
| 模型 | 特点与优势 | 最佳场景 | 速度 | 注意事项 |
|
|
62
|
+
| ---------------------------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------- | ------------------------------- | --------------------------------------------------------------- |
|
|
63
|
+
| **gpt-image-2** | 细节最丰富、光影最真实、网格/布局理解力最强、中文字符准确率最高、3 provider fallback 容错高 | 概念图、精灵图直出、含文字素材、写实/半写实风格 | 慢(7-8min/张),**不设 timeout** | 慢是正常的;只有 `API 500` / `fetch failed` 才切换下一 provider |
|
|
64
|
+
| **gemini-3.1-flash-image-preview** | 速度快、色彩鲜艳、构图清晰、最稳定不易报错、reference-image 理解好 | 快速迭代、扁平卡通、明亮休闲风、超时回退 | 快(<30s) | 精细细节和文字不如 gpt-image-2 |
|
|
65
|
+
| **hy-image-v3.0** | 亚洲审美偏向、角色设计好、Q版/IP风格擅长 | 中国风、Q版角色、IP 形象 | 中等 | 西方写实风格表现一般 |
|
|
66
|
+
| **flux-kontext-pro** | 艺术感强、风格独特、手绘质感好 | 艺术插画、手绘风、独特画风探索 | 中等 | 网格理解弱,不适合精灵图 |
|
|
67
|
+
| **nano-banana-2** | 最快、适合简单图形探索 | 简洁图标、平面设计、快速草稿 | 极快 | 中文字符不可靠、细节少 |
|
|
68
|
+
| **qwen-image-edit-max** | 图生图编辑能力强、局部修改精确 | 换花色/换数字/换颜色等结构相似变体 | 中等 | CAPABILITY=image→image,必须传 reference-image |
|
|
69
|
+
| **wan2.6-image** | 风格迁移能力好 | 将参考图风格应用到新内容 | 中等 | CAPABILITY=image→image,必须传 reference-image |
|
|
70
|
+
|
|
71
|
+
### 选型口诀
|
|
72
|
+
|
|
73
|
+
- 追求质量 / 含文字 / 网格图 → `gpt-image-2`
|
|
74
|
+
- 快速迭代 / 扁平风格 / 回退备选 → `gemini-3.1-flash-image-preview`
|
|
75
|
+
- 中国风 / Q版 / 亚洲审美 → `hy-image-v3.0`
|
|
76
|
+
- 艺术/手绘探索 → `flux-kontext-pro`
|
|
77
|
+
- 纯 edit 变体 → `qwen-image-edit-max`
|
|
78
|
+
- 一切都失败 → `gemini-3.1-flash-image-preview`(最稳定)
|
|
79
|
+
|
|
80
|
+
### 为什么精灵图直出是首选批量策略?
|
|
81
|
+
|
|
82
|
+
精灵图直出(一次 API 调用生成一张包含 N 个元素的网格图,再 sprite-split 切分)优于逐个生成,原因有三:
|
|
83
|
+
|
|
84
|
+
1. **成本**:一次 API 调用可包含 4-16 个元素,而逐个生成 N 个元素需要 N 次调用,成本和耗时线性增长。
|
|
85
|
+
2. **风格一致性**:同一张图中的所有元素共享相同的生成上下文,天然保证色调、线条、阴影风格统一,避免逐个生成时每张图风格漂移的问题。
|
|
86
|
+
3. **无逐元素偏差**:逐个生成时即使用相同 prompt,模型每次采样结果都不同,元素之间会出现肉眼可见的不一致;精灵图在一次推理中完成,消除了这种 per-element drift。
|
|
87
|
+
|
|
88
|
+
详细策略与代码示例见进阶参考。
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 2. 核心命令
|
|
93
|
+
|
|
94
|
+
### 文生图(text-to-image)
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
playcraft tools generate-image \
|
|
98
|
+
--prompt "A golden sword icon, flat 2D vector style, centered composition" \
|
|
99
|
+
--output assets/images/sword.png \
|
|
100
|
+
--aspect-ratio 1:1 \
|
|
101
|
+
--image-size 4K \
|
|
102
|
+
--image-model gpt-image-2
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 图生图(image-to-image / reference-image)
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
playcraft tools generate-image \
|
|
109
|
+
--prompt "A similar style silver shield icon, same art direction" \
|
|
110
|
+
--output assets/images/shield.png \
|
|
111
|
+
--reference-image assets/images/sword.png \
|
|
112
|
+
--aspect-ratio 1:1 \
|
|
113
|
+
--image-size 4K \
|
|
114
|
+
--image-model gpt-image-2
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 参数说明
|
|
118
|
+
|
|
119
|
+
| 参数 | 值 | 说明 |
|
|
120
|
+
| ---------------------- | ----------------------------------------- | ------------------------------------------------------- |
|
|
121
|
+
| `--aspect-ratio` | `1:1` / **`45:16`** / `16:9` / `9:16` / … | **Master Composite(5×9:16 横排)用 `45:16`** |
|
|
122
|
+
| `--width` / `--height` | 像素整数(成对) | MC 推荐 **`3600×1280`** 或 **`4096×1455`** |
|
|
123
|
+
| `--image-size` | `1K` / `2K` / `4K` | 控制分辨率级别。实际像素取决于模型+比例的组合(见下表) |
|
|
124
|
+
|
|
125
|
+
**`--image-size` 对 gpt-image-2 的落盘尺寸**(MuleRouter 请求 `size=auto`,由后端 letterbox 到目标像素):
|
|
126
|
+
|
|
127
|
+
| aspectRatio | 1K | 2K | 4K |
|
|
128
|
+
| ----------------------------- | --------- | ------------- | ------------- |
|
|
129
|
+
| 1:1 | 1024x1024 | 2048x2048 | 2048x2048 |
|
|
130
|
+
| **45:16** (5×9:16 故事板横排) | 2048x728 | **3600x1280** | **4096x1455** |
|
|
131
|
+
| 16:9 | 2048x1152 | 2048x1152 | 3840x2160 |
|
|
132
|
+
| 9:16 | 2160x3840 | 2160x3840 | 2160x3840 |
|
|
133
|
+
| 3:2 / 4:3 | 1536x1024 | 1536x1024 | 1536x1024 |
|
|
134
|
+
| 21:9 | 2048x1152 | 3840x2160 | 3840x2160 |
|
|
135
|
+
|
|
136
|
+
> **IEGG LiteLLM** 在 fallback 链中排第一,但 Azure gpt-image 最大约 1536px 宽 — 达不到 5×9:16 横排。故事板请用 **`mulerouter/gpt-image-2`**(跳过 litellm)+ `--width 3600 --height 1280`(或 4096×1455)。
|
|
137
|
+
|
|
138
|
+
**Phase 1(概念图)**:纯文生图,`--image-size 4K` + 优先 gpt-image-2 追求质量。
|
|
139
|
+
**Phase 2(批量生产)**:必须带 `--reference-image` 指向 Phase 1 确认的概念图,同一批次使用**相同模型 + 相同 reference image + 相同 image-size**。
|
|
140
|
+
|
|
141
|
+
### --reference-image 路径支持
|
|
142
|
+
|
|
143
|
+
- 本地绝对路径:`/path/to/ref.png`
|
|
144
|
+
- 相对路径(相对 CWD):`assets/images/ref.png`
|
|
145
|
+
- HTTP(S) URL(CLI 自动下载):`"https://images.unsplash.com/photo-xxx"`
|
|
146
|
+
- 多张参考图(重复选项,最多 8 张)
|
|
147
|
+
- 混合本地文件 + URL
|
|
148
|
+
- `search-image` 返回的 `downloadUrl` 可直接使用
|
|
149
|
+
|
|
150
|
+
### 常用辅助命令
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# 去背景(绿幕建议 tolerance=25;默认白背景可用 15)
|
|
154
|
+
playcraft image remove-background --input in.png --output out.png --tolerance 25
|
|
155
|
+
|
|
156
|
+
# 缩放
|
|
157
|
+
playcraft image resize --input in.png --output out.png --width 128 --height 128
|
|
158
|
+
|
|
159
|
+
# 精灵图切分
|
|
160
|
+
playcraft image sprite-split \
|
|
161
|
+
--input sheet.png --output-dir frames/ \
|
|
162
|
+
--rows 2 --columns 4 \
|
|
163
|
+
--frame-width <总宽/4> --frame-height <总高/2>
|
|
164
|
+
|
|
165
|
+
# 合并精灵图
|
|
166
|
+
playcraft image sprite-sheet \
|
|
167
|
+
--input-dir processed/ --output bundle \
|
|
168
|
+
--columns 8 --background white
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 3. 背景处理决策树
|
|
174
|
+
|
|
175
|
+
> **核心原则**:先确定素材类型,再决定是否需要去背景,再决定 prompt 应该写什么。
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
生成的素材需要做什么?
|
|
179
|
+
│
|
|
180
|
+
├─ 需要透明背景的独立元素(角色、道具、图标)?
|
|
181
|
+
│ ├─ 检查模型 ALPHA 列(playcraft tools list-image-models)
|
|
182
|
+
│ ├─ ALPHA = yes → prompt 加 "transparent background, PNG with alpha"
|
|
183
|
+
│ └─ ALPHA = no → 绿幕策略:
|
|
184
|
+
│ ├─ prompt 末尾加 "on solid bright green #00FF00 background, isolated, centered"
|
|
185
|
+
│ └─ 后处理:remove-background(floodfill,tolerance 25)
|
|
186
|
+
│
|
|
187
|
+
├─ 卡牌/棋盘格子/UI 面板(本身就是矩形有边框)?
|
|
188
|
+
│ ├─ 不要去背景!白色牌面就是牌的一部分
|
|
189
|
+
│ ├─ prompt 加 "flat 2D, no drop shadow, no 3D effect, clean edges"
|
|
190
|
+
│ └─ 后处理:直接 resize(skipRemoveBg = true)
|
|
191
|
+
│
|
|
192
|
+
└─ 场景背景(天空、地面、全屏图)?
|
|
193
|
+
└─ 不做背景处理,直接 resize
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 为什么需要绿幕策略?
|
|
197
|
+
|
|
198
|
+
**当前所有已接入模型均不支持原生透明 PNG(ALPHA = no)**。白色背景 + 白色物体 = floodfill 无法区分边界。绿色背景 + 任何游戏素材 = 极少撞色,抠图几乎完美。与影视 chroma-key 原理相同。
|
|
199
|
+
|
|
200
|
+
### Prompt 后缀速查表
|
|
201
|
+
|
|
202
|
+
| 素材类型 | prompt 建议后缀 | 后处理 | skipRemoveBg |
|
|
203
|
+
| --------------------- | ------------------------------------------------------------------- | -------------------------------- | ------------ |
|
|
204
|
+
| 独立元素(需透明) | `"on solid bright green #00FF00 background, isolated, centered"` | remove-background (tolerance 25) | `false` |
|
|
205
|
+
| 卡牌/棋子(矩形本体) | `"flat 2D, no shadow, no 3D effect, clean edges, white background"` | 只做 resize | `true` |
|
|
206
|
+
| UI 按钮/面板 | `"flat UI element, no shadow, clean edges"` | trim + resize | `true` |
|
|
207
|
+
| 场景背景 | `"full scene, edge to edge"` | 只做 resize | `true` |
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 4. 脚本决策
|
|
212
|
+
|
|
213
|
+
- **<=5 个文件** → 直接使用 CLI 命令
|
|
214
|
+
- **>5 个文件** → 编写 Node.js 脚本放入 `ta-workspace/scripts/`。脚本模板见 `reference/` 目录。
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 5. 进阶参考
|
|
219
|
+
|
|
220
|
+
需要以下进阶内容时,查阅 [`refs/ta-image-generation-detail.md`](../../agents/refs/ta-image-generation-detail.md):
|
|
221
|
+
|
|
222
|
+
| 主题 | 说明 |
|
|
223
|
+
| --------------------- | ------------------------------------------------------------------- |
|
|
224
|
+
| 精灵图直出策略 | gpt-image-2 网格图生成 + sprite-split 切分,白底/绿幕示例,分批策略 |
|
|
225
|
+
| Edit 模型工作流 | 基图 → edit 变体(换花色/换数字/换颜色),prompt 写法 |
|
|
226
|
+
| 错误恢复表 | 各类错误现象、原因、立即行动;模型回退顺序 |
|
|
227
|
+
| Provider 回退链 | gpt-image-2 三 provider 互为回退 + 非 gpt-image-2 稳定回退 |
|
|
228
|
+
| 批量生成最佳实践 | 单张验证、Node.js 脚本推荐、脚本模板使用 |
|
|
229
|
+
| ta-workspace 脚本驱动 | 为什么用 Node.js、目录约定、脚本模板一览表 |
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// build-sprite-sheet.template.mjs — 精灵图合并 + 验证脚本模板
|
|
3
|
+
// 用途:将处理好的图片目录合并为精灵图(PNG + JSON 元数据)
|
|
4
|
+
//
|
|
5
|
+
// 使用方式:
|
|
6
|
+
// 1. cp .claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs ta-workspace/scripts/build-<name>-atlas.mjs
|
|
7
|
+
// 2. 修改下方 CONFIG 区域
|
|
8
|
+
// 3. 如需控制帧顺序,填写 ORDERED_NAMES 数组(留空则按文件名排序)
|
|
9
|
+
// 4. node ta-workspace/scripts/build-<name>-atlas.mjs
|
|
10
|
+
// ============================================================
|
|
11
|
+
|
|
12
|
+
import { execSync } from 'child_process';
|
|
13
|
+
import { existsSync, readFileSync, readdirSync, mkdirSync, appendFileSync } from 'fs';
|
|
14
|
+
import { join, extname } from 'path';
|
|
15
|
+
|
|
16
|
+
// ============ CONFIG — 修改这里 ============
|
|
17
|
+
const CONFIG = {
|
|
18
|
+
/** 处理好的图片目录(process-batch 的输出目录) */
|
|
19
|
+
processedDir: 'assets/images/processed',
|
|
20
|
+
/** 输出文件路径(不含扩展名,会生成 .png 和 .json 两个文件) */
|
|
21
|
+
outputBase: 'assets/bundles/atlas',
|
|
22
|
+
/** 每行帧数 */
|
|
23
|
+
columns: 8,
|
|
24
|
+
/** 帧间距(像素) */
|
|
25
|
+
padding: 2,
|
|
26
|
+
/**
|
|
27
|
+
* 精灵图背景色
|
|
28
|
+
* - 'transparent'(默认):透明背景
|
|
29
|
+
* - 'white' / 'black' / '#RRGGBB':固定背景色
|
|
30
|
+
* 某些引擎(如 PlayCanvas)处理透明精灵图时可能显示为黑色,此时用 'white' 更安全
|
|
31
|
+
*/
|
|
32
|
+
background: 'transparent',
|
|
33
|
+
/** 文件名排序方式:'name'(字母序)或 'custom'(使用 ORDERED_NAMES) */
|
|
34
|
+
sort: 'name',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 自定义帧顺序(CONFIG.sort = 'custom' 时生效)
|
|
39
|
+
* 填写不含扩展名的文件名,按期望顺序排列
|
|
40
|
+
* 示例(扑克牌):['spades_A', 'spades_2', 'spades_3', ...]
|
|
41
|
+
*/
|
|
42
|
+
const ORDERED_NAMES = [
|
|
43
|
+
// 填写文件名(不含扩展名)...
|
|
44
|
+
];
|
|
45
|
+
// ============ LOGIC — 通常不需要修改 ============
|
|
46
|
+
|
|
47
|
+
const LOG_FILE = 'ta-workspace/logs/build-sprite-sheet.log';
|
|
48
|
+
mkdirSync('ta-workspace/logs', { recursive: true });
|
|
49
|
+
|
|
50
|
+
function log(msg) {
|
|
51
|
+
const line = `[${new Date().toISOString()}] ${msg}`;
|
|
52
|
+
console.log(line);
|
|
53
|
+
appendFileSync(LOG_FILE, line + '\n');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 收集输入文件
|
|
57
|
+
let inputFiles;
|
|
58
|
+
if (CONFIG.sort === 'custom' && ORDERED_NAMES.length > 0) {
|
|
59
|
+
// 自定义顺序:按 ORDERED_NAMES 排列,找不到的文件跳过并警告
|
|
60
|
+
inputFiles = [];
|
|
61
|
+
for (const name of ORDERED_NAMES) {
|
|
62
|
+
const candidates = ['.png', '.jpg', '.webp'].map(ext => join(CONFIG.processedDir, `${name}${ext}`));
|
|
63
|
+
const found = candidates.find(p => existsSync(p));
|
|
64
|
+
if (found) {
|
|
65
|
+
inputFiles.push(found);
|
|
66
|
+
} else {
|
|
67
|
+
log(`[WARN] Ordered file not found: ${name} (skipping)`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
// 文件名排序
|
|
72
|
+
inputFiles = readdirSync(CONFIG.processedDir)
|
|
73
|
+
.filter(f => ['.png', '.jpg', '.webp'].includes(extname(f).toLowerCase()))
|
|
74
|
+
.sort()
|
|
75
|
+
.map(f => join(CONFIG.processedDir, f));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (inputFiles.length === 0) {
|
|
79
|
+
log('ERROR: No input files found in ' + CONFIG.processedDir);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
log(`=== Build Sprite Sheet Start ===`);
|
|
84
|
+
log(`Frames: ${inputFiles.length} | Columns: ${CONFIG.columns} | Padding: ${CONFIG.padding} | BG: ${CONFIG.background}`);
|
|
85
|
+
|
|
86
|
+
// 构建 --inputs 参数列表
|
|
87
|
+
const inputsArg = inputFiles.map(p => `"${p}"`).join(' ');
|
|
88
|
+
|
|
89
|
+
const cmd =
|
|
90
|
+
`playcraft image sprite-sheet` +
|
|
91
|
+
` --inputs ${inputsArg}` +
|
|
92
|
+
` --output "${CONFIG.outputBase}"` +
|
|
93
|
+
` --columns ${CONFIG.columns}` +
|
|
94
|
+
` --padding ${CONFIG.padding}` +
|
|
95
|
+
(CONFIG.background !== 'transparent' ? ` --background "${CONFIG.background}"` : '');
|
|
96
|
+
|
|
97
|
+
log(`Running: playcraft image sprite-sheet ... --output ${CONFIG.outputBase}`);
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
execSync(cmd, { stdio: 'inherit' });
|
|
101
|
+
} catch (e) {
|
|
102
|
+
log(`ERROR: sprite-sheet command failed: ${e.message}`);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 验证输出
|
|
107
|
+
const pngPath = `${CONFIG.outputBase}.png`;
|
|
108
|
+
const jsonPath = `${CONFIG.outputBase}.json`;
|
|
109
|
+
|
|
110
|
+
if (!existsSync(pngPath) || !existsSync(jsonPath)) {
|
|
111
|
+
log('ERROR: Output files missing! Expected ' + pngPath + ' and ' + jsonPath);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const meta = JSON.parse(readFileSync(jsonPath, 'utf-8'));
|
|
116
|
+
const frameCount = Object.keys(meta.frames ?? {}).length;
|
|
117
|
+
|
|
118
|
+
log(`\n=== Sprite Sheet Built ===`);
|
|
119
|
+
log(` Frames : ${frameCount}`);
|
|
120
|
+
log(` PNG : ${pngPath}`);
|
|
121
|
+
log(` JSON : ${jsonPath}`);
|
|
122
|
+
log(` Columns : ${CONFIG.columns}`);
|
|
123
|
+
log(` Rows : ${Math.ceil(frameCount / CONFIG.columns)}`);
|