@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.
Files changed (121) hide show
  1. package/README.md +66 -3
  2. package/dist/atom-plan/validate-atom-plan.js +298 -0
  3. package/dist/cli-root-help.js +1 -1
  4. package/dist/commands/3d.js +363 -0
  5. package/dist/commands/create.js +337 -0
  6. package/dist/commands/fix-ids.js +17 -3
  7. package/dist/commands/fix-ids.test.js +264 -0
  8. package/dist/commands/image.js +1337 -43
  9. package/dist/commands/login.js +60 -2
  10. package/dist/commands/recommend.js +1 -1
  11. package/dist/commands/remix.js +213 -0
  12. package/dist/commands/skills.js +1379 -0
  13. package/dist/commands/tools-3d.js +473 -0
  14. package/dist/commands/tools-generation.js +454 -0
  15. package/dist/commands/tools-project.js +400 -0
  16. package/dist/commands/tools-research.js +37 -0
  17. package/dist/commands/tools-research.test.js +216 -0
  18. package/dist/commands/tools-utils.js +164 -0
  19. package/dist/commands/tools.js +7 -616
  20. package/dist/config.js +2 -0
  21. package/dist/index.js +20 -2
  22. package/dist/utils/agent-api-client.js +52 -16
  23. package/package.json +9 -3
  24. package/project-template/.claude/agents/designer.md +116 -0
  25. package/project-template/.claude/agents/developer.md +133 -0
  26. package/project-template/.claude/agents/pm.md +164 -0
  27. package/project-template/.claude/agents/refs/README.md +67 -0
  28. package/project-template/.claude/agents/refs/designer-art-style-catalog.md +533 -0
  29. package/project-template/.claude/agents/refs/designer-color-audio-recipes.md +153 -0
  30. package/project-template/.claude/agents/refs/designer-deliverable-spec.md +167 -0
  31. package/project-template/.claude/agents/refs/designer-dimension-axis.md +27 -0
  32. package/project-template/.claude/agents/refs/designer-handoff-v2-checklist.md +68 -0
  33. package/project-template/.claude/agents/refs/designer-master-composite-recipes.md +216 -0
  34. package/project-template/.claude/agents/refs/designer-style-exploration-flow.md +37 -0
  35. package/project-template/.claude/agents/refs/developer-dev-handoff.md +109 -0
  36. package/project-template/.claude/agents/refs/developer-impl-cookbook.md +134 -0
  37. package/project-template/.claude/agents/refs/developer-phase1-flow.md +211 -0
  38. package/project-template/.claude/agents/refs/pm-workflow-detail.md +545 -0
  39. package/project-template/.claude/agents/refs/reviewer-six-dimension-eval.md +286 -0
  40. package/project-template/.claude/agents/refs/ta-3d-flip-recipe.md +85 -0
  41. package/project-template/.claude/agents/refs/ta-atlas-deliverable-standard.md +46 -0
  42. package/project-template/.claude/agents/refs/ta-batch-pipeline-recipes.md +120 -0
  43. package/project-template/.claude/agents/refs/ta-image-generation-detail.md +356 -0
  44. package/project-template/.claude/agents/refs/ta-image-ops-reference.md +495 -0
  45. package/project-template/.claude/agents/refs/ta-pipeline-cookbook.md +699 -0
  46. package/project-template/.claude/agents/refs/ta-tools-reference.md +111 -0
  47. package/project-template/.claude/agents/refs/ta-vfx-preset-catalog.md +365 -0
  48. package/project-template/.claude/agents/reviewer.md +103 -0
  49. package/project-template/.claude/agents/technical-artist.md +111 -0
  50. package/project-template/.claude/hooks/README.md +36 -0
  51. package/project-template/.claude/hooks/validate-atom-plan.mjs +224 -0
  52. package/project-template/.claude/hooks/validate-workflow-stop.mjs +258 -0
  53. package/project-template/.claude/settings.json +32 -0
  54. package/project-template/.claude/settings.local.json +4 -0
  55. package/project-template/.claude/skills/playcraft-ad-psychology/SKILL.md +182 -0
  56. package/project-template/.claude/skills/playcraft-art-style-guide/SKILL.md +123 -0
  57. package/project-template/.claude/skills/playcraft-asset-state-sheet/SKILL.md +141 -0
  58. package/project-template/.claude/skills/playcraft-audio-generation/SKILL.md +280 -0
  59. package/project-template/.claude/skills/playcraft-batch-pipeline/SKILL.md +184 -0
  60. package/project-template/.claude/skills/playcraft-build-optimizer/SKILL.md +306 -0
  61. package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +229 -0
  62. package/project-template/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +123 -0
  63. package/project-template/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +254 -0
  64. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +235 -0
  65. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +97 -0
  66. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +118 -0
  67. package/project-template/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +137 -0
  68. package/project-template/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +397 -0
  69. package/project-template/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +296 -0
  70. package/project-template/.claude/skills/playcraft-image-ops/SKILL.md +122 -0
  71. package/project-template/.claude/skills/playcraft-masking/SKILL.md +373 -0
  72. package/project-template/.claude/skills/playcraft-research/SKILL.md +212 -0
  73. package/project-template/.claude/skills/playcraft-sprite-generation/SKILL.md +423 -0
  74. package/project-template/.claude/skills/playcraft-storyboard/SKILL.md +148 -0
  75. package/project-template/.claude/skills/playcraft-style-qa/SKILL.md +270 -0
  76. package/project-template/.claude/skills/playcraft-text-rendering/SKILL.md +236 -0
  77. package/project-template/.claude/skills/playcraft-vfx-animation/SKILL.md +130 -0
  78. package/project-template/.claude/skills/playcraft-workflow/SKILL.md +396 -0
  79. package/project-template/.cursor/hooks.json +17 -0
  80. package/project-template/.cursor/rules/playcraft-orchestrator.mdc +87 -0
  81. package/project-template/.cursor/rules/playcraft-subagent-boundary.mdc +18 -0
  82. package/project-template/CLAUDE.md +240 -0
  83. package/project-template/assets/audio/bgm/.gitkeep +0 -0
  84. package/project-template/assets/audio/sfx/.gitkeep +0 -0
  85. package/project-template/assets/bundles/.gitkeep +0 -0
  86. package/project-template/assets/images/bg/.gitkeep +0 -0
  87. package/project-template/assets/images/reference/.gitkeep +0 -0
  88. package/project-template/assets/images/storyboard/.gitkeep +0 -0
  89. package/project-template/assets/images/tiles/.gitkeep +0 -0
  90. package/project-template/assets/images/ui/.gitkeep +0 -0
  91. package/project-template/assets/images/vfx/.gitkeep +0 -0
  92. package/project-template/assets/models/.gitkeep +0 -0
  93. package/project-template/docs/team/agent-conduct.md +105 -0
  94. package/project-template/docs/team/agent-runtime-matrix.md +62 -0
  95. package/project-template/docs/team/atom-plan-format.md +74 -0
  96. package/project-template/docs/team/collaboration.md +288 -0
  97. package/project-template/docs/team/core-model.md +50 -0
  98. package/project-template/docs/team/platform-capabilities.md +15 -0
  99. package/project-template/docs/team/workflow-changelog.md +51 -0
  100. package/project-template/docs/team/workflow-consistency-checklist.md +128 -0
  101. package/project-template/game/config/.gitkeep +0 -0
  102. package/project-template/game/gameplay/.gitkeep +0 -0
  103. package/project-template/game/scenes/.gitkeep +0 -0
  104. package/project-template/logs/.gitkeep +0 -0
  105. package/project-template/ta-workspace/logs/.gitkeep +0 -0
  106. package/project-template/ta-workspace/scripts/.gitkeep +0 -0
  107. package/project-template/ta-workspace/tmp/.gitkeep +0 -0
  108. package/project-template/templates/atom-plan.template.json +26 -0
  109. package/project-template/templates/atom-plan.template.md +76 -0
  110. package/project-template/templates/design-brief.template.md +195 -0
  111. package/project-template/templates/design-lens-checklist.reference.md +117 -0
  112. package/project-template/templates/design-methodology.md +99 -0
  113. package/project-template/templates/designer-log.template.md +98 -0
  114. package/project-template/templates/developer-log.template.md +140 -0
  115. package/project-template/templates/five-axis-framework.md +186 -0
  116. package/project-template/templates/intent-clarifications.template.md +58 -0
  117. package/project-template/templates/layout-spec.template.md +132 -0
  118. package/project-template/templates/project-state.template.md +219 -0
  119. package/project-template/templates/review-report.template.md +166 -0
  120. package/project-template/templates/style-exploration.template.md +93 -0
  121. package/project-template/templates/ta-log.template.md +205 -0
@@ -0,0 +1,296 @@
1
+ /**
2
+ * validate-sprite-sheet.template.mjs
3
+ *
4
+ * 精灵图技术正确性验证脚本。
5
+ * TA 在 Compliance Gate 前运行,确认精灵图尺寸、帧数、通道数均符合要求。
6
+ *
7
+ * 使用方法:
8
+ * cp .claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs \
9
+ * ta-workspace/scripts/validate-sprite-sheet.mjs
10
+ * # 修改下方 SHEETS 数组后运行:
11
+ * node ta-workspace/scripts/validate-sprite-sheet.mjs
12
+ *
13
+ * 输出示例:
14
+ * [VALIDATE] tile_bounce_anim.png
15
+ * 尺寸验算: 512×256 = 4cols × 128px × 2rows × 128px ✅
16
+ * 通道数: 4 (RGBA) ✅
17
+ * 帧数: 8 帧(JSON 验证: N/A — animate 命令无 JSON)
18
+ * 帧内容抽查 (帧 0, 4, 7): 全部非空 ✅
19
+ * [VALIDATE] explosion_small.png
20
+ * 尺寸验算: 预设 4cols × 8frames → 期望 W=cols×frameW ✅
21
+ * 通道数: 4 (RGBA) ✅
22
+ *
23
+ * 注意:脚本使用 `playcraft image info --json` 获取图片信息。
24
+ * JSON 验证仅适用于 `sprite-sheet` 命令输出(有配套 .json 文件)。
25
+ */
26
+
27
+ import { execSync } from 'child_process';
28
+ import { existsSync, readFileSync, appendFileSync, mkdirSync } from 'fs';
29
+ import path from 'path';
30
+
31
+ // ─── CONFIG ───────────────────────────────────────────────────────────────────
32
+
33
+ /**
34
+ * 每个条目描述一张精灵图的期望参数。
35
+ * source: 'sprite-sheet' | 'animate' | 'use-vfx'
36
+ * - sprite-sheet: 有配套 JSON,可做完整验证
37
+ * - animate: 无 JSON,从 stdout 记录的参数验证
38
+ * - use-vfx: 无 JSON,从 list-vfx --json 记录的参数验证
39
+ */
40
+ const SHEETS = [
41
+ {
42
+ file: 'assets/images/tiles/tile_bounce_anim.png',
43
+ source: 'animate', // 'sprite-sheet' | 'animate' | 'use-vfx'
44
+ columns: 4,
45
+ frameWidth: 128,
46
+ frameHeight: 128,
47
+ frameCount: 8,
48
+ padding: 0,
49
+ jsonFile: null, // animate 无 JSON,填 null
50
+ },
51
+ {
52
+ file: 'assets/images/vfx/explosion.png',
53
+ source: 'use-vfx',
54
+ columns: 4,
55
+ frameWidth: 128, // use-vfx 预设宽高需用 playcraft image info 确认
56
+ frameHeight: 128,
57
+ frameCount: 8,
58
+ padding: 0,
59
+ jsonFile: null,
60
+ },
61
+ // sprite-sheet 示例(有 JSON):
62
+ // {
63
+ // file: 'assets/images/tiles/tile_atlas.png',
64
+ // source: 'sprite-sheet',
65
+ // columns: 6,
66
+ // frameWidth: 128,
67
+ // frameHeight: 128,
68
+ // frameCount: 34,
69
+ // padding: 2,
70
+ // jsonFile: 'assets/images/tiles/tile_atlas.json',
71
+ // },
72
+ ];
73
+
74
+ const LOG_FILE = 'ta-workspace/logs/sprite-validate.log';
75
+
76
+ // ─── HELPERS ──────────────────────────────────────────────────────────────────
77
+
78
+ function imageInfo(filePath) {
79
+ try {
80
+ const raw = execSync(
81
+ `playcraft image info --input "${filePath}" --json`,
82
+ { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },
83
+ );
84
+ return JSON.parse(raw);
85
+ } catch {
86
+ return null;
87
+ }
88
+ }
89
+
90
+ function pass(msg) { return `✅ ${msg}`; }
91
+ function fail(msg) { return `❌ ${msg}`; }
92
+
93
+ // ─── VALIDATION ───────────────────────────────────────────────────────────────
94
+
95
+ async function validateSheet(sheet) {
96
+ const lines = [`\n[VALIDATE] ${sheet.file} (source: ${sheet.source})`];
97
+ let allPassed = true;
98
+
99
+ if (!existsSync(sheet.file)) {
100
+ lines.push(` ${fail('文件不存在 — 请先完成资产生产')}`);
101
+ return { passed: false, lines };
102
+ }
103
+
104
+ // ── 1. 获取实际图片信息 ────────────────────────────────────────────────
105
+ const info = imageInfo(sheet.file);
106
+ if (!info) {
107
+ lines.push(` ${fail('无法读取图片信息(playcraft image info 失败)')}`);
108
+ return { passed: false, lines };
109
+ }
110
+
111
+ const actualW = info.width;
112
+ const actualH = info.height;
113
+ const actualChannels = info.channels ?? 4;
114
+
115
+ // ── 2. 尺寸数学验算 ────────────────────────────────────────────────────
116
+ const rows = Math.ceil(sheet.frameCount / sheet.columns);
117
+ const expectedW = sheet.columns * sheet.frameWidth + (sheet.columns - 1) * sheet.padding;
118
+ const expectedH = rows * sheet.frameHeight + (rows - 1) * sheet.padding;
119
+
120
+ const dimOk = actualW === expectedW && actualH === expectedH;
121
+ if (dimOk) {
122
+ lines.push(
123
+ ` ${pass(`尺寸验算: ${actualW}×${actualH} = ${sheet.columns}cols×${sheet.frameWidth}px + ${rows}rows×${sheet.frameHeight}px (padding=${sheet.padding}px)`)}`
124
+ );
125
+ } else {
126
+ allPassed = false;
127
+ lines.push(
128
+ ` ${fail(`尺寸不匹配: 实际 ${actualW}×${actualH},期望 ${expectedW}×${expectedH}`)}`
129
+ );
130
+ lines.push(` → 检查 columns/frameWidth/frameHeight/padding 参数是否与生成命令一致`);
131
+ lines.push(` → animate 命令 padding 固定为 0;sprite-sheet 命令默认 padding 为 0`);
132
+ }
133
+
134
+ // ── 3. 通道数验证 ──────────────────────────────────────────────────────
135
+ if (actualChannels === 4) {
136
+ lines.push(` ${pass(`通道数: 4 (RGBA,支持透明背景)`)}`);
137
+ } else {
138
+ allPassed = false;
139
+ lines.push(
140
+ ` ${fail(`通道数: ${actualChannels}(不是 4/RGBA)— 透明区域将渲染为黑色`)}`
141
+ );
142
+ lines.push(` → 如果原图有透明背景,确认去背景步骤正确(remove-background 或生成时使用绿幕策略)`);
143
+ }
144
+
145
+ // ── 4. JSON 验证(仅 sprite-sheet 命令)────────────────────────────────
146
+ if (sheet.source === 'sprite-sheet') {
147
+ const jsonPath = sheet.jsonFile || sheet.file.replace(/\.png$/i, '.json');
148
+ if (!existsSync(jsonPath)) {
149
+ allPassed = false;
150
+ lines.push(` ${fail(`JSON 文件不存在: ${jsonPath}`)}`);
151
+ lines.push(` → sprite-sheet 命令应自动生成 .json,确认命令执行成功`);
152
+ } else {
153
+ try {
154
+ const json = JSON.parse(readFileSync(jsonPath, 'utf-8'));
155
+ const frameKeys = Object.keys(json.frames ?? {});
156
+ const jsonFrameCount = frameKeys.length;
157
+
158
+ if (jsonFrameCount === sheet.frameCount) {
159
+ lines.push(` ${pass(`JSON 帧数: ${jsonFrameCount} 帧`)}`);
160
+ } else {
161
+ allPassed = false;
162
+ lines.push(
163
+ ` ${fail(`JSON 帧数不匹配: JSON 中 ${jsonFrameCount} 帧,期望 ${sheet.frameCount} 帧`)}`
164
+ );
165
+ }
166
+
167
+ // 验证 meta.size
168
+ const metaW = json.meta?.size?.w;
169
+ const metaH = json.meta?.size?.h;
170
+ if (metaW === actualW && metaH === actualH) {
171
+ lines.push(` ${pass(`JSON meta.size: ${metaW}×${metaH} 与实际图片一致`)}`);
172
+ } else {
173
+ allPassed = false;
174
+ lines.push(
175
+ ` ${fail(`JSON meta.size 不匹配: JSON 中 ${metaW}×${metaH},实际 ${actualW}×${actualH}`)}`
176
+ );
177
+ }
178
+
179
+ // 帧名字典序警告(数字后缀需补零)
180
+ const hasUnpaddedNumbers = frameKeys.some(k => /[^0]_\d\.png$/.test(k));
181
+ if (hasUnpaddedNumbers) {
182
+ lines.push(
183
+ ` ⚠️ 帧名警告: 检测到未补零的数字后缀(如 _1.png vs _10.png)`
184
+ );
185
+ lines.push(
186
+ ` → 字典序下 f_10.png 排在 f_2.png 之前,导致动画帧乱序`
187
+ );
188
+ lines.push(` → 输入帧文件名应补零对齐(f_01.png, f_02.png...)`);
189
+ }
190
+ } catch {
191
+ allPassed = false;
192
+ lines.push(` ${fail(`JSON 文件解析失败: ${jsonPath}`)}`);
193
+ }
194
+ }
195
+ } else {
196
+ lines.push(
197
+ ` ℹ️ JSON 验证: 跳过(${sheet.source} 命令不输出 JSON)— 网格参数已记录在 ta-log.md`
198
+ );
199
+ }
200
+
201
+ // ── 5. 帧内容抽查(随机 3 帧,验证非透明像素 > 1%)─────────────────────
202
+ if (dimOk && sheet.frameWidth > 0 && sheet.frameHeight > 0) {
203
+ const sampleFrameIndices = [
204
+ 0,
205
+ Math.floor(sheet.frameCount / 2),
206
+ sheet.frameCount - 1,
207
+ ].filter((v, i, a) => a.indexOf(v) === i);
208
+
209
+ const emptyFrames = [];
210
+ for (const frameIdx of sampleFrameIndices) {
211
+ const col = frameIdx % sheet.columns;
212
+ const row = Math.floor(frameIdx / sheet.columns);
213
+ const x = col * (sheet.frameWidth + sheet.padding);
214
+ const y = row * (sheet.frameHeight + sheet.padding);
215
+
216
+ try {
217
+ // 裁剪单帧并检查非透明像素比例
218
+ const cropResult = execSync(
219
+ `playcraft image crop \
220
+ --input "${sheet.file}" \
221
+ --output ta-workspace/tmp/_frame_check_${frameIdx}.png \
222
+ --x ${x} --y ${y} \
223
+ --width ${sheet.frameWidth} --height ${sheet.frameHeight}`,
224
+ { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },
225
+ );
226
+
227
+ const frameInfo = imageInfo(`ta-workspace/tmp/_frame_check_${frameIdx}.png`);
228
+ // playcraft image info 返回的 dominantColors 可以间接判断非空
229
+ // 简单启发式:如果 dominant colors 存在且有非透明颜色,认为帧非空
230
+ const nonEmpty = frameInfo && (frameInfo.dominantColors?.length > 0 || frameInfo.hasAlpha === false);
231
+ if (!nonEmpty) emptyFrames.push(frameIdx);
232
+ } catch {
233
+ // 裁剪失败跳过
234
+ }
235
+ }
236
+
237
+ if (emptyFrames.length === 0) {
238
+ lines.push(
239
+ ` ${pass(`帧内容抽查 (帧 ${sampleFrameIndices.join(', ')}): 全部非空`)}`
240
+ );
241
+ } else {
242
+ allPassed = false;
243
+ lines.push(
244
+ ` ${fail(`帧内容抽查: 帧 ${emptyFrames.join(', ')} 疑似全透明/空帧`)}`
245
+ );
246
+ lines.push(` → 检查对应帧位置坐标是否正确,或去背景是否过激(tolerance 过高)`);
247
+ }
248
+
249
+ // 清理临时文件
250
+ try {
251
+ execSync(`rm -f ta-workspace/tmp/_frame_check_*.png`, { stdio: 'ignore' });
252
+ } catch { /* ignore */ }
253
+ }
254
+
255
+ return { passed: allPassed, lines };
256
+ }
257
+
258
+ // ─── MAIN ─────────────────────────────────────────────────────────────────────
259
+
260
+ async function main() {
261
+ mkdirSync('ta-workspace/logs', { recursive: true });
262
+ mkdirSync('ta-workspace/tmp', { recursive: true });
263
+
264
+ console.log('\n🔍 精灵图技术验证');
265
+ console.log(` 检查 ${SHEETS.length} 张精灵图\n`);
266
+
267
+ let passCount = 0;
268
+ let failCount = 0;
269
+ const allLines = [];
270
+
271
+ for (const sheet of SHEETS) {
272
+ const { passed, lines } = await validateSheet(sheet);
273
+ lines.forEach(l => console.log(l));
274
+ allLines.push(...lines);
275
+ if (passed) passCount++;
276
+ else failCount++;
277
+ }
278
+
279
+ const summary = [
280
+ `\n=== 验证汇总 ===`,
281
+ ` 总计: ${SHEETS.length} 张 通过: ${passCount} 失败: ${failCount}`,
282
+ failCount > 0
283
+ ? ` ❌ 存在问题的精灵图需在 Compliance Gate 前修复`
284
+ : ` ✅ 全部通过,可继续 Compliance Gate`,
285
+ '',
286
+ ].join('\n');
287
+
288
+ console.log(summary);
289
+
290
+ const timestamp = new Date().toISOString();
291
+ appendFileSync(LOG_FILE, `\n[${timestamp}]\n${allLines.join('\n')}\n${summary}`);
292
+
293
+ if (failCount > 0) process.exit(1);
294
+ }
295
+
296
+ main().catch(e => { console.error(e); process.exit(1); });
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: playcraft-image-ops
3
+ description: TA 图形操作生产上下文指南。按可玩广告流水线阶段(提取/标准化/变换/合成/验证)组织 playcraft image 子命令,说明 WHEN 和 WHY 而非仅 HOW。完整 CLI 参数速查表见 refs/ta-image-ops-reference.md。
4
+ triggers: 裁剪,crop,叠图,合成,overlay,扩画布,pad,去白边,trim,旋转,rotate,翻转,flip,模糊,blur,色调,tint,灰度,grayscale,反色,negate,居中裁,等比裁,图层叠加,画布,像素级操作,图形处理,decompose-layers,图层分层,提取,extract
5
+ ---
6
+
7
+ # PlayCraft 图形操作 — 生产上下文指南
8
+
9
+ ## 0. 在流水线中的位置
10
+
11
+ 所有命令均为 `playcraft image <子命令>` 格式,基于 sharp 本地处理,无需后端。
12
+
13
+ ```
14
+ TA Production Pipeline:
15
+ Extract (从 Composite/ASR 提取)
16
+ -> decompose-layers (302 整图语义分层,Master Composite;见 playcraft-masking skill)
17
+ -> crop (ASR 网格 / 已知 bbox 的像素级裁切)
18
+ -> segment (SAM3 单对象蒙版,见 playcraft-masking skill)
19
+
20
+ Process (标准化处理)
21
+ -> trim (去除多余透明边)
22
+ -> resize (统一到 assetSpec 尺寸)
23
+ -> pad (补齐到等宽画布)
24
+ -> remove-background -> 见 playcraft-masking skill
25
+
26
+ Transform (变体生成)
27
+ -> flip horizontal (左右镜像,节省生成成本)
28
+ -> rotate (方向调整)
29
+ -> tint (色调变体 / 禁用状态)
30
+ -> grayscale (锁定 / 未解锁状态)
31
+
32
+ Compose (合成叠加)
33
+ -> overlay (多层合成:背景 + 角色 + UI)
34
+
35
+ Verify (验证)
36
+ -> info (检查尺寸 / 格式 / 文件大小)
37
+ -> convert (最终格式转换 -- 生产阶段保持 PNG)
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 1. 按阶段命令速查
43
+
44
+ | Stage | Command | One-liner | Key Param |
45
+ | --------- | ------------------ | --------------------------------------------------------------------------------- | ---------------------------------- |
46
+ | Extract | `decompose-layers` | `playcraft image decompose-layers --input X --output-dir ./layers --num-layers 4` | 后端 302;`--input` 宜为 HTTPS URL |
47
+ | Extract | `crop` | `playcraft image crop --input X --output Y --x N --y N --width W --height H` | x,y = 左上角原点 |
48
+ | Process | `trim` | `playcraft image trim --input X --output Y --threshold 10` | threshold: 0-255 |
49
+ | Process | `resize` | `playcraft image resize --input X --output Y --width W --height H` | 或 `--scale 0.5` |
50
+ | Process | `pad` | `playcraft image pad --input X --output Y --all 16` | 或 --top/bottom/left/right |
51
+ | Transform | `flip` | `playcraft image flip --input X --output Y --direction horizontal` | horizontal / vertical |
52
+ | Transform | `rotate` | `playcraft image rotate --input X --output Y --angle 90` | 角度(顺时针),背景默认透明 |
53
+ | Transform | `tint` | `playcraft image tint --input X --output Y --color "#FFD700"` | hex 颜色值 |
54
+ | Transform | `grayscale` | `playcraft image grayscale --input X --output Y` | 无额外参数 |
55
+ | Compose | `overlay` | `playcraft image overlay --base BG --overlay FG --output Y --gravity center` | 或 --x --y 精确坐标 |
56
+ | Verify | `info` | `playcraft image info --input X` | --json 供脚本解析 |
57
+ | Verify | `convert` | `playcraft image convert --input X --output Y --format webp --quality 85` | 生产阶段保持 PNG |
58
+
59
+ **overlay gravity 值**:center(默认) / north / south / east / west / northeast / northwest / southeast / southwest。
60
+ 指定 --x + --y 时 gravity 被忽略,叠加图左上角放置在底图 (x, y) 坐标处。
61
+
62
+ ---
63
+
64
+ ## 2. 最常用配方
65
+
66
+ ### 配方 A:标准化精灵尺寸 (trim -> info -> pad)
67
+
68
+ **场景**:AI 生成或分割提取的素材尺寸不一,需要统一到 assetSpec 指定的画布大小。
69
+
70
+ ```bash
71
+ playcraft image trim --input raw_sprite.png --output /tmp/trimmed.png
72
+ playcraft image info --input /tmp/trimmed.png --json
73
+ # 根据 info 输出计算 pad 值:top/bottom = (目标高 - 当前高) / 2,left/right 同理
74
+ playcraft image pad --input /tmp/trimmed.png --output assets/images/tiles/sprite_128x128.png \
75
+ --top 8 --bottom 8 --left 16 --right 16
76
+ ```
77
+
78
+ **为什么这个顺序**:先 trim 去掉 AI 生成图的冗余透明边,再 pad 到精确尺寸。反过来做会把冗余透明边也算进画布。
79
+
80
+ ### 配方 B:多层合成 (overlay chain: bg -> character -> UI)
81
+
82
+ **场景**:将背景、角色、UI 元素按层合成为最终画面。Layout Spec 中的 composite 通常需要这个流程。
83
+
84
+ ```bash
85
+ playcraft image overlay --base assets/images/bg/background.png \
86
+ --overlay assets/images/character.png --output /tmp/step1.png --gravity center
87
+ playcraft image overlay --base /tmp/step1.png \
88
+ --overlay assets/images/ui/cta_button.png --output assets/images/final.png --gravity south
89
+ ```
90
+
91
+ **为什么逐层叠加**:overlay 每次只接受一个叠加层。从最底层开始,每一步的输出作为下一步的 base,保证 z-order 正确。
92
+
93
+ ### 配方 C:镜像动画帧 (flip horizontal)
94
+
95
+ **场景**:已有 run_right 动画序列帧,需要 run_left。翻转比重新生成节省时间和 API 调用。
96
+
97
+ ```bash
98
+ for f in assets/images/character/run_right_*.png; do
99
+ name=$(basename "$f" .png)
100
+ playcraft image flip --input "$f" \
101
+ --output "assets/images/character/${name/right/left}.png" \
102
+ --direction horizontal
103
+ done
104
+ ```
105
+
106
+ **为什么用 flip 而不重新生成**:AI 生成的镜像帧可能出现风格不一致,而 flip 保证像素级对称,且零 API 成本。
107
+
108
+ ---
109
+
110
+ ## 3. 关键注意事项
111
+
112
+ - **crop 不支持 batch**:`playcraft image batch --steps` 中 crop 会报 `unsupported command`。批量裁切用 for 循环或 Node.js 脚本。
113
+ - **生产阶段保持 PNG**:所有中间产物和最终资产用 PNG。WebP/AVIF 转换交给构建阶段 `playcraft build --convert-webp`。
114
+ - **tint 是混合不是替换**:深色图像 tint 效果弱,需要颜色替换时用 overlay + 纯色图层。
115
+ - **居中裁公式**:`x = (原图宽 - 目标宽) / 2`,`y = (原图高 - 目标高) / 2`(取整)。
116
+
117
+ ---
118
+
119
+ ## 4. 完整参考
120
+
121
+ 完整 CLI 参数速查表、所有 gravity 值、rotation 选项、滤镜命令(blur / negate)及更多组合配方:
122
+ 读取 `refs/ta-image-ops-reference.md`。