靠 AI 一个人一个月做出微信+抖音双端小游戏:我的对话式开发实录

2026-十月-23T06:35:36.000Z
阅读:70
字数:6271
评论:0
作者:pwl201314

靠 AI 一个人一个月做出双端小游戏:我的对话式开发实录

一个月前,我给自己定了个目标:做一款能上线、能靠广告活下来的小游戏。不组队、不融资、不用现成游戏引擎——但也不"纯手写":全程和一个 AI 结对,我负责方向和验收,AI 负责设计、实现、测试和排坑。

现在这款游戏——《猫咪守卫队》(合成 + 守城塔防,微信)已经完成开发进入审核流程。这篇文章是完整复盘:AI 结对到底怎么工作、坑长什么样、怎么被 AI 写的自动化测试救回来的。全文约 5000 字,建议收藏。

一、起点:一个免费素材包逼出来的架构决策

项目起点是 xx网站 的一个免费卡通猫防御素材包:角色立绘、UI 套件、场景图,以及——最关键的——32 套 Spine 骨骼动画(JSON Atlas 格式)。

拿到素材第一件事不是写代码,是让 AI 通读素材清单,先把设计文档全部吐出来:玩法循环、15 级进化链的数值公式(伤害 1.35^lv 成长这类)、关卡波次结构、广告变现节点,七份文档文档化之后才动工。这个顺序后面被证明极其正确:数值公式定稿后,波次、Boss、经济的迭代全是在表格层面推演,不用反复改代码试。

技术选型时 AI 给了我三个选项的分析:

选项一:Cocos Creator。  我真装了。但玩法是纯 2D、无物理需求、UI 自己画,引擎运行时对小游戏 4MB 主包限制来说是笔不小的"税"。而且小游戏的坑大多在平台适配层(微信/抖音 API 差异、真机怪癖),这层不管用什么引擎都得自己趟一遍。

选项二:Laya / Egret 等老牌 H5 引擎。  生态偏老,TS 支持和工具链不如自己搭的顺手。

选项三:自研 TS + Canvas。  渲染层只需要:图片、圆角矩形、文字、渐变、粒子——Canvas 2D 原生全覆盖。缺的不是渲染能力,是工程化。

最终落自研:

  • TypeScript + Canvas 2D,esbuild 打成单文件 IIFE
  • 平台适配层:统一 Sys 接口(canvas / 触摸 / 存储 / 音频 / 广告 / 震动),三个实现 WebSys / WxSys / TtSys,业务代码零平台分支
  • 产物:web/bundle.js、dist/wechat、dist/douyin,一套代码三端跑

最终三端总包 2.76MB,无分包——Spine 运行时 + 全部素材 + 游戏逻辑,远低于微信 4MB 主包红线。

二、人机结对到底怎么分工

先讲清楚工作流,后面所有章节都是它的注脚。一个月下来,稳定成型的分工是:

我(人类) AI
提需求、给素材、定产品方向 写设计文档、架构、全部业务代码
真机测试,把截图和报错丢回去 定位根因、改代码、跑四套测试回归
体验判断:"Boss 太强了""18 波太长" 数值推演、实现改动、全绿后提交
我自己也直接改代码(UI/波次大改过几百行) 改完后 AI 负责更新测试坐标、补回归用例

几个关键心得:

  1. 人类的黄金价值是"体感反馈" 。"第四关 Boss 打不过去""标题太生硬"——这种一句话的体验判断,AI 永远给不出第一手,但拿到之后能一路推到具体数值和代码。
  2. 让 AI 改代码的前提是先有测试网。我让 AI 在写功能的同时就写好四套自动化测试(第五章),之后所有改动——不管是 AI 改的还是我自己改的——都过同一道回归门。没有这张网,人机结对的翻车率会指数级上升。
  3. 验收要两道:像素采样证"画了",AI 目检证"看见" (第七章展开)。

三、Spine 骨骼动画:动画"从未播放"的三重坑

素材包里的 Spine 动画是最大的卖点(猫咪的待机/攻击/受击全是骨骼驱动),也是最大的坑源。接入 @esotericsoftware/spine-canvas@4.3 后,画面上所有角色纹丝不动——攻击照常出伤害,但模型像一尊雕塑。

我把症状描述给 AI(伤害在跳、模型不动),它排查出是三个问题叠加:

坑 1:TextureAtlas 构造 API 变了。  网上教程(包括官方旧文档)的写法是把图片和文本一起传给构造函数,4.3 版本实际是构造函数只收文本,图片要逐页手动绑定:

evolve-effects.png ts

const atlas = new spine.TextureAtlas(atlasText);
for (const page of atlas.pages) {
  const img = await loadImage(page.name);
  page.setTexture(new spine.CanvasTexture(img));
}

这个 API 变更没有任何运行时报错,就是白屏/不动。

坑 2:每帧更新顺序不能错。  正确顺序是:

ts

state.update(dt);
state.apply(skeleton);        // 把动画姿态写到骨骼
skeleton.update(dt);
skeleton.updateWorldTransform(spine.Physics.update);

漏掉 state.apply(skeleton),skeleton 永远保持初始姿态——这是"伤害在跳、模型不动"的直接原因。

坑 3:最隐蔽的一个——加载流程漏调了初始化。  早期 AI 用批量补丁改过一次 app.ts,补丁脚本的断言失败了,但被 try/catch 静默吞掉,导致 SpineCache.loadAll() 压根没执行。这个坑后来成了我们结对流程的一条铁律:

批量补丁的断言失败必须让整个流程报错,而不是静默跳过。  否则你修的是 A,坏的是 B,而日志里一片绿色。

附带一坑:怎么证明"动画在动"?  最初 AI 读 bone.pose.worldX 做活性检测,发现永远是 0——因为渲染走的是 appliedPose,不在 bone.pose 上。最后改成连拍两帧像素对比:同一位置截图两次,差异像素超过阈值才算"动了"。土,但真实。

不同体型单位的贴地问题,用 skeleton.getBounds() 算包围盒,做脚底对齐 + 高度归一化,保证 Lv1 小猫到 Lv15 巨猫都踩在同一地平线上。

四、微信真机适配:四个"灵异现象"

boss-battle.png

模拟器一切正常,真机全是惊喜。我把截图和报错一张张丢给 AI,它总结出一条小游戏开发铁律:永远不要用"应该"来猜测平台行为,拿不到的数据就返回 null,绝不编造。

现象 1:画面旋转 90°。  真机上整个游戏横过来了,拖动点击全部错位。根因:微信小游戏启动早期 jsbridge 未就绪时,getWindowInfo 返回的是竖屏尺寸,代码用错误尺寸建了横版画布。修复分三刀:

  • systemInfo 获取失败返回 null,绝不 fallback 猜一个尺寸
  • main.ts 里轮询等待桥就绪(200ms × 25 次)再 boot
  • 画布尺寸只在真正发生变化时写入,避免中途上报竖屏值把画布写坏

现象 2:jsbridge not ready 直接崩。  启动期调用系统 API,微信侧桥还没注入。同上,等。

现象 3:document.getElementById is not a function。  为浏览器调试写的 DOM 垫片垫得不全,真机直接抛异常。最终方案:五重判定 isRealBrowser(),浏览器专属代码严格隔离到 WebSys。

现象 4:导入开发者工具就报"未找到 game.json"。  小游戏根目录和仓库根目录不是一层,放一个 project.config.json 指向 miniprogramRoot: dist/wechat/ 即可;纯资源分包必须有 game.js——最后评估包体足够小,直接取消分包。

五、包体 2.76MB:不是优化出来的,是设计出来的

rouge-choice.png

小游戏主包 < 4MB 是硬红线,最终三端总包 2.76MB:

  1. 图片统一走 PNG 压缩管线(manifest 清单化管理)
  2. 音频全部程序化合成:19 个音效 + 2 首 BGM,AI 用纯 Python 标准库(正弦波/噪声/ADSR 包络)生成 PCM 再转 AAC。零外部音频素材、零版权风险——这也是 AI 结对的典型收益:这种"一次性造轮子"的脏活,AI 干得又快又没有情绪
  3. 单文件 IIFE:esbuild 打包,不做按需加载,启动后全内存
  4. Spine 素材按 manifest 精确注册,不进任何"以防万一"的冗余文件

画质取向:移除了自动降质逻辑,强制 imageSmoothingQuality = 'high',低端机宁可掉帧也不糊——产品决策我拍板,实现 AI 落地。

六、一个人的 QA 团队:让 AI 写代码不翻车的四张安全网

tutorial-battle.png

人机结对最大的风险不是 AI 写不出功能,是改 A 坏 B 而不自知。我让 AI 在开发早期就搭了四套测试:

1. 无头整局模拟:Node 直接实例化 Battle,快进模拟整局,断言波次推进、合成规则、胜负星级。跑一遍 3 秒,覆盖 90% 逻辑回归。

2. 像素冒烟测试:Playwright + 无头 Chrome,连拍两帧像素对比(证明动画在动)+ 素材加载检查 + 运行时错误捕获。

3. 微信环境无头模拟:mock 完整 wx API,覆盖横竖屏切换、jsbridge 延迟、systemInfo 为 null 等真机场景。旋转 90° 的回归用例就住在这里。

4. 18 项全流程交互:从签到、训练、进关、召唤、拖拽合成、技能释放、暂停退出到重新进关,全自动点一遍。

这套体系的价值在下一章的数值迭代里,有现场证据。

七、数值迭代现场:波次分级是怎么翻车又救回来的

上线前玩家反馈:一局 18 波太长了。我的决策:按难度分级——难度一 12 波、难度二 14、难度三 16、难度四 18(难度五 20)。

AI 的第一版实现看起来很"工程正确":波次结构从硬编码 18 改成 CHAPTER_WAVE_COUNTS + actBounds() 统一推导(三幕均分,幕末守门 Boss、倒数第二波怪潮),再加一刀切的密度补偿——每波敌人预算 ×(18/波数),防止短局经济缩水。

跑测试,教学关第 1 波直接团灭。  12 波局的第一波敌人从 3 只变成 5 只,新手两只猫,墙被啃穿;第 12 关同样第 1 波就输。

AI 自己的测试抓住了 AI 自己的 bug——这就是安全网的意义。修正后的形状是渐进补偿:开场与 18 波经典局完全一致,随进度逐步加密,12 波局末段约 1.5 倍:

ts

const dens = 18 / waveCount;
const densW = 1 + (dens - 1) * Math.pow(w / (waveCount - 1), 0.6);
const budget = Math.max(2, Math.round(3 + (ramp * densW)));

教学关回绿,末波 Boss 强度对齐。这次迭代还修掉一批历史硬编码(路线选择触发点、路线时长写死 waveIdx + 6、HUD 幕数 floor(wn/6)),也暴露了交互测试的时序脆弱:30 秒采样点恰好落在三选一弹窗上,暂停按钮点了个寂寞——改成轮询等回 playing 再操作后彻底稳定。

没有这张测试网,这个改动会带着"教学关必输"的 bug 直接上线——而且无论写代码的是人还是 AI,结局一样。

八、视觉验收:像素采样 + AI 目检,一个都不能少

标题 Q 版化(逐字弹跳、金橙渐变、猫爪点缀)时,我们沉淀了一套双保险验证法,也是"AI 验收 AI"最有意思的部分:

  • 像素采样证"画了" :在期望坐标取 getImageData 比对颜色值(猫爪主垫 #fff3e0 是否出现在指定坐标)——证明代码真的把图形画到了画布上
  • AI 目检证"看见" :截图丢给视觉模型,问"两侧有没有猫爪?挡不挡字?"——证明图形在真实视觉尺度上可辨识

为什么要两道?因为有次像素采样全对,但图形太小太淡,视觉模型根本没把它识别成装饰——"画了"和"看见了"是两回事。后来猫爪挡字,我人眼反馈"挡住了",AI 挪完再用两道验收收口。

另一个跨平台教训:装饰猫爪最初用 emoji(🐾)实现,无头浏览器里根本不渲染。改为纯代码绘制(贝塞尔画爱心肉垫 + 三趾 + 描边)后三端表现完全一致。emoji 属于文案,不属于画面。

九、备案与合规:独立开发者绕不开的一课

国内上线小游戏,备案材料本身就是个工程:

  • 单机/联网分类:自建服务器(排行榜/云存档/远程配置)会把单机翻成联网,选择了纯本地存储保住单机分类
  • 名称一致性:备案名《猫咪守卫队》,首页最初是英文 Logo,被驳回"名称与游戏名称不一致"——AI 改中文标题,再迭代成 Q 版逐字标题(备案要一致、观感要 Q,两个需求不冲突)
  • 材料文案:场景描述、玩法描述、系统功能(如实写明"无内购、纯广告")都有字数与口径要求,这类八股文正是 AI 的舒适区
  • 流量主现实:UV≥1000 才能开通流量主,此前广告 API 拿不到广告位,代码要为"无广告"状态做好降级,提审版本要避免"按钮声称看广告、点击直接发奖"的合规风险

十、写在最后:一个月下来,人和 AI 各值哪块钱

回看这一个月,我的结论:

  1. AI 把"实现"的价格打到接近零——设计文档、三端适配、Spine 接入、音频合成、四套测试,这些在传统外包报价里是大几万的活。人类的时间全部花在了刀刃上:体验判断、产品决策、真机验收。
  2. 但人类的判断一次都不能省。"Boss 太强砍 20%""18 波太长""标题生硬"——每一句主观反馈都是 AI 摸不到的地板。产品品味是结对里的稀缺资源。
  3. 安全网决定了结队的上限。测试、断言、双保险验收,这些"不产出功能的投资"恰恰是人机协作能敢快跑的原因。

游戏叫 《猫咪守卫队》 :拖拽合成 15 级进化、五路守城、肉鸽三选一、七个技能 Boss、每日 Boss 与无尽模式,完全免费无内购。微信搜索即玩(上线后替换为准确入口)。

想了解某个模块更深的展开(Spine 接入完整代码 / wx mock 设计 / 音频合成参数 / 人机结对的提示词技巧),点赞过百我拆专文。

0 / 130
评论列表(0)