
boardgame.io 回合制游戏引擎完全指南状态管理、多人联网与 AI 实战【免费下载链接】boardgame.ioState Management and Multiplayer Networking for Turn-Based Games项目地址: https://gitcode.com/gh_mirrors/bo/boardgame.ioboardgame.io 是一个用 JavaScript/TypeScript 编写回合制游戏的引擎你只需写出状态如何因某个动作而改变的纯函数框架便会自动将其转换为包含在线多人对战能力的可玩游戏全程无需手写任何网络通信或存储代码。本指南以仓库 README.md 为主线结合 docs/documentation 下的官方文档与 src 目录的源码实现系统讲解其核心概念、功能特性、安装运行方式以及从单机原型到多人服务器的完整实战路径。一、项目定位与核心设计理念boardgame.io is an engine for creating turn-based games using JavaScript.这是项目自述的定位一个面向回合制游戏board games、card games、tabletop games 等的专用引擎。与通用游戏引擎不同它把精力聚焦在回合、玩家、阶段这类回合制游戏的公共抽象上让你用最小的代码量完成从规则定义到可玩产品的跨越。其核心设计理念可以概括为三句话用纯函数描述规则写一个描述某一步棋后游戏状态如何变化的函数剩下的交给框架状态自动同步G游戏状态与ctx游戏元数据在客户端、服务器与存储层之间被无缝管理开箱即用的网络能力自动获得在线多人、实时同步、日志回放等能力without requiring you to write a single line of networking or storage code。二、快速上手安装与运行仓库示例作为依赖安装在你的 Node 项目中安装npm install boardgame.io从 package.json 可以看到当前仓库版本为0.50.2要求node 10.0、npm 6.0并提供了多种模块入口mainCommonJS、moduleESM、unpkg浏览器直接引用的压缩版以及typesTypeScript 类型声明同时通过 subpackages.js 生成boardgame.io/client、boardgame.io/core、boardgame.io/react、boardgame.io/server、boardgame.io/ai、boardgame.io/multiplayer等子路径入口。运行本仓库自带的示例克隆本仓库后在仓库根目录执行npm install npm startnpm start实际由两个脚本并行组成见 package.json 的 scripts 字段dev:server用 nodemon 热重载examples/react-web/server.js与dev:client启动开发客户端。仓库自带的示例都位于 examples 目录examples/react-webReact Web 示例包含井字棋单机/多人/观战/带 bot、随机性、秘密状态、撤销、大厅、模拟器等子示例examples/react-nativeReact Native 移动端示例examples/snippets配合官方文档嵌入的小型示例含 Svelte 示例。其他常用开发命令还包括npm testJest 测试运行前会自动执行 ESLint、npm run test:coverage、npm run docs用 docsify 在本地启动文档站、npm run buildRollup 构建、npm run tsTypeScript 类型检查、npm run benchmark性能基准测试。三、核心概念G、ctx、Moves、Events、Phase、Turn、Stage了解引擎的第一站是官方 Concepts 文档它把一切抽象为 7 个核心概念理解它们就掌握了 90% 的引擎心智模型。1. StateG与ctx游戏状态由两个对象共同表达{ // 游戏状态由你管理 G: {}, // 只读元数据由框架管理 ctx: { turn: 0, currentPlayer: 0, numPlayers: 2, } }G完全归你所有存放棋盘、手牌、分数等业务数据ctx由框架维护记录当前回合数、当前玩家、玩家数量等元数据还包含阶段phase、回合顺序turn order、活跃玩家activePlayers、游戏结束标志gameover等字段。官方文档特别强调两点约束ctx是可增量采用的如果你愿意可以完全在G中手动管理一切状态G必须可 JSON 序列化因为状态会在客户端与服务器之间传输G中不能出现类实例或函数。2. Moves玩家的动作Moves 是告诉框架当某个动作发生时如何改变G的函数。它不能依赖外部状态也不能有副作用修改G除外。至于不可变性immutability如何保证见 Immutability 指南——引擎内部借助 immer 提供便捷的可写式更新体验。moves: { drawCard: ({ G, ctx }) { const card G.deck.pop(); G.hand.push(card); }, // ... }从源码 src/core/game.ts 的ProcessGameConfig可以看到 move 的执行细节processMove会从flow.getMove取到对应的 move 函数用plugins.FnWrap包裹后以(context, ...args)的形式调用其中context包含G、ctx、playerID以及插件注入的 API。客户端派发 move 的方式取决于视图层// Plain JS从 client 实例上取 client.moves.drawCard(); // React从组件的 props 上取 props.moves.drawCard();3. Events框架提供的事件Events 与 Moves 类似但操作对象是ctx而非G——典型用途是结束回合endTurn、切换阶段endPhase等流程推进。派发方式也一致// Plain JS client.events.endTurn(); // React props.events.endTurn();4. Phase / Turn / Stage三层时间结构Phase阶段游戏中覆盖全局配置的一段时期可以定义不同的 move 集合与回合顺序游戏可在阶段间切换回合发生在阶段内部。详见 PhasesTurn回合与单个玩家绑定的一段时期通常由该玩家的一个或多个 move 组成然后轮转给下一位玩家。也可以让其他玩家在你的回合内行动。详见 Turn OrdersStage子阶段类似阶段但发生在回合内部作用于单个玩家而非整个游戏一个回合可细分为多个 stage且不同玩家可以同时处于不同的 stage。详见 Stages。这三层结构让游戏整体流程 → 单个玩家回合 → 回合内的细分行动窗口这一复杂的回合制游戏时序变得完全可配置。四、功能特性深度解析README.md 罗列了引擎的九大特性下面结合仓库源码逐一展开。1. State Management状态管理游戏状态在客户端、服务器与存储层之间被自动无缝管理。ctx由框架维护客户端与服务器都运行同一套 reducer 逻辑。单机模式下客户端直接通过InitializeGame初始化状态并本地运行见 src/client/client.ts 构造函数中if (!multiplayer) this.initialState InitializeGame(...)的分支。2. Multiplayer多人联网游戏状态跨客户端实时同步。其架构在 Multiplayer 文档中有精辟阐述**客户端Client与主控Master**分工——单机模式下Client自己就是权威状态源多人模式下客户端不再充当权威存储而是把 move/event 交给game master计算下一状态再由 master 广播给所有客户端但客户端因为知道游戏规则会并行本地预演乐观更新optimistic update以提供无延迟体验一旦客户端算错最终会被 master 覆盖保证单一权威源。若 move 访问了客户端不可见的秘密状态则可能需要为该 move 关闭乐观更新见 Secret State。引擎提供两种开箱即用的多人模式Local本地主控import { Local } from boardgame.io/multiplayermaster 完全运行在浏览器内存中适合传屏轮流玩或无需服务器的多人原型测试SocketIOimport { SocketIO } from boardgame.io/multiplayer通过 socket.io 连接远程服务器可配置socketOpts与server格式[http[s]://]hostname[:port]默认当前页面主机。import { Client } from boardgame.io/client; import { Local } from boardgame.io/multiplayer; import { TicTacToe } from ./Game; const client Client({ game: TicTacToe, multiplayer: Local(), playerID: 0, // 多人模式下客户端必须关联某个玩家座位 });多人模式下不带playerID的客户端是旁观者可观看实时状态但不能行动。底层通信实现在 src/client/transportsocketio/local/dummy 三种 transport接收到的sync、update、patch、matchData、chat消息在receiveTransportData中被分派处理见 src/client/client.ts。3. AI自动生成的机器人只需在游戏定义中增加ai节并提供一个enumerate函数返回所有合法 move 的数组框架就会自动生成能玩你这个游戏的 bot。以仓库井字棋示例 examples/react-web/src/tic-tac-toe/game.js 为例ai: { enumerate: (G) { let r []; for (let i 0; i 9; i) { if (G.cells[i] null) { r.push({ move: clickCell, args: [i] }); } } return r; }, },play让 bot 计算并走一步棋调试面板快捷键2simulate让 bot 自己玩完整局快捷键3。从源码看bot 体系在 src/ai抽象基类 src/ai/bot.ts 负责把{ move, args }转换为标准的 makeMove action并内置基于 alea 的可播种随机数src/ai/mcts-bot.ts 实现了MCTS蒙特卡洛树搜索机器人——通过selectUCT 公式选择、expand、playout按playoutDepth随机推演并检查 objectives、backpropagate四步迭代探索博弈树默认每次决策迭代1000 次可配置范围 1–2000并支持通过objectives指定短期收集资源、后期发动战争这类多目标优化。src/ai/ai.ts 提供Step让 bot 走一步与Simulate模拟至终局或最大深度两个高层入口。此外还有 src/ai/random-bot.ts 提供随机机器人实现。4. Game Phases游戏阶段支持每个阶段使用不同的游戏规则与回合顺序。阶段机制在 src/core/flow.ts 中实现配合 docs/documentation/phases.md 使用。5. Lobby大厅与匹配提供玩家匹配与游戏创建能力。其 REST API 由 src/server/api.ts 实现React 大厅组件与创建/登录表单在 src/lobby完整接口见 Lobby API 文档。6. Prototyping原型设计内置调试面板Debug Panel让你在渲染任何 UI 之前就能模拟走子、查看状态、调用事件。单机创建 Client 后start()会自动挂载调试面板debug: false可关闭。调试面板还可配合 AI 进行人机混合操作验证如先手动摆出两个连子再验证 bot 是否会封堵。7. Extendable可扩展插件系统插件机制允许创建新抽象。核心实现在 src/plugins内置插件包括事件events、随机数random基于 alea 的可复现随机、不可变性immer、日志log、玩家player、可序列化校验serializable。插件会在ProcessGameConfig中被校验名称不能含空格并通过plugins.FnWrap包装到每次 move 调用中。详见 Plugins。8. View-layer Agnostic视图层无关既可用原生 JS 客户端boardgame.io/client也有 Reactboardgame.io/react见 src/client/react.tsx与 React Nativeboardgame.io/react-native绑定。示例目录中 examples/react-web 与 examples/react-native 展示了两种视图层的完整用法。9. Logs游戏日志与时间旅行自动记录游戏日志支持时间旅行——回看任意历史时刻的棋盘状态。客户端通过LogMiddleware见 src/client/client.ts把每次 move/event 产生的deltalog增量追加到this.log并提供undo/redo撤销重做服务端主控同样支持见 src/master/master.ts。详见 Undo 指南。五、从零编写一个游戏井字棋实战官方 Tutorial 以井字棋为例给出了 Plain JSParcel与 Reactcreate-react-app两条完整路径这里提炼其核心步骤。第 1 步定义游戏创建src/Game.js核心只有setup初始化G与moves改变Gexport const TicTacToe { setup: () ({ cells: Array(9).fill(null) }), moves: { clickCell: ({ G, playerID }, id) { G.cells[id] playerID; }, }, };move 函数的第一个参数是包含G、ctx、playerID的对象其后可跟任意自定义参数这里是格子的id。第 2 步创建客户端Plain JS 方式src/App.js 的同构实现import { Client } from boardgame.io/client; import { TicTacToe } from ./Game; class TicTacToeClient { constructor() { this.client Client({ game: TicTacToe }); this.client.start(); } }React 方式import { Client } from boardgame.io/react; import { TicTacToe } from ./Game; const App Client({ game: TicTacToe }); export default App;此时虽然还没写任何 UI但调试面板已经可以玩完整局游戏点击clickCell、输入 0–8 的数字回车即可落子点击endTurn换人——这就是Prototyping特性的体现。第 3 步改进游戏规则校验非法 move导入特殊常量INVALID_MOVE并返回它框架便拒绝该动作import { INVALID_MOVE } from boardgame.io/core; clickCell: ({ G, playerID }, id) { if (G.cells[id] ! null) { return INVALID_MOVE; } G.cells[id] playerID; }自动管理回合井字棋每步应自动换人用turn配置turn: { minMoves: 1, // 玩家必须走棋不能直接 endTurn maxMoves: 1, // 走完一步自动结束回合 },胜利条件用endIf在每次状态更新时检查终局返回值会出现在ctx.gameoverendIf: ({ G, ctx }) { if (IsVictory(G.cells)) return { winner: ctx.currentPlayer }; if (IsDraw(G.cells)) return { draw: true }; },上述逻辑与仓库 examples/react-web/src/tic-tac-toe/game.js 中的完整实现完全一致。第 4 步渲染棋盘Plain JS手动构建 DOM 表格用client.moves.clickCell(id)派发 move用client.subscribe(state this.update(state))订阅状态变化刷新界面——这是 vanilla 客户端的两个关键 API。React创建src/Board.js函数组件从 props 解构ctx, G, movesexport function TicTacToeBoard({ ctx, G, moves }) { const onClick (id) moves.clickCell(id); // ...渲染 3x3 表格点击空按钮触发 onClick(id) }再把它作为board选项传入 Clientconst App Client({ game: TicTacToe, board: TicTacToeBoard, });仓库中完整的 React 棋盘实现见 examples/react-web/src/tic-tac-toe/board.js它展示了G、ctx、moves、playerID、isActive、isMultiplayer、isConnected、isPreview等全部 props 的用法包括断线提示与胜负展示。六、Client API 速查官方 Client API 文档 完整列出了客户端 API这里整理为速查表。构造选项选项说明game游戏定义对象必填numPlayers玩家数量multiplayerfalse默认、SocketIO()或Local()也可传自定义 transport 实现matchID要连接的比赛 ID多人playerID客户端关联的玩家多人不传则为旁观者credentials玩家认证凭据多人debug设为false关闭调试面板enhancer注入 Redux store enhancer可用于调试或拦截动作实例属性moves派发游戏 move 的函数集合函数名与游戏定义中的 move 名一致events派发endTurn、endPhase等游戏事件log游戏日志matchID/playerID/credentials当前关联的标识与凭据matchData通过 Lobby API 加入比赛的玩家数组形如[{ id: 0, name: Alice }, { id: 1, name: Bob, isConnected: true }]chatMessages收到的聊天消息数组每条含id、sender、payload字段。实例方法方法说明start()启动客户端连接 transport、挂载调试面板stop()停止客户端断开连接、卸载调试面板getState()获取当前状态未与远程主控同步前返回null否则返回含G、ctx、plugins、log、isActive、isConnected的对象subscribe(cb)每次状态变化调用回调返回退订函数reset()/undo()/redo()重置 / 撤销 / 重做sendChatMessage(msg)发送聊天消息字符串或带元数据的对象updateMatchID(id)/updatePlayerID(id)/updateCredentials(c)运行时更新关联的 matchID、playerID、credentialsReact 版的Client({...})返回一个 React 组件除上述选项外还支持board棋盘组件、loading同步前的加载组件且matchID、playerID、credentials可作为组件 props 传入。棋盘组件收到的 props 除了G、ctx、moves、events外还有isActive、isMultiplayer、isConnected等标志位。七、多人联机搭建游戏服务器当客户端启用多人模式后需要一台服务器作为权威主控。官方 Server API 文档 说明Server创建一个基于Koa的 app跟踪各客户端连接的游戏状态并向所有连接同一局的浏览器实时广播更新同时托管用于创建/加入游戏的Lobby REST API默认同端口也可配置到独立端口。最小服务器示例const { Server, Origins } require(boardgame.io/server); const server Server({ // 提供你的游戏定义可多个 games: [game1, game2], // 数据库存储类默认内存实现 db: new DbConnector(), origins: [ // 允许你的游戏站点访问 https://www.mygame.domain, // 允许 localhost生产环境 NODE_ENVproduction 时除外 Origins.LOCALHOST_IN_DEVELOPMENT, ], }); server.run(8000);配置项说明选项说明games必填游戏实现数组每个符合 Game APIorigins必填CORS 允许的源支持字符串或正则db数据库连接器默认内存实现可选 Flatfile、LocalStorage 等见 Storage 文档 与 src/server/dbtransport传输实现默认 socket.iouuid生成游戏 ID 与玩家凭据的函数默认 nanoidgenerateCredentials生成玩家凭据并存入元数据的函数可读 Koactx定制authenticateCredentials校验玩家 move 凭据的函数apiOriginsLobby API 的允许源默认同origins返回对象Server(...)返回包含run(portOrConfig, callback)、kill({apiServer, appServer})、appKoa app、db、routerKoa Router的对象。run也支持回调形式server.run(8000, () console.log(server running...))以及通过lobbyConfig{ apiPort, apiCallback }把 Lobby API 放到独立端口。进阶用法HTTPS传入https: { cert, key }读取证书文件即可启用 TLS自定义认证generateCredentials从请求头解码 token 生成凭据authenticateCredentials校验 move 携带的凭据与元数据中存储的用户 ID 是否匹配仓库 examples/react-web/src/tic-tac-toe/authenticated.js 有完整示例扩展服务器利用返回的router添加自定义路由server.router.get(/custom-endpoint, ...)或为既有路由如/games/:name/create注入中间件从而定制创建游戏时的numPlayers、setupData等逻辑。八、类型安全与测试TypeScript仓库本身以 TS 编写核心src 下.ts文件boardgame.io包自带类型声明官方 TypeScript 指南 说明如何为 React 棋盘组件标注BoardProps类型。测试仓库对每个模块都配有单元测试例如 src/core/game.test.ts、src/client/client.test.ts、src/ai/ai.test.ts、src/server/api.test.ts测试框架为 Jest配置见 package.json 的jest字段。官方 Testing 指南 与 src/testing如MockRandom可帮助你为自己的游戏编写测试。九、文档、版本与贡献变更日志见 docs/documentation/CHANGELOG.md完整文档仓库 docs/documentation 目录内含概念、教程、多人、阶段、回合顺序、插件、随机数、存储、部署、调试、类型脚本等全套指南可通过npm run docs本地阅读路线图见 roadmap.md贡献欢迎各类贡献参与前请阅读 CONTRIBUTING.md含 VS Code dev container 说明与 CODE_OF_CONDUCT.md协议MIT见 LICENSE。结语从写纯函数描述规则到自动获得多人联网boardgame.io 把回合制游戏开发中最繁琐的状态同步、网络传输与存储问题全部封装进了引擎内部。沿着本文的路径——先用调试面板快速验证规则再通过Local()体验多人协作最后用Server部署真正的在线对战——你可以用极少的样板代码把任何回合制桌游创意变成可玩的在线游戏。进一步深入时建议按顺序精读官方 Tutorial、Concepts、Multiplayer 三篇文档并结合 src 源码对照学习各模块的实现细节。【免费下载链接】boardgame.ioState Management and Multiplayer Networking for Turn-Based Games项目地址: https://gitcode.com/gh_mirrors/bo/boardgame.io创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考