Vibe Coding 游戏开发教程 · 下篇 |《深夜画廊》:一句题材词,做出有声有色的视觉小说
立项输入只有一句话:"换成悬疑访谈吧"。文生图定人、图生图定情绪、BiRefNet 抠图、TTS 一人一音色(基频 291/202/158 Hz 仪器验证)、Lyria 2 氛围乐——五种生成能力各有引擎契约承接。附立绘管线四阶段图与 WASM 实机成品截图。
两款游戏,两篇教程。这是下篇。上篇《小马拼图:一张截图、一段视频,复刻一款解谜手游》的输入是截图和视频;这一篇更极端——立项输入只有一句话:
换成悬疑访谈吧。
设定、人物、剧情、素材规格,全部由 agent 统筹展开。我后续的参与方式仍然只有两种:一句话要求(如”一个人物固定一个音色”)和一张截图指出问题(如”三个人都是有背景的”)。照旧,没有写过复杂提示词。
先看成品——两张都是 WASM 版在浏览器里跑着的实机截图:
选人界面:三位证人并排立在夜画廊里,透明立绘干净地叠在光影背景上。
审讯苏晴:打字机字幕正在逐字打出,她身后墙上挂着的正是《凝视者》——那幅”盯着你”的画。
第 1 步 · 一句话,agent 统筹出一个游戏
“换成悬疑访谈吧”六个字,agent 自己统筹出的东西:
| 我说的 | agent 自己分解出的活 |
|---|---|
| “悬疑访谈” | 剧情设定:名画《凝视者》深夜失窃,审讯三位证人,选问法、观表情、指认真凶 |
| (没说) | 三个角色的人设:林薇(网球教练)/ 苏晴(会计)/ 陈墨(美术史讲师)——职业、性格、各自的隐情 |
| (没说) | 素材规格清单:3 人 × 3 表情立绘 + 干净/惊悚两版场景 + 3 条开场语音 + 1 首氛围循环乐 |
| (没说) | 分支对话树引擎:打字机字幕、选项、按剧情切换表情、指认结局 |
| (没说) | 踩了 Lua 保留字 goto 的坑(分支跳转字段),自己改名 dest 绕开 |
一个 Lua 文件装下全部。一句话是意图,清单是 agent 的。
第 2 步 · 立绘管线:同一张脸,四个阶段
视觉小说最难的是角色一致性——同一张脸要有平静/紧张/惊惧三种状态,还得是透明底。这条管线全程 Floniks(经 MCP,agent 直接调):
林薇的四个阶段,全部真实素材:① 文生图底图(注意带烘焙背景——这就是后来被截图报障的问题);② BiRefNet 去背景得到透明立绘;③④ 以底图为源图生图,只动表情不动脸。棋盘格 = 真透明通道。
- 底图定人:每位证人一张文生图,定脸、定服装、定气质;
- 图生图定情绪:紧张/惊惧从底图派生——同一张脸,只动表情;
- 场景同理:干净画廊底图 → 图生图惊悚变体(墙上多一幅盯着你的画,见上面审讯截图)。
第 3 步 · 语音:一人一音色,修到有仪器证据为止
我的要求一句话:
创建 TTS 的时候需要根据人物性别来生成不同性别的声音,要用不同的音色,一个人物固定一个音色。
第一版”修好了”——听感上却总觉得像一个人。我追问一句”人物的声音性别问题解决了吗”,agent 做了声学分析:三人基频 128 / 122 / 131 Hz,几乎同一个声源——根本没修好。
根因挖出来:voice 参数写错了字段,平台处理器实际读的是 config.voiceId(camelCase、数组形式)。修正字段 + 原生 pitch 后再次测量:291 / 202 / 158 Hz,少女/播报/御姐三个真实音色。
这一步的教训值得写进任何 AI 工作流:“修好了”必须有可测量的证据,听感不算。
第 4 步 · 截图报障:一张图,三个根因
上线后我发了一张截图:
声音有了,但是没有抠图。三个人都是有背景的,一个都没抠图。
agent 的处理链:
- 9 张立绘全部过 Floniks removeBackground(BiRefNet)抠成透明底(管线图的第 ② 步,当时是补课);
- 顺手修掉网页版无声:浏览器把 AudioContext 初始为 suspended,首次点击时 resume;
- 抠图后画面还是旧的——浏览器缓存在作祟,贴图整体改名破缓存。
第 5 步 · 一句现象描述,换来一次引擎重构
整个游戏的音轨管理有点混乱,出现多重音轨交叉或同时播放的问题,需要系统性的解决这一问题。
注意我说的是现象和”系统性”三个字,没有指定方案。agent 把整个引擎的音频重构成三条声道:SFX 可叠但帧内去重、Music 同名不重启、Voice 播新台词先掐旧的——对话永不重叠。补丁能修一次,模型能修一类,这次重构惠及全部 12 个游戏。
为什么这么丝滑:两个平台咬合成一条流水线
《深夜画廊》把 rust_bevy_lua_game(引擎平台)× Floniks(素材平台) 的协同用到了最满——五种生成能力,每一种的落点都是引擎早已定好的契约:
| 能力 | Floniks 侧(生成即工具,MCP) | rust_bevy_lua_game 侧(数据即约定) |
|---|---|---|
| 立绘 | 文生图底图 + 图生图表情 | 贴图同名同尺寸落位,一行 API 切表情 |
| 抠图 | removeBackground(BiRefNet) | 透明 PNG 直接叠加,无需引擎改动 |
| 语音 | minimax TTS,voice_id 固定进角色表 | Voice 声道:先掐后播,对话永不重叠 |
| 氛围乐 | 文生音乐(Lyria 2) | Music 声道:同名不重启,场景重入不炸音 |
| 剧情 | —(agent 直接写分支树,LLM 即编辑器) | Lua 热重载秒级验证;分支跳转纯数据可 diff |
和上篇同一个结论,这里更明显:不是 agent 快,是路上没有关卡。 每个生成产物落进约定路径就能被引擎吃掉,agent 在一个会话里跑完”写剧本 → 生成立绘 → 抠图 → 配音 → 配乐 → 测试 → 上线”整条链,零人工搬运。
完全跨平台:原生与 WASM,同一份代码
《深夜画廊》是 12 个游戏里对跨平台要求最苛的——它有立绘、语音、音乐、分支剧情,而这一切在三种形态下同一份 gallery.lua,字节级相同:
- 原生 macOS / iOS:mlua(C Lua)驱动,iOS 上 120Hz ProMotion;
- Web / WASM:ottavino(纯 Rust Lua VM)驱动,暴露一模一样的
gameAPI;连”浏览器音频要首次点击解锁”这种平台差异,也被引擎层吸收,脚本毫无感知。
本文开头两张成品图,就是 headless 浏览器打开 WASM 版实机截的——立绘、光影、打字机字幕都在浏览器里原样跑。一条链接点开即玩:https://maweis.com/rust_bevy_lua_game/;同一场审讯,iPhone 上又是原生帧率。
方法论小结
- 一句题材词就能立项,人设/剧情/素材规格的统筹是 agent 的活。
- 角色一致性 = 底图 + 图生图,表情/场景变体都从底图派生(见管线图)。
- 修复要有仪器证据:基频分析证伪了”听起来修好了”。
- 截图报障,根因归 agent:一张图挖出抠图、缓存、无声三个根因。
- 描述现象,不指定方案:”系统性解决”四个字换来一次正确的引擎重构。
- 双平台咬合 + 全跨平台:五种生成能力各有引擎契约承接;一份脚本,原生与浏览器同跑。
开源脚手架:rust_bevy_lua_game(仓库内
docs/blog/有开发博客与会话存档);素材平台 Floniks(MCP 端点api.floniks.com/api/v1/mcp);编排 Claude Code。上篇:《小马拼图:一张截图、一段视频,复刻一款解谜手游》。