在2026年7月的大约一周时间里,我把五款浏览器游戏发布到了自己的网站上:一款《我的世界》风格的体素生存游戏、一款《马里奥赛车》风格的3D竞速游戏、一款《糖果传奇》风格的三消益智游戏、一款在真实世界地图上进行、拥有一千多个程序化生成省份的大战略游戏,以及一款以韩国民间传说为背景的《超级马里奥》风格平台跳跃游戏。这五款游戏全部完全运行在浏览器里,没有后端、没有构建流程,除了域名费用之外没有任何预算。而且这五款游戏几乎全部是与一个AI编程智能体配对完成的——我扮演的是产品负责人、测试人员,以及唯一真正盯着屏幕看的那个人。
我这个网站是做AI和科技话题的,但这次我想看看,在一个和我平时写的CRUD应用、内容流水线完全不同的软件类别里,AI智能体到底能走多远:带有物理引擎、程序化内容和敌方AI的实时游戏,“能编译通过”和”好玩”之间的距离完全是两回事。发布这五款游戏的过程,让我看清了真实的开发流程是什么样子——以及让这一切成为可能的那一个关键决定。
五款游戏,一套统一的静态文件夹结构
每款游戏都以public/games/<slug>/路径下的一小撮静态文件形式存在——一个index.html加一两个.js文件,3D游戏偶尔还会附带一个像Three.js这样的小型第三方库。没有打包工具,没有构建步骤,也没有需要时刻打补丁的npm依赖树。一个统一的注册文件用五种语言列出了每款游戏的slug、标题和描述;游戏列表页、每款游戏的详情页,以及网站地图,全部都从这一份列表自动生成。想添加第六款游戏,只需要往数组里加一条记录。
五款游戏简单介绍如下:
- 一款体素生存游戏 —— 昼夜循环、七种行为各异的怪物、每逢第三个夜晚的一场Boss战、成就系统,以及带武器挥砍动作的第一人称战斗视角。
- 一款3D卡丁车竞速 —— 一条带有坡道、弯道倾斜和S形弯的赛道、十一名属性各异的可玩角色、靠漂移充能的氮气加速,以及采用”橡皮筋”机制让比赛始终胶着却又不显得像剧本一样的电脑对手。
- 一款三消益智游戏 —— 8x8的棋盘、四种特殊方块(包括能一次清空一种颜色的彩虹方块)、粒子特效,以及完全靠Web Audio API合成、不使用任何音频文件的132拍每分钟背景音乐。
- 一款大战略游戏 —— 以真实国界为种子、通过泰森多边形(Voronoi)剖分生成约1,200个省份的真实世界地图、人口与粮食生产模拟,以及230个各自拥有独立外交与战争逻辑的AI国家。
- 一款平台跳跃游戏 —— 用九尾狐、道깨비(鬼怪)、勾魂使者之类的韩国民间妖怪取代了库巴仔和板栗仔,五个手工设计的关卡,还有一只扮演耀西角色、可以骑乘的独角兽。
这些游戏没有一款需要服务器。进度和本地排行榜都存在localStorage里,配合一个导出/导入按钮,存档文件就是一次简单的JSON下载——这是没有后端这件事上唯一真正的变通方案,此外我还留了一个钩子(一个尚未使用的REMOTE_API常量),以备将来想接入真正的跨设备排行榜。
部署循环
网站本身是一个静态的Astro构建产物,通过把刚构建好的dist/文件夹强制推送到gh-pages分支来发布到GitHub Pages——一段两行的脚本,每次有新内容要发布时就跑一遍。游戏(以及网站其余部分)的语言切换用的是普通的?lang=查询参数,而不是各自独立的本地化路由,这样一份游戏构建产物就能在没有任何i18n框架的情况下服务五种语言。移动端支持是后来才加上的,是叠加上去的一层,而不是重写:触屏设备会被自动检测到(pointer: coarse,在桌面端测试时可用?touch=1强制开启),虚拟方向键和按钮会把值写入与键盘控制原本使用的完全相同的按键状态对象——所以游戏逻辑本身完全不需要知道输入是来自拇指还是键盘。
最重要的一个决定:不靠人来测试
这才是这个项目能以这样的速度真正发布出来的关键所在。游戏在本质上是交互式和视觉化的,这让AI智能体格外难以独自完成验证——你没法仅凭一段文本diff就断言”这个物理手感是对的”。最初的直觉是用无头浏览器像人一样去操作游戏。但这行不通,原因不亲身撞上是不会明白的:无头Chrome的虚拟时间预算并不能可靠地驱动requestAnimationFrame。一个基于rAF构建的游戏循环,在无头自动化下无论把虚拟时间预算调得多长,都跑不出一个有意义的速率。任何建立在”打开页面、等待、截图”之上的测试,基本上什么都验证不了。
真正让这五款游戏都能在无人碰鼠标的情况下被验证的解决办法是:每款游戏都内置一个?test=sim模式,以固定的时间步长同步推进游戏物理,完全脱离requestAnimationFrame和真实时钟,并用console.warn而不是console.log来记录断言结果——无头Chrome的stderr捕获能可靠地抓到warn级别的输出,却会漏掉普通的log。正是这一个模式——确定性的同步步进,加上warn级别的日志——让AI智能体得以确认:平台跳跃游戏的五个关卡是否都能通关、三消棋盘是否永远不会死锁、战略游戏里的省份邻接关系在AI推进数十回合之后是否依然保持对称、每一个存档文件是否都能正确地往返保存与恢复——而这一切都是在没有任何人打开真实浏览器标签页玩过的情况下完成的。还有一个更轻量的辅助模式?shot=1,能把帧时钟瞬间冻结,以便截图捕捉某个特定的戏剧性瞬间(一次爆炸的中途、与Boss相遇的一刻),而不必依赖时机上的运气。
让我学到最多的一个bug
大战略游戏在绘制约1,200个省份时,做法是把每个省份的数字ID编码成一种颜色,画到一块隐藏的画布上,然后再把像素颜色读回来,用来回答诸如”这个坐标属于哪个省份""哪些省份彼此相邻”之类的问题。这是一个挺巧妙的技巧——把画布当成一张查找表来用,而不是当成一张图片——直到你想起画布会在图形边界处做抗锯齿处理。这种混合在每一个省份边界上都悄悄”发明”出了并不对应任何真实省份的ID,进而污染了质心计算和邻接数据,单个看都很微小,累积起来却诡异得很:计算出来的德国中心点,最后跑到了大西洋中间。解决办法是把每一个解码出来的像素都拿去和该省份真实的向量包围盒做校验,校验失败的像素就用周围像素的多数表决来代替。这个教训也直接搬到了其他游戏上:任何时候只要把一个渲染表面当作数据结构而不是图片来复用,抗锯齿、混合、mipmap这些渲染管线自带的”贴心功能”,就都变成了随时可能发作的正确性bug。
AI智能体在这类工作里真正擅长的地方
做完这五款游戏之后,我的真实看法是:AI编程智能体确实非常擅长解决那些拖慢独立游戏开发速度的具体环节——搭建存档系统、在画布上以程序化方式生成矢量美术而不是去找现成的精灵素材、在难度曲线可被量化之后对其进行调优(比如三消游戏的数值平衡,不过就是跑上几千局模拟对局,把每一步的平均得分和目标值做比较)、以及把在一款游戏里验证过的模式移植到下一款游戏里。但它无法替代真正去玩一遍成品——有几个bug只在合成测试的断言技术上通过、而实际行为却是错的情况下才暴露出来,真正的防线只有肉眼查看联系表截图,或者在收工前亲手把成品玩一遍。整个项目里杠杆效应最大的工作,并不是任何一款具体的游戏,而是把?test=sim这个模式一次性搭建好——这样从第二款游戏开始,每一款都直接继承了一种无需任何人用眼睛盯着就能完成验证的方式。
五款游戏全部可以在menewsoft.com/games免费畅玩。