AI实践 2026-10-14

「拧螺丝啦」:WorkBuddy 把一个微信小游戏"骗"进了浏览器

从 GitHub 拉了个叫「拧螺丝啦」的微信小游戏:零引擎、Canvas2D 自绘 3D、30 关。但它只能在微信开发者工具里跑。WorkBuddy 没改一行游戏代码,写了个 10KB 的适配层把浏览器伪装成微信,30 关无头全通。这回是真·拧螺丝。

一、名字就赢了一半

打工人自嘲,说自己天天在"拧螺丝"。所以当我在 GitHub 上刷到一个叫「拧螺丝啦」(nls_minigame,作者 MrZhaoZQ)的游戏时,就没忍住——这名字,打工人看了会心一笑。

拉下来一看,正经得吓人:

  • 玩法:3D 空间规划 + 休闲解压 + 三消。旋转观察一堆叠起来的木板,把螺丝拧出来,同色三个一碰就消,木板坍塌,过关。
  • 技术:微信小游戏,零引擎、零构建管线——纯 JS 加 Canvas2D 自绘 3D(自己写了 Vec3、矩阵、射线求交、画家算法渲染)。
  • 质量:30 个关卡由生成器加校验器管线产出,近 200 项 Node 单测,包体只有 830KB(预算 4MB 的一小半)。

【插图 01 · 01-game.png】

一个休闲小游戏,工程做到这个份上,值得认真对待。

二、问题:它只肯在微信里跑

然后我就撞上了微信小游戏的经典门槛:必须装微信开发者工具,导入项目、编译、预览——一套流程走下来,玩的心情先凉一半。

我只是想现在、立刻、马上玩一下。

看了一眼代码结构,发现希望很大:游戏通过一个 Platform.js 访问平台能力,而且只认全局的 wx 对象——检测到 wx 就走微信分支。也就是说,只要有个东西能假装自己是微信,游戏根本不会发现。

三、WorkBuddy 的解法:不改一行代码,把浏览器伪装成微信

我把这事丢给了 WorkBuddy。它的方案很克制:游戏源码一行没改,在旁边加了一个 web/ 适配层,核心是一个 10KB 的 wx-shim.js——用标准 Web API 把 wx.* 的接口一个个实现出来,让游戏以为自己跑在微信里。

几个关键翻译:

  • createCanvas → 在页面里建 canvas,接上指针和滚轮事件;
  • 触摸事件 → Pointer Events 转成微信的结构;
  • getStorageSync → localStorage(加个 nls: 前缀);
  • 音效 → WebAudio 解码 wav,失败还有 HTMLAudio 兜底;
  • vibrateShort → 浏览器的震动接口;
  • 广告、分享这些浏览器给不了的 → 返回 null,而游戏代码本身对 null 有兜底,激励按钮干脆直接发奖,本地把完整流程体验了一遍。

配上一段 esbuild 打包,游戏就在浏览器里跑起来了——滚轮还被顺手映射成双指捏合,桌面端能缩放视角。

【插图 02 · 02-shim.png】

这就是"适配层"这个老派工程模式的妙处:两个世界不匹配,不去改任何一边,在中间放一层翻译。 游戏仓库保持原样(还能跟着上游更新),浏览器那头也不用迁就谁,所有不匹配的脏活都收敛在那 10KB 里。

四、一个真实的坑

过程也不是一帆风顺。打包完一跑就报错:Module not found in bundle: ./levelData/level_001。

原因:游戏加载关卡用的是动态 require——require('./levelData/level_' + n),路径是运行时拼出来的。打包器只能静态分析,看到这种写法直接懵了。

解法也干净:写了个小脚本扫一遍关卡目录,生成一份显式的静态索引(每个关卡逐个列出,照样惰性加载),再让打包脚本里一个小插件把原来的动态入口重定向过去。游戏代码还是一行没动。

这类坑没有技术上的高潮,但每一个都得有人踩、有人填。

五、验收:数字说话

跑起来之后做了两层验证:

  • 近 200 项单测全绿(实跑 199 项,0 失败)——游戏自带的测试套件,适配层没碰坏任何逻辑;
  • 30 关无头全通——用模拟贪心玩家把 30 关从头打到尾,全部 WIN。

最后本地起个静态服务,index、bundle、shim、音效资源全部 200,浏览器打开就能玩。

【插图 03 · 03-pipeline.png】

六、这回是真·拧螺丝

回到名字。这整个事,游戏本体在拧螺丝,把它跑起来的人也在拧螺丝——查接口、写翻译、填动态 require 的坑、跑验证。没有一步是"设计一个伟大架构",全是小而具体的活。

但这恰恰是工程的大头。真正稀有的是那个 830KB 里自绘 3D 的游戏本体;而从一个仓库到"能玩",中间隔着的全是拧螺丝:适配、兜底、转换、验证。

有意思的是,这次拧螺丝的活大部分是 WorkBuddy 干的:读代码找出生死攸关的 wx 检测点、写适配层、踩坑、补测试。我的角色变成了那个指着木板说"把这几颗拧下来"的人。

游戏把"拧螺丝"做成了消遣,AI 把"拧螺丝"做成了默认工作量。 留给人的部分反而更值钱了:判断往哪拧。

想自己跑的话:GitHub 搜 nls_minigame,克隆下来装个微信开发者工具导入就能玩;懒得装的话,照着仓库里 web/README.md 三条命令,浏览器里一样开玩。