跳过正文

深受Codex Pet启发,我捣鼓了一个可以用Codex直出瓦片图(游戏素材)的skill

·5856 字·12 分钟
月半杰瑞
作者
月半杰瑞
软件工程师·独立创作者
目录

之前开发了一个SpriteSheet编辑器,操作下来还是觉得流程太繁琐了:得逐张图和ChatGPT沟通,等出图后还得反复沟通调整,再通过这个编辑器来后期处理,AI时代应该有更聪明的解法。

在看到Codex Pet给我生成的底层SpriteSheet后

codex pet spritesheet

突然有了想法

  • 首先,Codex 能出图
  • 而且,Codex 能出标准规格的图

这不就意味着Codex也能生成游戏素材?

尝试让Codex在最近制作的游戏demo里,参考Hatch-Pet Skill(OpenAI开源),生成需要的角色动画后,更加确信此路可行

目前基于个人理解,先捣鼓了一个专门用来生成瓦片图的Game-Tileset-Generator Skill。

比如想制作《星露谷物语》这样的游戏,就可以用这个skill直出瓦片图,直接导入 Tiled 等游戏开发工具,大幅降低 GPT 出图后手工整理编辑和返工成本

terrain atlas
forage atlas

skill已开源,Github,欢迎体验和反馈,这里也有一个非常简单的介绍

实话说目前还达不到100%完美,GPT生成的瓦片不一定都是自己想要的,但比起花时间找素材或者自己画,已经方便不少了。

下面就来分享下,Hatch-Pet skill给我带来的启发,以及Game-Tileset-Generator skill是怎么做出来的

Hatch-Pet Skill解析
#

Hatch-Pet的目标,是生成适配Codex Pet功能的宠物动画

running preview

底层是一张SpriteSheet图

  • 一共九组动作,除了上面这个 running ,还有 idlerunning-rightrunning-leftwavingjumpingfailedwaitingreview
  • 每个动作的帧序列需要尽可能连贯,角色的面部特征、比例、材质、色调和道具均保持一致
  • 每帧是固定192x208像素大小
  • 干净的透明背景

这么多的动作和要求,想全靠提示词一口气让GPT Image出图几乎不现实,光是调试提示词就非常痛苦,而且目前GPT也无法精确处理尺寸,这也是之前做SpriteSheet编辑器的出发点。

Hatch-Pet Skill也放弃了这种一口气出图的幻想,把整个生图流程拆分成了好几步,逐步推进:

  1. 生成宠物基础形象
  2. 单独生成每组动作的序列帧
  3. 对每组序列帧提取宠物主体再标准化处理每一帧
  4. 所有帧拼成一张大图
  5. QA验证,有问题局部返修

涉及的细节比较多,不过多展开,这里主要想聊一些给我带来启发的点

  • Hatch-Pet是如何标准化处理每一帧的
  • Hatch-Pet是如何编排工作流的

关于标准化处理
#

整个skill最有价值的部分,就是这个标准化处理方法

所谓标准化处理,其实就是在GPT生成的这么一组动作序列图中

waiting source frames

把宠物提取出来,处理成下面这样每个动作帧192x208像素,背景100%透明的图

waiting standardized frames

核心是:

  • 布局引导
  • 透明处理
  • 主体提取

1. 布局引导
#

Hatch-Pet在生成每组动作的时候,除了动作提示词和基础形象图,还提供了一个布局引导图作为参考

waiting layout guide

比起抽象的文字描述,这样的布局引导图更容易让模型理解一组动作有多少帧,布局和排列是怎么样的,可以尽量让每一帧的宠物动作,落在对应的格子内并且尺寸保持一致

2. 透明处理
#

canonical base with chroma key

目前GPT无法直接生成背景透明的图,而这样带背景的动作帧也无法用在Codex Pet里,需要透明处理,实际是通过代码把背景像素处理成RGBA(0,0,0,0)。RGB常用来表示像素的颜色,RGBA中的A,就是透明度Alpha Channel。

透明处理的核心思路,就是视觉特效里常用的“绿幕”,chroma-key,本质上是用一种不会与主体撞色的颜色作为背景色,这里用的是紫色/品红色#FF00FF

为了方便透明处理,提示词里也有所要求:每个像素要么属于宠物,要么是可完全移除的chroma-key,而且宠物的颜色不能与chroma-key接近。

代码处理也不是简单的把#FF00FF都处理掉,只要用取色器检查,就会发现GPT生成的图都会有色差,所以代码还需要计算每个像素RGB 与 chroma-key的颜色距离,处理阈值范围内的像素

canonical base transparent result

3. 角色提取
#

除了像素的RGBA,目前 GPT 也无法精确处理尺寸,比如waiting动作需要6帧,一帧是192x208像素,那标准就是1152x208

但即便给了这个尺寸的布局引导图,生成的图片还是2172 × 724,和目标不符,所以就需要把角色提取出来,每帧再缩放成192x208像素。

这个提取有3种方法:

1)Slots,按宽度等分直接切格子

比如waiting的6帧2172 × 724

slots extraction example
  • 先宽度等分,就是2172 / 6 = 362, 所以每一帧就是362x724
  • 再根据与192x208的比例差异min(192/362,208/724)=0.2873得到缩放比例
  • 进行等比例缩放(宽高362x724x0.2873)得到104x208
  • 居中放置后宽度缺的部分直接用透明像素填充

这种方法在GPT严格参照布局引导图来生成的时候就特别有用,简单又稳定。

但如果GPT生成的动作帧稍微偏一点,动作帧序列在播放的时候就会位移。

2)Components, 非透明主体

这个提取方法基于前面提到的透明处理,如果背景完全透明,剩下连起来的像素就是角色主体,用每一大片像素的上下左右边界形成的包围盒bbox就可以框住主体,然后再等比例缩放到192x208的格子里

components extraction example
专治GPT生图的不规则输出。

但如果之前透明处理后有像素残留,就会有噪点,所以还要增加像素面积的判断,把这些噪点给去掉。

然而如果宠物有特效,比如右边多一个思考的泡泡,那每个包围盒bbox就会因为这个特效变得不一样,因为这种方法是每一个bbox独立缩放的

如果bbox尺寸不一样,等比例缩放到192x208格子后,宠物尺寸也会不一样,播放动画时就会有忽大忽小的跳变。

为了避免这种情况, Hatch-Pet有专门的一节透明度与特效的描述,核心是:不要给宠物角色附加阴影,漂浮物等脱离宠物主体的特效,以及和动作无关的装饰效果

这种方法最适合那种bbox变化不大的动作,比如小幅摆手、呼吸眨眼等。

但有些动作幅度大,bbox尺寸容易出现较大的差异,而且对于跳跃动作,这种底部对齐的方法也体现不出的跳跃效果

3)Stable-Slots,统一视窗

这种方法是对Components方法的优化,既然不同bbox独立缩放会产生大小跳变和抖动,那就用一个统一大小的视窗,用这个窗口提取主体,然后等比例缩放到192x208的格子中。

比如跳跃动作

stable slots extraction example
  • 找出一组动作中bbox 的最高和最低,确定能框住所有动作的高度
  • 比较每一个bbox的宽度,找到最大的宽度
  • 四周增加一些透明像素,就得到了一个统一的窗口

用这种方法提取的主体能尽量保留动作之间相对位置的变化,但因为空白像素的增加,等比例缩放之后宠物大小也可能会比其它动作小

关于工作流编排
#

工作流的编排,实际上就是把标准化处理的流程给串起来,但流程之外,重要的还有

  • 目标
  • 分工
  • 验收

1. 定义具体的spec目标规格
#

有具体明确的spec目标规格,产出才能被衡量和程序化验收。

Hatch-Pet 在一开始,就通过脚本定好了目标规格

  • 最终图的像素规格多大。1536x1872 , 一个单元格192x208 ,总共8x9 个单元格
  • 第几行固定是什么动作,这个动作需要多少帧,宽高多少,安全边界多少。比如第7行是waiting,需要6帧,192x208一格,一行就是1152x208,而且还需要保持18px宽和16px高的安全边界等

2. 明确的Worker分工
#

上下文会影响Agent的判断。

如果让一个Agent做完所有的活,拥有所有的上下文,那后面的执行就有可能被前面的信息干扰

Hatch-Pet是一个多agent的设计,有这些角色和分工

角色 分工
Parent Agent - 宠物形象推断
- 生成目标
- 分配任务给其它Worker
- 任务调度及维护任务进度
- 执行后期脚本处理和修复
Base Worker - 只负责生成基础形象
Row Worker - 一个Row Worker只负责生成一组动作
Visual QA Worker - 评判每个动作的Gif动图以及所有行拼起来的Contact-Sheet检查表是否与目标匹配

每个角色有自己的具体任务和上下文,各司其职

3.验收与修复
#

Hatch-Pet每一个阶段性产物,都会有对应的QA检查

  • 在标准化处理完一组动作后,就会通过代码检查帧的数量、尺寸、边缘是否透明(安全距离)、是否有背景残留、像素面积不在安全范围内等
  • 拼成大图后也会再次检查尺寸和透明度等等

但是代码只能理解像素,无法理解生成的图片是否合理,所以还会生成Gif动图和Contact-Sheet,让大模型进行视觉QA,发现问题就会自行修复,要么重新生成这组动作,要么重新标准化

waiting animation preview
contact sheet qa

不过Hatch-Pet只是尽量保证满足要求,最终还是需要人来判断是否合格(比如上面这个第3组,视觉QA就这么放过了???)。

Game-Tileset-Generator 的制作经验
#

熟悉了Hatch-Pet这套标准化流程,应该也可以结合GPT生图,标准化处理图片素材进入很多工作流了。

比起技术细节,我更想分享点技术之外的经验

skill的迭代历程
#

1. 从宏大到聚焦
#

在看到Hatch-Pet用在游戏demo里的效果后,一开始是想直接做一个通用游戏素材生成skill的,毕竟标准化过程大同小异,用户描述好要什么样的素材,大模型通过这个标准化处理流程来生成。

于是直接让Codex参考Hatch-Pet来实现这个skill,一顿输出,没成功。

1)想一套方法跑所有素材

游戏素材种类太多,有角色动画,有瓦片图,有道具等等,不同素材的目标和要求完全不一样,所以提示词和标准化处理方法都得针对性处理,但Codex写出来的这个通用素材生成skill,就是试图用一个通用套路解决所有场景。

拿瓦片地形素材举个例子,用宠物动画这种,带安全边界的布局引导图和components提取方法,提取出非透明像素主体之后,拼起来就会发现每个地形边缘有很多透明处理后形成的锯齿

应该得用无安全边界的布局引导图和slots等分的思路

layout-guide

2)角色动画的局限性

目前GPT生成的动作序列,脚部动作替换不连贯,这是硬伤。

尝试了很多提示词,甚至学习布局引导图的思路,用GPT生成了一个动作骨架图作为参考,都生成不了满意的动画序列

所以想要的太多,反而每个场景都处理不好,应该得每种素材单独做skill。

而实现一个角色动画生成skill,没有解决硬伤问题的话,对比Hatch-Pet来说没有太多改进,就先聚焦只做瓦片图的生成skill

2. 从入门到“精通”
#

在制作这个skill之前,完全没有图像处理或者游戏开发经验,唯一的经验积累,就是空闲时探索用Codex做游戏,只给游戏想法,不管具体实现的那种。

用Codex写瓦片图生成skill,纯粹就是外行指导内行,唯一的作用就是

  • 给它一个一句话需求:参考Hatch-Pet写一个瓦片图生成skill
  • 发现问题再跟它说: 这个问题你参考一下Hatch-Pet改一改,那个问题你自己想想办法

vibecoding的一大乐趣就在于,需求还没理清楚,demo就已经出来了,而一大痛苦就是,让它自行排查了很多轮都解决不了问题,让人非常抓狂,开始厌蠢。

而且看一眼SKILL.md里的提示词,就会发现字里行间充斥着非常多为了解决特定问题出现的表述,说屎山文档应该不过分。

屎山代码,不去看它,业务逻辑用不到还能忍;而屎山SKILL,完全不知道哪个表述出现在上下文里就对大模型的行为产生了影响

于是就有了前面的Hatch-Pet skill解析,不去深入理解Hatch-Pet的实现,学一点入门的图像处理知识,确实很难写出这个skill。

好在AI时代,学习效率也发生了质的改变,不需要先把相关入门知识先过一遍,制作的过程中碰到问题直接问Codex,直接在创造中学习。

同时为了避免失控,SKILL.md也需要阶段性人工审查内容,先确认内容结构,再逐段让Codex补充

明确需求的引导流程
#

大多数与Agent协作时无奈的返工,都源于需求从一开始就没有被精确定义

Hatch-Pet的需求很明确,就是做能在Codex Pet里面用的SpriteSheet,用户只需要描述下需要什么样的宠物就好了,其他的目标规格,skill里已经定义好了。

但瓦片图不一样,不同游戏类型需要的瓦片规格不一样,有的要32x32有的要64x64,有的要地形,有的要放置的道具,视图也会有俯视或者侧视

专业游戏开发也许能把所有的需求一次性描述清楚,但应该也会遗漏细节

而绝大多数时候,用户的需求描述都是模糊的,对于新手来说,甚至都不知道应该如何表达

没有明确的目标规格,skill很难得到预期内的成果。

所以skill的一开始,就让Agent把用户的需求翻译成skill支持的规格,并给出契合用户需求的建议,让用户确认,比如:

帮我生成星露谷物语游戏的各种地面素材。草地,土地,耕地等。12个

就会得到这样的建议

建议规格如下。

  1. tile size 推荐 64x64 原因:你前两套已经是 64x64,这次继续沿用,后续混用最省事。若要更接近原版密度,32x32 也可以,但细节会少一些。

  2. pixel style 推荐 full 原因:草地、土地、耕地这类地面素材本质是整格铺地,应该铺满 tile。

  3. view 推荐 top-down 原因:和 Stardew 的农场地表阅读方式一致。

  4. object layout size 推荐全部 1x1 原因:12 个单格地表变化,最适合地图编辑和随机混铺。

  5. atlas content 推荐 terrain 我建议这 12 个地面 tile:

  • grass_light:浅色草地
  • grass_dark:深色草地
  • grass_worn:轻微踩踏草地
  • grass_patchy:斑驳草地
  • soil_plain_light:浅色裸土地
  • soil_plain_dark:深色裸土地
  • soil_hoed_dry_a:翻耕干土地 A
  • soil_hoed_dry_b:翻耕干土地 B
  • soil_hoed_watered_a:翻耕湿土地 A
  • soil_hoed_watered_b:翻耕湿土地 B
  • field_transition_soft:草地与土地过渡块
  • field_path_worn:田间踩踏小路地块

这套覆盖草地、土地、耕地和过渡地块,能直接搭基础农场地表。

  1. repeatability 推荐 both 原因:这类 terrain 需要横向和纵向都能无缝平铺。

  2. atlas 排布 推荐 4 columns x 3 rows 原因:正好 12 格。

  3. run 目录 建议: [项目路径]/game-tileset-generator/stardew-ground-mix-64

如果这版可以,直接回复:

按这个生成

如果要改,直接说改哪项,比如: 改成32x32 去掉小路,换成更多草地变化 要更接近原版低饱和配色

用户可以反复沟通,直到确认需求。

只要确认了规格,剩下的就好处理了,直接根据确定的规格就能路由到一套设定好的处理方案。

最后
#

目前我测试这个skill,跑了好几次都比较稳定,就先放出来了,已开源,Github

如果你做游戏时,找了一大圈,都找不到想要的瓦片图素材,也不会自己画,可以试下用这个skill来生成,欢迎体验和反馈