前段时间我用 9 天时间做了一个网页联机卡牌游戏 Neo Card Party,前前后后提交了 160 多次,经历了 6 次架构重写。这篇文章就当是个开发记录,分享一下这个过程。
第 0 天:边缘计算的惨痛教训
一开始我想用 EdgeOne Pages(边缘函数平台)来做联机,结果被坑得很惨。KV 存储限制多、边缘函数跑游戏逻辑各种水土不服。
折腾了半天,最后结论是——边缘函数不适合做实时联机游戏。果断放弃。
第 1 天:283 行的起点
真正的起点其实特别简单——一个叫 ASCLLuno 的单 HTML 文件,283 行代码,用纯 ASCII 字符在浏览器里渲染卡牌。没有框架、没有构建工具、没有后端,就是一个文件。
从下午 4 点到 6 点,2 个小时就做出了一个能玩的 UNO 界面。当时的感觉是:这东西有戏。
但这个版本的问题也很明显——单页面、无路由、无状态管理、无后端、无联机。就是个玩具。
第 2~4 天:走在错误的路上狂奔
接下来做了一个叫 myasclluno 的项目,开始了第一次”正经”重构。这次选择了多页面终端风(Cyber-Terminal)架构。
3 天时间,60 多次提交,经历了:
- 3 次架构重写:多页面 → 前后端分离 → Canvas 渲染
- 20+ 次联机调试:等待大厅、重复创建房间、连接失败、聊天系统重构了 3 次
- 1 个文件暴涨到 1522 行:所有 HTML/CSS/JS 塞一起,完全失控
典型的”屎山越堆越高”——每次遇到瓶颈就换架构,但每次换架构只是把问题推迟了。
为什么这么挣扎?后来复盘发现 8 个致命问题:
- 游戏逻辑写了两遍 — 前端一套规则、服务端一套规则,修 bug 要改两个文件
- 页面膨胀失控 — 没有组件化、没有模块系统
- 零测试 — 全靠手工点点点
- 没有构建工具 — 没有 npm、没有 TypeScript、没有热更新
- Canvas 和 DOM 两套代码同时维护
- 联机系统残缺 — 没有掉线重连、没有玩家持久化、没有结算流程
- 移动端靠 hack — 比例缩放能显示,但交互坐标全是补丁
- 代码规范建立太晚 — 大量代码已经写死,改不动了
最后一天(第 4 天凌晨 2:46)做完最后一次视觉升级后,我做了个决定——放弃整个项目,从零开始用正确的方式重写。
第 5~9 天:真正的成功
新项目叫 myUNO(后来改名为 Neo Card Party)。这次从第一天就用了正确的工程实践:
从零开始,不修旧代码
没有在旧项目的废墟上修补,而是直接开新仓库。第一天就用 Vite + TypeScript SPA,单页面应用 + Hash 路由 + View 接口。这是现代 Web 游戏前端的正确基础。
最关键的决策:共享协议包
吸取了之前前后端规则写两遍的教训,抽了一个 shared 包——GameAction 类型、UnoCard 接口、计分函数全部一处定义、两处引用。前后端契约由 TypeScript 类型系统保证一致,编译期就能发现不匹配。这个决策后来被证明是整个项目最正确的选择。
测试先行
旧项目零测试、全靠手工点。新项目第一天就加了测试文件,后来服务端拆出了 4 个可测试模块,每个都有配套测试。测试覆盖了出牌合法性、多人流程等核心场景,联机 bug 大幅减少。
正确的分层
服务端不再是单文件包揽一切,而是拆成了职责清晰的 4 个模块:
- 规则适配器 — 判断出牌合法性
- 私有牌状态 — 处理手牌和牌堆
- 公共状态投影器 — 同步客户端可见信息
- 动作控制器 — 处理出牌/摸牌/跳过/选色
房间只负责生命周期和消息路由,具体逻辑委托给这 4 个模块。
响应式状态管理
用 Proxy 实现响应式状态,所有状态变更自动触发事件,UI 自动更新。联机场景下服务端推送的状态只需写到 state,所有相关 UI 自动同步。
一些有意思的数字
| 指标 | 旧项目 (myasclluno) | 新项目 (myUNO) |
|---|---|---|
| 开发天数 | 4 天 | 5 天 |
| 提交数 | 60+ | 165+ |
| 测试文件 | 0 | 10+ |
| 架构重构次数 | 3 次(救火式) | 0 次(一次成型) |
| 最终状态 | 被放弃 | 成功发布 |
5 天 165 次提交,没有一次架构重构——不是因为代码写得更好,而是因为吸取了所有教训,从第一天就用正确的工程实践来构建。
学到的几件事
- MVP 先行:从单 HTML 文件起步快速验证,比一开始就想”完美架构”重要得多
- 架构演进而非预设:每次重构都是因为碰到了真实瓶颈,而不是为了用某个技术
- 前后端契约最重要:shared 包解决规则分裂,但依赖管理是持续的挑战
- 联机是复杂度倍增器:等待大厅和重连花了最多调试时间
- 运营系统是另一个游戏:邮件、兑换码、排行榜结算的工作量不亚于核心玩法
- 移动端不是缩小版:横屏游戏的交互坐标需要从底层适配,不能靠事后打补丁
最后
这个项目从 5 月 2 日的边缘函数实验开始,到 6 月 11 日发布公共版,中间经历了无数次失败和重来。但回头看,那些”失败”的项目其实都不是白费的——每一次踩坑都让下一个版本变得更好。
如果你也对做游戏感兴趣,欢迎到 GitHub 看看,也欢迎 star 和支持!
在线体验:uno.songzhearen.cn
项目时间线:2026-05-02 ~ 2026-06-12,跨越 4 个仓库,165+ 次提交