应用市场游戏开发
游戏 SDK 参考
@caputchin/game-sdk 是一个游戏作者对着写的那个契约:一个 register 助手、一个仅推送的 Bridge、逐回合的 GameContext,以及清单预设块的 TypeScript 类型。它和面向用户的组件分开发布,于是游戏绝不传递性地捆绑组件运行时。第一方游戏用这同一个公开 API;没有私有契约。
一个有引导的构建,见 构建一个应用市场游戏。声明这个 SDK 所暴露预设的那个清单,见 caputchin.json 清单。
register(factory)
那单一的注册入口点。传你的游戏工厂;你 不 传清单(服务器在索引时读 caputchin.json,并把解析出的预设作为工厂的上下文送下来)。注册两次会记一条控制台警告,且最后一次写入获胜;没有平台强制。
register(factory: GameFactory): void游戏工厂
type GameFactory = (
container: HTMLElement,
bridge: Bridge,
ctx?: GameContext,
) => (() => void) | void| 参数 | 含义 |
|---|---|
container | 游戏沙箱化 iframe 里面的一个元素。在这里渲染。样式天然被限定范围,iframe 是它自己的文档。 |
bridge | 通往宿主的仅推送通道(见 bridge)。游戏向上发出;它不订阅。工厂被调用就是那个开始信号。 |
ctx | 逐回合的 上下文(种子加上解析出的预设)。在类型里是可选的,因为组件可能在一个已核验会话之外跑一个游戏。 |
| return | 一个可选的清理函数,组件在卸载你的游戏时调用它。 |
bridge
bridge 是仅推送的:游戏向宿主报告事件,而从不监听。它的成员:
| 成员 | 形状 | 作用 |
|---|---|---|
pass | pass(result: { trace: string }): void | 示意这个回合 被通过了,把不透明的 trace 交给宿主。服务器在签发的种子下重跑游戏的 run 来算出那个权威裁定,所以游戏在这里 不 报告一个分数。第一次调用释放被持有的验证并锁定令牌;之后的调用被忽略。 |
error | error(err: { code: string; message?: string }): void | 游戏自己失败了(资源加载、内部异常)。向用户浮现一个 error 事件。区别于一次玩家落败,后者靠什么都不调用来示意。 |
setSize | setSize(width: number, height: number): void | 明确地把 iframe 调整为适配内容。在第一次绘制之后调用;组件也会自动量测游戏的第一个子元素,所以大多数游戏从不需要这个。 |
layout | readonly layout: 'inline' | 'modal' | 'fullscreen' | null | 游戏所跑在的那个解析出的呈现方式,或在未知时为 null。 |
有意没有 complete、没有 start 监听器、没有 unmount 方法(改为返回一个清理函数)、也没有沉默之外的失败信号。
上下文
interface GameContext {
seed: Seed | null
locale: ResolvedLocale | null
skin: ResolvedSkin | null
config: ResolvedConfig | null
}| 字段 | 含义 |
|---|---|
seed | 逐回合的回放种子(来自回放契约的一个 Seed)。从它给所有游戏随机性播种。当游戏在一个已核验会话之外跑时为 null。 |
locale | 解析出的语言对象:_lang(BCP-47)、_direction,加上你扁平化的文本键。如果你的清单不交付 locales 块则为 null。 |
skin | 解析出的皮肤:_theme 加上你扁平化的颜色/资源键,资源 URL 已是绝对的。_theme 始终是皮肤为之解析的那个具体模式,light 或 dark(绝不是 any),所以一个与主题无关的预设报告访客的实际模式。如果没有 skins 块则为 null。 |
config | 解析出的配置:你扁平化的带类型标量。如果没有 configurations 块则为 null。 |
当对应的清单块缺失时每一个都是 null,所以总是提供一个内置回退。
预设类型
SDK 导出用于撰写 caputchin.json(以及拆分的 .caputchin/ 文件)并带类型检查的 TypeScript 类型。这些镜像 清单 块:
| 类型 | 描述 |
|---|---|
GameManifest | 整个 caputchin.json。作者加索引器的真相来源;绝不在浏览器里读。 |
LocalePreset / ResolvedLocale | 一个声明的 locale 预设 / 游戏收到的那个解析出的对象。 |
SkinPreset / ResolvedSkin / SkinSchemaEntry / SkinValueType | 皮肤预设、解析出的皮肤,以及逐键的类型模式。 |
ConfigPreset / ResolvedConfig / ConfigSchemaEntry / ConfigValueType | 配置预设、解析出的配置,以及逐键的类型模式。 |
LocalesFile / SkinsFile / ConfigurationsFile | 每个 .caputchin/<axis>.json 拆分文件的顶层对象。 |
MarketplaceMetadata / PreferredPresentation | marketplace 块和那个 preferred 占位提示。 |
用一个 satisfies 导入撰写一个拆分文件,好让编译器检查它:
import type { LocalesFile } from "@caputchin/game-sdk";
export default { schema: { /* ... */ }, presets: { /* ... */ } } satisfies LocalesFile;什么被有意省去
- 没有
sessionId或平台标识符到达游戏。 - 没有
start/pause/resume生命周期钩子;工厂调用就是那个开始。 - 没有
maxScore或平台分数范围;裁定的分数就是你的run返回什么。
这个契约有意做得极小,好让它跨多年的目录增长保持稳定。
另见
- 构建一个应用市场游戏:用这个面的那篇教程。
- 回放契约:bridge 和上下文所指的那个
Seed、轨迹和裁定。 - caputchin.json 清单:声明上下文所解析的那些预设。