一款完全由 Agnes AI免费支持生成的克苏鲁卡牌 Roguelike。 从第一行代码到能直接分发给玩家玩,24 小时。 这篇文章讲讲它怎么来的——以及它能跑。
上个月重读了《印斯茅斯的阴影》。洛夫克拉夫特那种潮湿地黏附在皮肤上的恐惧一直让人着迷。某天我盯着一个卡牌 Roguelike(《杀戮尖塔》那种)想:如果每个事件都像克苏鲁短篇那样开场,而不是"获得 5 金币",是不是更带感?
然后我意识到自己不会画画。
但我有 API。
于是我让AI全自动生成游戏及所需剧本、图、视频的脚本(BOSS 过场)。最后这个东西长成了下图这样:

游戏主菜单 - 标题"印斯茅斯之书",金色触角 glyph,雾港背景
印斯茅斯之书 · The Book of Innsmouth — 一款单文件 Vite + React 项目,180KB JS,83MB 静态资源,所有立绘、卡牌、过场视频都是 AI 一次跑出来的。
简单说:《杀戮尖塔》玩法 + 克苏鲁叙事。
看下面这张地图,你大概能感受到节奏:

章节地图,4 节点路径(事件→事件→战斗→战斗),当前节点金色脉冲光环
战斗是这样 — 你抽 5 张牌,3 点精力,每张牌有消耗。打空所有敌人血条就赢:

战斗画面 - 敌人"星之眷族"(绿色发光触须),玩家手牌 5 张,调查员状态栏
事件是这样 — 不是干巴巴的选项,是真的有个小故事:

事件画面 - "黑发的医生",医生穿西装、拿血迹斑斑的手术刀,叙事文本 + 选项
注意那把血迹斑斑的手术刀——AI 准确理解了"手指太长、鳞片指甲"这个设定。
我让 AI 生成了 37 张图 + 8 段视频。下面挑几张最戏剧性的——

达贡 - 海之主宰
达贡,110HP 的大 BOSS。深海之神,三叉戟,雷暴。

星之眷族
星之眷族(克苏鲁的子嗣),35HP,深青色调触须。

修格斯
修格斯,55HP 的变形怪(爱手艺笔下那种黏糊糊、无数眼睛的)。
下面这四张是我最喜欢的——注意它们的色彩和构图几乎都是统一的(深色背景 + 单一焦点),放到手牌里毫不违和:
银弹 | 禁忌仪式 | 印斯茅斯血统 | 深潜者诅咒 |
|---|---|---|---|
18 伤害,对超自然双倍 | 14 伤害值 -3 SAN | 永久 +2 maxHP,-3 maxSAN | 对所有敌人 8 伤害,-2 SAN |
每一张事件都配一张图,让叙事落地:
黑发的医生 | 耳边的低语 | 自己的影子 |
|---|---|---|
AI 视频接口用来生成战斗过场。每次进入战斗,先放 5 秒视频。
达贡登场 — 注意它从海面升起,背景一群深潜者环绕:

达贡 BOSS 过场 GIF - 深海升起,克苏鲁怪物,红色标题
狂热信徒(第一战遇到的普通怪)— 红色烟雾,蜡烛光:

狂热信徒战斗过场 GIF - 红色烟雾、蜡烛、穿袍人物
深潜者(章二中段)— 深海蓝绿色调:

深潜者战斗过场 GIF - 深海场景,克苏鲁触须
5 秒过场后,UI 自然过渡到卡牌对战。玩家可以点击屏幕跳过。
关键思想:美术资源全部预生成到 public/assets/,游戏运行时零 API 依赖。发给别人玩,他不需要 key,不需要联网,不需要 AI 配额。
我用的网关是 O4OpenAI / Agnes,OpenAI 兼容接口。
资产生成器就一个文件:scripts/generate-assets.mjs(约 300 行)。它干三件事:
src/data/cards.js、enemies.js、events.js、acts.js 里读取每个对象的 imagePrompt 字段/v1/images/generations,size 按用途分(卡牌 1024×1024 / 事件 1024×1536 / 场景 1536×1024)视频流程稍麻烦:视频接口是异步的 —— 提交任务拿 id → 轮询 /v1/videos/:id → status === 'completed' 时从 output[0].url 下载。
看下面这一行——游戏里的达贡祭司就是这一个对象:
// src/data/enemies.js
'dagon-priest': {
id: 'dagon-priest',
name: '达贡祭司',
hp: 40,
san: 0,
tags: ['supernatural', 'elite'],
intents: [
{ type: 'attack', value: 8, weight: 2, desc: '8 伤害' },
{ type: 'san', value: 5, weight: 1, desc: '5 SAN 流失' },
{ type: 'buff', value: 2, weight: 1, desc: '+2 力量' },
],
imagePrompt: 'a dagon priest, tall amphibian humanoid in ceremonial robes, holding a deep one trident, lovecraftian elite enemy art, dark blue-green, isolated on black background',
}
imagePrompt 字段是英文的,专门为 AI 绘画优化(构图、光影、风格、背景)。改它,就能换风格——比如改成"日式浮世绘风格"重新跑一遍,整套美术就成浮世绘了。
我让脚本支持:
实际跑 37 张图:4 分钟。8 段视频:10 分钟。一次搞定。
src/
├── data/ ← 卡牌/敌人/事件/章节 数据 + prompt
├── engine/ ← 战斗 / 跑团 / 事件引擎(纯逻辑)
├── store/ ← zustand 全局状态
├── screens/ ← 画面(Title/Map/Battle/Event/...)
├── components/ ← UI 组件(CardView, EnemyView)
└── styles/ ← CSS
public/assets/
├── cards/ 10 张卡面
├── enemies/ 9 张立绘
├── events/ 12 张事件插图
├── portraits/ 1 张调查员
├── scenes/ 5 张关卡背景
├── videos/ 8 段过场
└── manifest.json ← 生成记录(断点续跑用)
vite build 之后整个 dist/ 目录就是可以独立分发的游戏——零外部依赖,发给谁都能玩。
你看到的 37 张图、8 段视频,背后还有约 3500 行自动生成的代码——
engine/battle.js): 卡牌执行、敌人意图系统、状态效果(虚弱、易伤、力量)、伤害/格挡结算engine/runs.js): 5 幕权重化节点生成engine/events.js): 12 个事件 × 多个分支选项,效果作用在玩家状态store/gameStore.js): zustand 管理 title → map → battle → event → reward → gameover 屏幕切换 + localStorage 自动存档screens/BattleScreen.jsx): 敌人意图气泡、目标选择、手牌 hover、回合结束按钮、战斗日志下面是这个项目最硬核的部分——一个有 11 个测试的 180 行战斗引擎:
// scripts/smoke-test.mjs 摘录
test('打出一张 strike 造成 6 伤害', () => {
const p = newPlayer();
const enemies = buildEncounter('e-deep-one');
const b = newBattle(p, enemies, newDeck());
b.hand = ['strike', 'strike', 'strike', 'strike', 'strike'];
b.draw = []; b.discard = [];
playCard(b, 'strike', 0);
if (enemies[0].hp !== 28 - 6) thrownewError('hp ' + enemies[0].hp);
});
npm run dev 之外,跑 node scripts/smoke-test.mjs 看 13 个战斗/事件/跑团测试是否通过。
最后贴两张没在前文出现的图——
关卡 1 背景(你搭上前往印斯茅斯的末班火车时看到的就是这个):

关卡 1 背景 - 雾港,灯塔,隐约的船骸
关卡 5 背景(BOSS 战场景):

关卡 5 背景 - 风暴海洋
调查员(你扮演的角色,1920s 经典装束):

调查员立绘 - 1920s 戴帽、穿风衣、手持笔记本与左轮
能。
10 分钟后你会在达贡面前。它 110 血,会吸你 SAN。要么 18 伤害的银弹超自然双倍秒它,要么——大多数时候——你 SAN 归零,看到"调查结束,你的意识被拖入海底"。
AI 让一个不会画画的人做出了一款有画面、有过场、有氛围的完整游戏。
这并不意味着"画师要失业了"——AI 生图可控性还很差,连续性、风格统一、人物一致性都需要反复调试。我让一张"手指太长、鳞片指甲"的医生和一段"深海升起的达贡"恰到好处,是 7 次重试 + 精巧 prompt 的结果。
但——从"我想做一款游戏"到"我有一款游戏可以玩"之间的 6 个月,缩短成了 1 天。
剩下的事——玩法设计、状态机、卡牌平衡、叙事节奏——仍然是人的事。AI 出图只是把"我有一个想法"和"我能做出东西"之间的墙,凿穿了一个洞。
祝你调查顺利。
资源生成:O4OpenAI / Agnes 网关(37 张图 + 8 段视频,4 + 10 分钟) 技术栈:Vite 5 + React 18 + Zustand + GSAP 代码量:~3500 行(含 13 个单元测试 + 3 个集成测试)