应用市场游戏开发
引擎套件 engine-kit(可选)
这一页是可选的。 这里的一切只是 产出 一个合规 run 的一种便利方式;你可以完全忽略这个套件,交付一个你手写的光秃秃的 run。当你宁愿写普通的游戏逻辑、并让确定性、回放循环和轨迹编码替你处理好时,再去用 @caputchin/engine-kit。
这个套件重新导出整个 回放契约 面,所以套件用户有单一一个导入点。
npm install @caputchin/engine-kit这个点子:写一个 reducer,得一个 run
这个套件的核心动作,是让你把你的游戏表达为一个 纯 reducer:一个接受当前状态和一个 tick 的输入、返回下一个状态的函数。从那个 reducer 加上确定性原语,套件的 toRun 适配器产出一个按构造就合规的 run(seed, config, trace)。
import { defineEngine, toRun, cap } from "@caputchin/engine-kit";
const engine = defineEngine({
setup(seed) {
const rng = cap.rng(seed); // deterministic, seeded RNG
return { score: 0, targets: spawn(rng), rng };
},
tick(state, input) {
// pure: same (state, input) always yields the same next state
return applyInput(state, input);
},
result(state) {
return { passed: state.score >= 3, score: state.score, durationMs: state.elapsed };
},
});
export const run = toRun(engine); // a conforming RunFn确定性原语
这个套件给你那两样最常打破跨运行时确定性的东西,两者都可播种且可重现:
cap.rng(seed)(以及cap.rngFromState):一个可播种的 PRNG。用它来做每一个随机选择,而不是Math.random()。cap.math:跨运行时一致的确定性超越函数(sin、cos、……),而不是可能不一致的平台Math那些。
可选垫片
applyShim():中和那些非确定性的全局量(墙上时钟、Math.random),好让一次意外的调用在开发中大声失败,而不是在回放时默不作声地分叉。applyDomShim():给框架路径用的一个极简 headless DOM,好让一个碰一小片 DOM 面的 reducer 在无 DOM 的隔离体里仍能回放。
在发布之前在本地跑它
这个套件的 replay 测试床以服务器将要采用的同样方式把一条轨迹跑过你的引擎,而 selfCheck 跑一批用例并在你发布 之前 报告任何非确定性:
import { selfCheck } from "@caputchin/engine-kit";
const report = selfCheck(engine, { cases: myCases });
if (!report.ok) console.error(report.violations);一次干净的本地 selfCheck 是应用市场发布自检会通过的最好预测(它是同一个确定性标准)。这个套件还交付一个 CLI,用于从 package.json 脚本或 CI 里跑这个。
轨迹编码
encodeTrace / decodeTrace 给你一个紧凑的、带版本的轨迹格式,好让你实时游戏发出的那条输入流恰好就是你的 run 在回放时解码的那条。在两侧都用它们,让两者保持锁步。
何时跳过这个套件
当你已经有确定性逻辑(一个定点模拟、一个为规范浮点编译的 WASM 模块)、或者当你的游戏简单到手写 run 不费吹灰之力时,就跳过它。平台从不知道也不在乎这个套件有没有产出你的 run;它只加载并回放这个契约。
另见
- 回放契约:这个套件产出的那个
run/ seed / verdict。 - 构建一个应用市场游戏:这个套件能支撑其逻辑的那个游戏。
- caputchin.json 清单:把产出的
run作为工件交付。