16.3 持续集成与发布流水线
把前面各节散落的检查(配置合法性、必需文件、体积预算、禁浮点、命名规范、随机数可播种)串成一条发布前流水线。真实 CI 平台的执行不可复现,本节给的是同一套检查逻辑的本地可运行版本:读一份 D 层流水线定义,在本地逐条真跑,产出 JSON、CSV 与报告文本。
tag
把前面各节散落的检查(配置合法性、必需文件、体积预算、禁浮点、命名规范、随机数可播种)串成一条发布前流水线。真实 CI 平台的执行不可复现,本节给的是同一套检查逻辑的本地可运行版本:读一份 D 层流水线定义,在本地逐条真跑,产出 JSON、CSV 与报告文本。
配置表是小游戏里的唯一真源:关卡数值、合成链、掉落权重都写在 JSON 里,错的不只是一个文件,而是所有读它的仿真、内核与原型。本节先给出一份带字段、类型、取值范围与必填约束的 D 层 schema,再用一段 P 层校验器把类型、范围、引用完整性、禁浮点与唯一键一次查全,返回全部错误而非首个。
第 2 章把模块边界写成了一张可校验的配置表,但声明会漂移:有人新增一条跨模块 import,表还写着合规。本节把校验对象从声明换成真实源码,用一段 P 层 TypeScript 解析各模块的 import 声明,断言依赖不越界、无环,并顺带扫描 enum、namespace、参数属性、装饰器这些不可擦除构造。
把「在哪些设备上测、每台测什么、风险怎么加权」摆成一张可统计的真机兼容测试矩阵:设备档位、屏幕、内存、输入方式、已知风险与必测项写进一份配置,再用仿真统计屏幕/输入/内存三维覆盖度并按风险等级加权算出必测负担,避免「只在旗舰机上测过」的假安全感。
把小游戏的端到端链路变成可自动跑的断言:用带整数毫秒时间戳的输入序列做录制,按固定步长推进时钟回放,Node 侧与浏览器侧读同一份录制、跑同一段逻辑,断言终局摘要逐位相同;再用 Playwright 无头在单文件 HTML 里回放并对照两侧摘要。
把《合成小岛》最易出错的合成规则收敛成可测的纯函数,用 Node 内置 node --test 写四类断言:边界值(空/上限/越界)、确定性(同 seed 同输入同输出)、异常路径(非法输入被拒绝而非静默通过)、属性不变量(价值守恒、占用单调不增),并讲清哪些该测、哪些不值得测。
把每项优化写成一对整数增量:有的降包体却升内存,有的反过来。枚举所有子集,在包体 × 内存的平面上求帕累托前沿,找出「无法同时再降两者」的那些点,再用 B 基准扰动最不确定的内存增量看前沿怎么变——显式声明这是解析模型而非真机实测,帮你在取舍曲线上选点。
把一次运行拆成稳定帧与长帧两种:长帧占比极小时,平均帧耗时几乎不动,卡顿感知却直线下滑。用整数模型算出长帧频率、有效帧率与感知评分,再用 B 基准扫长帧频率,看评分在哪一档跌破软底线——全程显式声明这是解析模型而非真机实测,避免被平均值误导。
把冷启动耗时拆成下载 / 解析 / 编译 / 首帧四段可加的整数毫秒模型,比较同一包体在 Wi-Fi、4G、弱网三档下的分布,再用 B 基准扫包体看首屏时间在哪里越过预算——全程显式声明这是解析模型而非真机实测,用来判断该砍下载还是砍解析。
渐进式教学按连续失败次数把提示抬到三档,卡住不动时自动给提示,容错侧再给一个有限深度的撤销栈让误操作原路撤回;P 层内核加单测保证状态迁移,W 层单文件 HTML 原型用 Playwright 无头驱动,断言「连续失败→提示升级」与「误操作→撤销」并截图。
引导漏斗回答的是另一类问题:一万个玩家走到第几步会掉。用可播种 LCG 逐玩家逐步骤推进,每步含跳过、失败重试、直接流失三条分支,再跑两遍做对照——允许可跳过步骤跳过与强制逐步完成的最终完成率差多少,产出 JSON、CSV 与纯 Python SVG。
引导状态机把「教玩家认识玩法」变成一串可断言的步骤:每步只认自己的完成事件,未开始、已结束、事件不匹配、不可跳过的步被跳过、第一步没有可回退的步这五种非法迁移一律拒绝且不改状态;再配跳过、回退与幂等重入,用 P 层内核与单测把整条新手路径钉死。
音效与震动是同一个反馈模型的另外两个通道:用一张分级表把「事件 → 音效 → 震动档位 → 是否可关」写死,再用内核处理静音、震动开关、宿主能力探测与同一事件连点的频控,最后用可播种仿真统计一次会话的反馈预算、画出震动分级分布图供策划评估手感。
把「打击感」拆成可量化的三要素:屏幕震动(幅度按几何比衰减、方向交替)、命中停顿帧、缩放脉冲。三者全用整数、无随机,同一权重与同一时刻必得同一结果,最后用单文件 HTML 原型配 Playwright 断言「命中→震动→衰减到静止」的完整数值序列。
把手感拆成可计算的缓动曲线与时间轴:用整数定点实现线性、二次、三次、回弹、弹性五种缓动(进度取千分比、避开浮点),再搭一个支持并行串行、延迟、打断与 onComplete 的时间轴调度器,最后用单文件 HTML 原型配 Playwright 无头推进时间、采样动画值。
把 UI 性能拆成可算的整数:元素按「纹理 + 材质」合并绘制调用,作者顺序里相邻元素键不同就打断合批;给出收益模型脚本、CSV 与 SVG,再用 B 基准扫元素数看 UI 帧占比在哪一档越过预算——同一份配置跑 Python 仿真,数字全来自本机实跑。
把弹窗从「随手 new 一个框」升级成可算的弹窗栈:按层级压栈、同去重键拒绝重复、超时自动关闭、模态遮罩拦截点击穿透、点遮罩只关最上层模态——配可跑内核、单文件 HTML 原型与 Playwright 无头验收,全程整数毫秒、可确定性回放,无需真实时钟。
把 UI 布局拆成可算的整数像素:锚点(左右上下与拉伸)+ 偏移 + 边距递归求每个节点的最终矩形,用层级决定绘制顺序与遮挡,用点命中判断谁在最上面,再用虚拟滚动只实例化可视区间——配可跑内核、单文件 HTML 原型与 Playwright 无头验收。
把微信 / 抖音 / QQ / 百度与浏览器摆成一张五维能力兼容矩阵:登录、支付、广告形态、分享、云存档逐平台对比,每个平台再配一份「已知差异」清单,并用可跑的 S 层脚本统计差异条目数、按复用系数估算边际适配工时与总成本,并给出差异维度分布与三个可执行结论。
把同一份会话逻辑分别注入 Node mock 宿主与浏览器宿主,用同一组输入序列驱动,断言两侧终局摘要逐位相同。给出可跑的 session.ts、单测、浏览器宿主构建脚本与 Playwright 无头验收,正文给出两侧真实摘要值与 ok/fail/cancel 三态分布。