6.3 平台输入差异适配
把浏览器与小游戏宿主的输入差异摆成一张矩阵:事件 API 名、多点触控投递方式、取消事件、安全区、坐标原点五个维度逐平台对比,用 S 层脚本统计差异条目并估算适配工时,讲清权重模型与复用系数如何把「每家平台都要改一遍」压成一次性抽象层成本。
category
把浏览器与小游戏宿主的输入差异摆成一张矩阵:事件 API 名、多点触控投递方式、取消事件、安全区、坐标原点五个维度逐平台对比,用 S 层脚本统计差异条目并估算适配工时,讲清权重模型与复用系数如何把「每家平台都要改一遍」压成一次性抽象层成本。
把「跟不跟手」从主观感受变成可调参数:用整数跟随模型(跟随系数、死区、最小步、速度上限、松手吸附)实现拖拽手感,参数全为像素整数、无浮点,再用单文件 HTML 原型配 Playwright 无头真跑一次鼠标拖拽,断言落点、吸附与手势并截图存档。
把不同平台的触摸事件统一归一化成 {x,y,phase} 样本序列,再用手势状态机识别点击、长按、拖拽与滑动:给出可跑的 TypeScript 输入内核与 14 项单元测试,讲清时间阈值与位移阈值的判定顺序,以及物理像素到逻辑坐标的整数缩放与原点翻转。
暂停容易,恢复难:切后台十分钟再回来,若把十分钟按固定步长如实补回,一帧要跑三万七千步,设备直接卡死。本节用封顶补偿把离线时长折算成有上限的固定步数,并把整条「暂停 → 切后台 → 恢复」路径放进单文件 HTML 原型,用 Playwright 无头断言加截图验收。
一款小游戏不止一个「世界」:菜单、对局、结算、弹窗各自是一个场景。本节用场景栈 + 生命周期状态机管理它们——进入、暂停、恢复、退出四个动作,按动作而非目标态判定合法迁移,非法迁移一律拒绝且不改动任何状态,并配可跑的 TS 内核与断言测试。
固定步长主循环是《合成小岛》可复现的地基:用累加器把可变帧率折算成整数固定步,输入按 tick 采样、随机按步推进,同一 seed 与输入序列在 16ms / 32ms / 不规则帧率下终局逐位一致;配可跑的 TS 内核、断言测试与跨语言对拍。
小游戏改一张图、加一个关卡,用户要重下多少,取决于热更新的版本模型。本节用 TypeScript 写一个差异计算内核:版本号按整数分段比较,清单按路径与哈希分类,再据此在「差异下载」与「整包更新」之间做决策,让每次更新要下多少变成可复算的数字。
音频常常是包体里仅次于图集的一块,却最容易被「随便导出个 MP3」糊弄过去。本节把音频格式折算成可算的字节:码率、容器开销、片段时长一起进公式,再用一段脚本选出每个片段该用的格式,并给出「什么时长用什么格式」的判据,算清短音效与长片段各自该走哪条路。
图集与纹理是包体里最重的一块:它既是批处理能否发生的前提,也决定了运行时的显存占用。本节用 Pillow 真实生成精灵、跑一遍自写的货架装箱,把打包率、PNG 字节与显存占用都算成确定数字,并给出图集尺寸与纹理格式的取舍判据,让资源预算从手感变成可复算的数字。
把「合批到底省多少」算成可对照的整数模型:一帧耗时拆成固定开销、每批状态切换成本与每精灵顶点成本三项,比较未合批/按纹理合批/图集三种策略的批次数与帧耗时,产 CSV 与纯 Python SVG,再用 B 层扫单批上限看批大小敏感性在哪里趋于平台。
把设计分辨率到各种真实屏幕的映射拆成可算的整数像素:用千分比整数表达 fit/fill 缩放,算出内容区与居中偏移,再与刘海/圆角/指示条的安全区求交,四台设备逐档断言,并给出可切换设备与缩放模式的单文件 HTML 原型与 Playwright 无头验收脚本。
把「小游戏没有 DOM」这件平台约束落成可运行的工程抽象:用一份不依赖任何引擎的最小 2D 绘制内核,把清屏/矩形/文本三类指令发到两个宿主——Node 里的整数像素缓冲与浏览器里的真实 Canvas,逐像素断言两边画出的非背景像素数一致、指纹稳定,并附可打开的单文件 HTML 原型与无头验证脚本。
分包方案定下来之后,还要回答一个问题:这份方案在真实构建里占多少体积、离上限有多近。本节把构建产物清单按包与类型聚合,算出各包占比并画出堆叠图,再用一段 B 层基准把每项体积按可播种的整数抖动跑 400 轮,看「main 越线」出现的概率,让余量从感觉变成数字。
分包不是把文件挪个位置,而是把「玩家什么时候会用到它」翻译成加载顺序。本节给出一份带依赖与体积的资源清单,再用一段 P 层 TypeScript 内核按「依赖闭包 + 体积预算」自动规划 main 与分包,并用四条不变量断言规划结果,让分包线由约束反推而不是拍脑袋。
引擎选型定下来之后,第一件事不是写玩法,而是把工程骨架的模块边界钉死。本节先把《合成小岛》的十个模块写成一份带层级与依赖方向的配置表,再用一段 P 层 TypeScript 内核做拓扑排序、无环校验与「依赖只能向下」的检查,让模块边界不靠口头约定,而靠一条跑得起来的断言守住。
把前面各节散落的检查(配置合法性、必需文件、体积预算、禁浮点、命名规范、随机数可播种)串成一条发布前流水线。真实 CI 平台的执行不可复现,本节给的是同一套检查逻辑的本地可运行版本:读一份 D 层流水线定义,在本地逐条真跑,产出 JSON、CSV 与报告文本。
配置表是小游戏里的唯一真源:关卡数值、合成链、掉落权重都写在 JSON 里,错的不只是一个文件,而是所有读它的仿真、内核与原型。本节先给出一份带字段、类型、取值范围与必填约束的 D 层 schema,再用一段 P 层校验器把类型、范围、引用完整性、禁浮点与唯一键一次查全,返回全部错误而非首个。
第 2 章把模块边界写成了一张可校验的配置表,但声明会漂移:有人新增一条跨模块 import,表还写着合规。本节把校验对象从声明换成真实源码,用一段 P 层 TypeScript 解析各模块的 import 声明,断言依赖不越界、无环,并顺带扫描 enum、namespace、参数属性、装饰器这些不可擦除构造。
把「在哪些设备上测、每台测什么、风险怎么加权」摆成一张可统计的真机兼容测试矩阵:设备档位、屏幕、内存、输入方式、已知风险与必测项写进一份配置,再用仿真统计屏幕/输入/内存三维覆盖度并按风险等级加权算出必测负担,避免「只在旗舰机上测过」的假安全感。
把小游戏的端到端链路变成可自动跑的断言:用带整数毫秒时间戳的输入序列做录制,按固定步长推进时钟回放,Node 侧与浏览器侧读同一份录制、跑同一段逻辑,断言终局摘要逐位相同;再用 Playwright 无头在单文件 HTML 里回放并对照两侧摘要。