AI 结对编程做游戏,难在哪?
译注:本文编译自 dev.to 作者关于其独立游戏 Galactic Idle 的开发复盘,原文链接见文末。作者使用 Vue 3、TypeScript、Capacitor 与 AI 结对编程工具开发了一款太空帝国放置类游戏,本文记录了他认为真正耗时的地方。
一位开发者用几个月时间构建了放置类游戏 Galactic Idle,技术栈为 Vue 3、TypeScript、Capacitor(用于 Android 打包),并全程借助 AI 结对编程。他的结论很直接:AI 把写代码的成本压低了,但难点只是转移到了别处。
技术栈
- Vue 3 + TypeScript + Vite:游戏与 UI
- Capacitor:同一套代码打包为 Android 应用
- Vitest + Playwright:单元测试与端到端测试
- PostHog:需用户主动选择、经同意后才启用的分析
- 九种语言本地化,并配有覆盖率检查,缺失的翻译键会直接报错
作者坦言,所有游戏状态都塞在一个巨大的 composable useGameStore.ts 里——这不是推荐做法,而是自白,也是他后来必须回头清理的原因。
AI 让什么变便宜了
过去要花几天、现在一个下午就能完成的事:
- 接入经用户同意的分析层,从中心化的
logEvent函数统一转发 - 九种语言的 i18n
- 一套预告片录制装置:Playwright 脚本注入虚拟光标与虚拟时钟来「玩」游戏,再渲染出 16:9 和 9:16 两种游戏预告片
- 涉及数十处调用点的重构,例如把散落的
toast()调用替换为结构化的logEvent/grantResources主干与结果卡片
如果你的瓶颈是「我知道要什么,只是得把它敲出来」,这种变化会立刻被感知到。
AI 没能让什么变便宜
1. 平衡是数据问题,不是代码问题
放置类游戏本质是经济体。早期点击收益过强,作者把 clickPower 从 5000 降到 900,并对升级叠加做了平方根衰减;随后征服奖励又过于慷慨,于是砍掉了 ×3/×5 的全局奖励升级。AI 几分钟就能实现每次改动,但该改哪一个需要数据支撑。
为此他给自己留了一条取数通道:只有当 URL 含 ?__sim 时才暴露的 hook。
// Balance-sim hook — only active when the URL contains ?__sim
// Lets an offline harness fast-forward the real economy and read/drive it.
// VITE_SIM_HOOK=1 opts a production build in (scripts/capture-trailer.mjs builds that
// into dist-capture/ so the shipped bundle never carries the hook).
if ((import.meta.env.DEV || import.meta.env.VITE_SIM_HOOK === '1')
&& typeof window !== 'undefined'
&& /(\?|&)__sim\b/.test(window.location?.search ?? '')) {
;(window as unknown as { __SIM: unknown }).__SIM = {
store: useGameStore(),
tick, recalc, cleanup, fireRandomEvent,
setDtCap: (v: number) => { _tickDtCap = v },
}
}一个 Node 脚本驱动无头浏览器,用提高后的 dt 上限调用 tick,读取的是真实 store,而不是可能与经济系统脱节的再实现版本。作者建议照搬这一点:模拟真实代码,而不是它的模型。
模拟发现:削弱之后,内容大约能撑 8 到 20 小时,并且在第 3 到第 8 小时之间存在一个「信用点为负」的低谷——靠手动游玩根本发现不了。
2. 数据告诉他,他在修错误的问题
上线需用户主动选择的分析后,第一批真实数据是:
- 约 40% 的玩家在完成首个目标前就流失了
- 中位游玩时长:5 分钟
- 漏斗断崖出现在 建造 → 研究 → 出货 之间
他此前一直在纠结一个 2 小时的进度墙,而真正的问题是最初五分钟。这一点任何结对编程者——无论人或 AI——都不会告诉他,只有数据会。
一个实操坑:他的 session_end 事件实际上相当于心跳,去重之前原始计数被虚高了。在信任漏斗之前,先确认事件到底代表什么。
3. 快速生成代码会滋生死代码
当实现变得廉价,很容易留下一份半废弃的平行应用副本。作者就遇到了这种情况。一次「产品内聚性」审计删掉了整套死掉的平行应用栈,把两个逐渐分叉的消耗模型合并为一个 upkeep 系统,并把两个重叠的征服功能合二为一。
他现在的原则是:每当 AI 新增一个东西,就问它替代了什么。 如果答案是「什么都没替代」,那就是坏味道。
4. 离线收益是藏在数字里的设计决策
离线收入上限为 30 秒的实时产出,且不含 plasma。这一行代码引发的来回讨论比大多数功能都多,因为它同时牵涉平衡、变现(有一个激励广告 hook 可以提升它)和留存。代码是琐碎的,决策不是。
给其他开发者的建议
- 给 AI 明确目标,并给它验证手段。 能自查(测试、模拟、构建)时它很快,不能自查时它会自信地犯错。
- 尽早搭建度量体系。 分析和模拟器教给你的,比反复自我试玩多得多。
- 把删除当作功能。 为清理预留时间,因为生成也让混乱变便宜了。
- 绝不要让密钥出现在工具输出里。 作者用 token 踩过这个坑,务必用管道或直接赋值。
- 预期你的角色会转变:从「写代码的人」变成「决定代码该做什么、并检查它是否做到的人」。
下一步
该系列下一篇文章将深入录制装置,以及虚拟时钟如何让预告片保持确定性。作者也想知道其他放置类或经济驱动型应用的开发者如何做平衡,尤其是如何处理「最初五分钟」的问题。Galactic Idle 已在 itch.io 上线,Google Play 版本仍在开发中。