半天,AI 帮我从零实现了我五年前做的娃娃机
五年前,我一砖一瓦手写了这台 3D 娃娃机。五年后,我整理好需求,让 AI 用半天把它实现了一遍。
项目地址:github.com/neciszhang/…
在线试玩:neciszhang.github.io/claw3d
起源
五年前,我做了一台 3D 娃娃机。
那时候 Three.js 还在 r1xx 的版本,React 还没有 Hooks,物理引擎要在浏览器里跑 WASM 还是一件很折腾的事。我用裸 Three.js + 手写物理近似 + 一堆 if-else 状态机,硬生生搭出来一个能玩的娃娃机。
模型是自己拿 Blender 捏的,材质是手调的,贴图是用 WebP 格式硬塞进去的。每一个玩具的碰撞检测、每一次爪子下落的轨迹、每一个硬币的扣减逻辑,都是我一行一行敲出来的。那台娃娃机跑得很卡,bug 很多,但我很骄傲——它是我做的。
后来项目就躺在那里了。五年,技术栈翻了几轮,它成了一个时间胶囊。
重生
直到今天。
我把五年前的 3D 模型文件找出来,整理了下主要需求——游戏流程怎么走、物理碰撞怎么算、UI 怎么交互、难度怎么分级。然后让 AI 帮我写。
然后,半天。
半天。27 个源文件,3664 行 TypeScript 代码。
- React 19 + TypeScript 5.6 的组件架构
- @react-three/fiber 9.7 驱动的 3D 渲染管线
- @react-three/rapier 2.2 接入的 Rapier 物理引擎——真实的刚体碰撞、堆叠、滑落
- Zustand 5.0 管理的完整游戏状态机(13 个状态:BOOT → LOADING → TUTORIAL → COIN → READY → MOVING → GRABBING → RESULT → COMPLETED…)
- 完整的抓取流程:移动 → 下降 → 闭合 → 上升 → 移动到出口 → 释放,每一步都有缓动函数和时间控制
- 三档难度系统,影响爪子速度、传感器半径和玩具布局密度
- 实时小地图、双语国际化、自适应画质、音效震动反馈、新手引导、数据持久化
- GitHub Actions 自动部署到 GitHub Pages
这些不是空话。我翻看 AI 生成的代码——GrabController 里的状态机用 performance.now() 精确计时,缓动函数用了正确的 easeInOut 公式,物理参数被抽成可配置常量,甚至玩具的碰撞传感器都做了三触点检测。状态管理用 Zustand 的 selector 做了精准更新,避免不必要的渲染。这些是五年前我花了一周才想明白的事情。
五年前 vs 半天
五年前,我做这台娃娃机的时候:
- 搭环境装依赖用了大半天
- 物理碰撞调参调了三天,玩具老是穿模
- 状态机写成了面条代码,改一个分支牵连三个功能
- 手机适配做了两天,虚拟摇杆的灵敏度怎么都不对
- 部署到线上又折腾了一天,HTTPS 证书、路径配置、CDN 缓存
- 总计:大概两周
现在,我把需求理清楚之后,AI 半天就把它们全部实现了。
而且实现得比我当年好。代码结构清晰——配置文件、游戏逻辑、UI 层、音频层、存储层各司其职,27 个文件每个都有明确的职责。物理引擎从手写近似升级到了 Rapier 的真实刚体模拟,玩具之间的碰撞、堆叠、滑落都是引擎在算,不用我操心。状态机用 TypeScript 的联合类型做了严格的类型约束,13 个状态之间的转移不会出错。
感慨
我不是在感叹「AI 取代了程序员」。
我是在感叹「时间」。
五年前,我做这个项目的时候,每一个技术决策都需要翻文档、查 Stack Overflow、试错、调试。物理引擎怎么接?Three.js 的 render loop 怎么管理?移动端的 touch event 怎么映射到 3D 空间?这些问题,每一个都要花掉我半天到一天的时间。
现在,AI 一个个帮我跨过去了。不是因为它「聪明」,而是因为这五年里,无数程序员在无数项目里积累的经验,已经沉淀成了 AI 可以调用的知识。它站在五年来所有前端工程师的肩膀上,把那些曾经困扰我的问题,变成了理所当然的答案。
五年前的那台娃娃机,是我一个新手摸索着做出来的。粗糙,但是真实。
五年后 AI 实现的这台,是我在半天里把需求变成成品的。精致,而且高效。
它们之间隔着的不是 AI 的能力,而是整个行业五年的积累——加上我自己这五年想清楚了到底要做什么。
未来
这个项目我打算开源出去。不是为了证明什么,而是觉得——如果五年后再来一次,也许半天都不需要了。
五年的技术进步被压缩进了半天的 AI 协作里。那下一个五年呢?
我不知道。但我很期待。
写于 2026 年 8 月 7 日,娃娃机实现完成之夜。