65 格竞速地图
棋子沿路线推进,并在地标、事件、碰撞和道具作用下改变局势,最终以到达终点决定胜负。
独立全栈 / AI 协作开发
一款面向桌面浏览器的多人竞速棋盘游戏。项目将 65 格地图、事件与道具系统、离线人机对战和 2 至 4 人真人 / AI 混合联机整合在同一套确定性规则中,并围绕可靠同步、断线恢复与内容版本管理完成全栈实现。
玩家可以直接配置本地棋手开始离线对局,也可以创建私人房间,邀请其他玩家加入。真人和 AI 可以混合入座,房间覆盖准备、开局、回合行动、事件选择、道具取舍、胜负结算及恢复流程。
棋子沿路线推进,并在地标、事件、碰撞和道具作用下改变局势,最终以到达终点决定胜负。
支持 2 至 4 个座位,本地和联机模式共享规则与 AI 能力,便于单人体验和多人组局。
通过房间码加入对局,包含房主权限、座位准备、开局控制和房主转移等完整流程。
刷新或短时掉线后可恢复原座位;超过宽限时间后由 AI 接管,避免整局因单个玩家离线停滞。
行动过程包含事件候选、主动与被动道具、目标选择和取舍确认,增加路线竞速之外的决策空间。
地图、事件与皮肤可在管理端编辑、校验、预览、审核、发布和回滚,运行中的房间锁定开局版本。
项目由玩家端、游戏服务器、内容服务器和管理后台 4 个应用组成,并抽取规则、协议、AI、内容和渲染等共享包。依赖方向保持单向:领域包不依赖 React、WebSocket 或数据库,应用层在这些稳定边界之上组合产品能力。
规则函数接收状态、游戏定义、玩家和命令,输出新状态、领域事件及表现提示,不直接操作 DOM、Canvas、网络或数据库。
共享类型之外,协议包以 Zod 校验不可信网络数据,并维护协议版本与 TypeScript 推导类型,减少客户端和服务端漂移。
State 保存权威事实,DomainEvent 描述业务语义,PresentationCue 提供骰面、路径和动画信息,共同兼顾恢复与表现。
权威状态保存 RNG seed 与 cursor。同一游戏定义、初始状态和命令序列能够得到相同结果,便于恢复与稳定测试。
技术栈 TypeScript · React · Vite · PixiJS · Three.js · XState · Node.js · WebSocket · Zod · SQLite · PostgreSQL · Docker
对局包含座次确认、起始道具、等待行动、事件选择、道具取舍和游戏结束等阶段。每个阶段只开放明确的命令;客户端用服务端下发的合法命令生成控件和目标列表,最终合法性仍由服务端再次校验。
客户端只表达意图,不上传骰子点数、抽卡结果或最终位置。Authority 统一校验玩家身份、Revision、当前行动者与阶段,再调用规则引擎产生随机结果和结算,避免客户端作弊或不同实现造成状态分叉。
相同 commandId 和载荷重试时返回原结果,不重复执行;相同 ID 携带不同载荷会被拒绝。
expectedRevision 表示命令基于哪个权威版本,旧命令会被拒绝并触发客户端重新同步。
队列确定服务端写入顺序,Revision 判断客户端上下文是否过期,两者处理不同层面的并发问题。
网络更新到达后,客户端立即保存最新权威快照,用于 Revision 和下一条命令;画面则通过表现队列逐步追赶。React 管理大厅、HUD、卡牌和弹窗,PixiJS 负责棋盘与棋子,Three.js 在透明画布中呈现 3D 骰子,XState 编排表现阶段。
rolling、routePreview、targetEmphasis、routeFade、moving 等阶段按序推进,避免不同动画相互抢占。
动画异常、页面失焦或超时后可直接同步至最新权威快照,再继续消费后续更新,不拖慢其他玩家。
客户端以 snapshot revision 为顺序依据,只接收更高版本;完整重连快照会清空旧表现队列并重建棋盘。
React 只管理 PixiJS 容器的创建与销毁,高频补间、镜头和 ticker 更新留在场景树中执行。
联机正确性不仅是把消息广播出去,还包括进程重启、临时断网、多标签页和多实例切换时如何维持房间身份与单写者约束。
玩家凭证保存在标签页 sessionStorage,服务端只持久化 SHA-256 摘要;重连后发送最新完整投影,而非补播旧动画。
成员记录有效连接数,只有最后一条连接断开才进入宽限期,关闭单个标签页不会误判玩家离线。
服务端按查看者裁剪道具、私有候选、私有事件、合法命令和随机状态,敏感信息不会先发到浏览器再隐藏。
单实例部署使用 SQLite WAL 保存房间、Authority 检查点和幂等缓存,支持进程重启后的状态恢复。
多实例模式使用 owner lease、房间路由和单调递增 fencing token,让数据库拒绝旧 owner 的延迟写入。
新检查点保存成功后才对外发布,确保客户端可见状态不会领先于服务器可恢复状态。
管理平台覆盖地图、事件和皮肤的编辑、校验、预览、审核、发布与回滚。发布版本不可变,新房间使用当前版本,进行中的房间继续使用开局时锁定的内容、地图和规则版本,避免运营调整改变存量对局的含义。
后台地图预览复用玩家端棋盘渲染器,让坐标、标记和路线语义与正式运行时保持一致。
前端守卫改善操作体验,内容服务器仍对每个受保护接口校验会话与角色,发布和回滚无法绕过页面直接调用。
AI 用于仓库检索、影响范围分析、方案比较、局部实现、测试补充和文档同步。我负责需求边界、领域模型、包依赖、服务端信任模型、架构取舍与最终验收,让协作建立在可审查的上下文和明确责任上。
测试按责任边界展开,而不是只依赖最终页面回归。规则、协议、房间服务、客户端组件和跨浏览器联机流程分别验证各自不变量,失败时回到规格判断是实现回归还是测试假设已经过期。
覆盖碰撞、终点、道具、固定随机种子、Schema 往返、命令幂等、过期 Revision 和快照恢复。
验证房主权限、准备与开局、持久化、进程重启恢复、owner lease 和房间单写者约束。
验证合法操作、事件选择、表现队列、重复或乱序更新,以及动画异常后的权威状态恢复。
使用 Playwright 覆盖双客户端建房、加入、准备、开局和刷新恢复,并关注不同浏览器与延迟链路。