Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
6.8 KiB
name, description
| name | description |
|---|---|
| shmup-player-sprite | 竖版射击游戏主角机三帧精灵(平飞/左滚转/右滚转)生产流水线。Use when 生成或调整玩家机 sprite、shmup aircraft sprite、bank/roll 滚转侧身帧、调试飞机贴图滚转效果、或为 1942 式竖版射击游戏制作新机型的三帧美术。关键词:主角机、玩家飞机、滚转身、bank frames、P-38、雷光、plane_funnel。 |
竖版主角机三帧精灵生产流水线
为本项目(1942 式竖版射击)生产主角机三帧动画精灵:平飞基准帧 + 左/右滚转帧。
核心思路:AI 只负责生成一张严格对称的平飞基准图;滚转帧用高度图浮雕投影确定性推导,避免 AI 生图的不可控性。
工具位置
流水线脚本在本项目 tools/gen_plane_sprites.py(git 跟踪,单一数据源)。机型档案在 tools/profiles/*.json(内置 p38,另有 plane_funnel)。
迁移到其他项目:把 tools/gen_plane_sprites.py 拷过去,参照脚本内 BUILTIN_PROFILES["p38"] 写新机型的 JSON profile 即可。
快速开始
# 密钥:环境变量 APIYI_API_KEY,或 tools/.apikey(已 gitignore,勿提交)
# 1. 生成基准图(唯一需要 AI 的一步)
python tools/gen_plane_sprites.py --profile tools/profiles/<机型>.json base
python tools/gen_plane_sprites.py check assets/raw/<name>-base.png --symmetry # 对称度应 >95%
# 2. 确定性生成左右滚转帧(零 API)
python tools/gen_plane_sprites.py --profile tools/profiles/<机型>.json relief
# 3. 裁边 + 统一缩放 + 居中落地 assets/art/
python tools/gen_plane_sprites.py --profile tools/profiles/<机型>.json process
# 4. 校验三帧后 godot --import
python tools/gen_plane_sprites.py check assets/art/<name>.png
几何模型(理解一切的基础)
滚转侧身帧的正确语义:飞机不动,相机在飞机 Up-Right 平面内从正上方移到右上方 θ 角处(等距、看向机心)。正交投影下:
x' = x·cosθ − h·sinθ y' = y
三个视觉后果,缺一不可:
- 翼展按 cosθ 压缩——整机变窄,纵向(机头到机尾)长度不变
- 有高度的部件向画面左移 h·sinθ(θ=45° 时座舱盖偏移 ≈ 高度的 0.7 倍)
- 朝向相机的侧面露出——机身/发动机舱右缘出现一条暗色侧面带
反面辨析:只压缩(无侧面露出)看起来仍是正俯视;机翼一高一低(2D 斜切)是"相机自己 roll",不是相机移动。
关键步骤与校验标准
1. base — AI 文生图基准帧
Prompt 四个硬约束,少一个都不行:
- 正俯视("Top-down view, seen from directly above")
- 严格左右对称("PERFECTLY LEFT-RIGHT SYMMETRIC")——对称是 relief 高度图正确的前提,也便于镜像出右滚转帧
- 机头正上("nose pointing STRAIGHT UP")
- 透明背景(gpt-image-1 原生支持
background: "transparent")
校验:check --symmetry,对称度 >95%、四角 alpha=0 才放行。不合格重新生成,不要带伤进入下一步。
2. relief — 高度图浮雕投影(推荐,确定性)
零 API,从基准图严格推导:
- 高度图 = 剪影距离变换(chamfer distance transform):管状结构(机身/发动机舱/尾撑)自动获得圆顶高度,薄结构(机翼/尾翼)自动低平——无需手绘高度图
- 逐像素投影
x' = x·cosθ − h·sinθ:陡坡(朝相机的侧面)被行内拉伸,缝隙用加暗色填充 → 新侧面露出;背侧坡压缩覆盖 - 右滚转帧 = 左帧水平镜像,两侧严格对称
调参旋钮(profile 的 relief 节,或 CLI --angle/--height/--side-dark 覆盖):
| 参数 | p38 默认 | 作用 |
|---|---|---|
angle |
45 | 相机偏角。越大翼展越窄、侧面越宽;48px 精灵建议 30-45 |
height |
48 | 机身最大高度(原始图像素)。控制座舱/机脊的横向位移量 |
side_dark |
0.4 | 露出侧面的最大暗度(0-1) |
slope_th |
0.3 | 高度梯度阈值,超过才视为侧面加暗;调低则机翼边缘也带暗面 |
3. process — 裁边缩放落地
统一缩放系数是隐藏的关键约束:以基准图外接框算出 scale = min(W/bw, H/bh),三帧共用。各帧独立缩放会导致同一架飞机跨帧纵向尺寸不一致(视觉上尾翼"离机身更远")。机身纵向长度是滚转不变量,必须跨帧锁定。
备选:bank — AI 图生图滚转帧
如果一定要 AI 重绘滚转帧(追求真实光影细节),prompt 纪律:
- 直接描述飞机姿态("banking LEFT at 20°, left wing lower, right side sliver visible"),绝不描述相机移动("camera moved" 会被画成前视 3/4 插画)
- 显式钉死:机头正上、机身竖直、翼尖同高、整机完整(枚举
bank_parts所有部件)、螺旋桨机加"螺旋桨侧视不翻脸"(profile 的propellers: true,喷气机设 false) - 生成后用
align校正朝向(模板匹配 ±90° 搜索;不行就align --rotate <度数>手动) - 不要用二阶矩主轴法找角度——滚转的机翼会带偏主轴
踩坑记录(血泪教训)
| 坑 | 现象 | 解法 |
|---|---|---|
| 文生图直接说 "bank/roll" | 模型自由发挥:机翼消失、整机画斜 | 基准帧只生成平飞;滚转交给 relief |
| prompt 描述相机移动 | 画成前视 3/4 插画(螺旋桨翻脸) | 描述飞机姿态,不提相机 |
| 垂直剪切(shear)模拟滚转 | 飞机被拉斜,2D 平面感 | 那是相机自旋,几何错误 |
| 只水平压缩(无侧面) | 仍是正俯视,无滚转感 | 必须有高度驱动的侧面露出 |
| 逐帧独立缩放 | 尾翼看似离机身更远 | 统一缩放系数(锚定基准图) |
| 半分辨率高度图直接采样 | 机翼出现 2×2 方块暗纹 | 高度图双线性升回全分辨率再采样 |
| 陡坡均匀压暗 | 机身整体发暗发糊 | 渐变加暗:脊线亮→边缘暗,且仅陡坡 |
产物约定
assets/raw/{name}-base.png AI 原始基准图(保留,勿删——relief 的输入)
assets/raw/{name}-bank-left.png 滚转帧原始图
assets/raw/{name}-bank-right.png
assets/art/{name}.png 最终三帧(48×56 或 profile 指定尺寸)
assets/art/{name}-bank-left.png
assets/art/{name}-bank-right.png
游戏侧接线约定(本项目 scripts/player.gd 已实现):三帧贴图切换 + 迟滞阈值(进入 0.45 / 退出 0.25),缺图回退平飞帧;滚转帧不做代码旋转/缩放变换。
环境依赖
- Python 3.10+,Pillow(仅标准库 + PIL,无 numpy/scipy)
- AI 步骤(仅
base/bank)需要 OpenAI 兼容图像接口(默认 apiyi,gpt-image-1) - 密钥:
APIYI_API_KEY环境变量,或tools/.apikey(必须 gitignore)