npm.io
0.3.2 • Published 1 week ago

@jogabox/game-sdk

Licence
MIT
Version
0.3.2
Deps
0
Size
165 kB
Vulns
0
Weekly
203

@jogabox/game-sdk

静态 HTML5 游戏接入 jogabox 大厅(PWA / Telegram Mini App)。 游戏在大厅的 iframe 里运行,SDK 经 postMessage 与大厅通信:生命周期、激励视频、云存档、遥测。 大厅是权威方,游戏不能自己发积分——奖励由服务端校验后入账,游戏只读回执。

推荐用 npm + 打包器(Vite),不要用 <script> CDN 动态引入。

SDK v2 升级提示:为了进入 Games 关卡漏斗、教程漏斗、进度快照、性能与错误分析,开发者需要升级到最新版 @jogabox/game-sdk,并优先使用 levelStart/levelComplete/levelFailroundStart/roundEndtutorialStepprogressUpdategameErrorperformance 等 typed API。旧 track() 仍兼容,但只作为自定义事件。


1. 安装

npm i @jogabox/game-sdk@0.3.2

2. 用法(Vite 工程)

src/main.ts:

import { createClient } from '@jogabox/game-sdk/client'

const jogabox = createClient()

async function boot() {
  const ctx = await jogabox.init()      // { account_id, tenant_id, game_ref, locale, brand, channel }
  jogabox.loadingFinished()             // 资源就绪、进入可玩
  jogabox.gameplayStart()               // 开始游玩(暂停时配对调用 gameplayStop)

  // —— 你的游戏逻辑 ——
  // 看广告得奖励(服务端发放, 游戏只读 granted/余额):
  // const r = await jogabox.rewardedBreak({ placement: 'level_end' })
  // confirmed_balance 是入账后的权威余额;points 只用于 "+N" 动效
  // if (r.granted) updateBalance(r.confirmed_balance)
  // 云存档(跨设备):
  // await jogabox.save('progress', { level: 5 })
  // const { value } = await jogabox.load('progress')
}
boot()

vite.config.ts(关键:base: './' 让资源用相对路径,因为游戏托管在版本化子路径下):

import { defineConfig } from 'vite'
export default defineConfig({ base: './', build: { outDir: 'dist' } })

不想从零搭?用官方模板 templates/game-vite/(含上面所有配置),复制后改 src/main.ts 即可。

3. API

方法 说明 返回
init() 握手取上下文;无大厅父窗口时自动返回 standalone mock context { account_id, tenant_id, game_ref, locale, brand, channel, config, autostart }
getContext() 同步取已缓存上下文 同上 / null
shouldAutostart() 大厅是否要"进入即开局"(默认 true) boolean
进入即开局(autostart)—— 必做

大厅是奖励大厅,玩家点游戏就是要马上玩不要展示菜单/空棋盘/需要再点 "New/Start" 的中间态。 init() 后调用 jogabox.shouldAutostart(),为真就立刻开一局;New/Restart 只作手动重开。

const ctx = await jogabox.init()
jogabox.loadingFinished()
if (jogabox.shouldAutostart()) startNewRound()   // ← 直接开局,别停在空盘
jogabox.gameplayStart()

旧版 SDK 无 shouldAutostart() 时:把 ctx.autostart !== false 当作 true 处理即可(等价)。 | loadingProgress(0..1) / loadingFinished() | 加载进度 / 进入可玩 | — | | gameplayStart() / gameplayStop() | 游玩生命周期(驱动广告频控+留存) | — | | rewardedBreak({ placement }) | 看视频得奖励(大厅放广告→完播校验→入账) | { granted, points, confirmed_balance } | | commercialBreak() | 插屏(自然停顿;是否真出由大厅频控) | { shown } | | save(key, value) / load(key) | 云存档(跨设备同步) | { ok } / { value } | | setScore(board, score) | 排行榜 | — | | track(event, props) | 自定义遥测 → 分析 | — | | roundStart/roundEnd | 标准局内生命周期事件;自动补 runId | — | | levelStart/levelComplete/levelFail | 标准关卡漏斗事件;自动继承当前 runId | — | | tutorialStep | 新手教程漏斗 | — | | resourceEvent | 游戏内资源来源/消耗(非平台积分) | — | | progressUpdate(snapshot) | 平台可读进度快照 | — | | gameError/performance | 错误与性能遥测 | — | | happyTime(0..1) | 高光时刻信号(提示装 PWA / 交叉导流) | — | | requestExit() / share(payload) | 退出 / 分享 | — |

标准事件(v2)—— 推荐

track() 仍可用于自定义事件,但运营看板优先识别标准事件:

const round = await jogabox.roundStart({ mode: 'classic', level: 3 })
await jogabox.levelStart({ runId: round.runId, level: 3, difficulty: 'normal' })
await jogabox.levelComplete({ runId: round.runId, level: 3, score: 1200, durationMs: 42000, moves: 18 })
await jogabox.progressUpdate({
  runId: round.runId,
  current_level: 4,
  highest_level: 4,
  rounds_played: 12,
  wins: 8,
  fails: 4,
  last_result: 'win',
  custom_summary: { booster_count: 2 }
})

约定:

  • runId 用于配对 roundStart/roundEndlevelStart/levelComplete/levelFail 与进度快照;roundStart() 未传时 SDK 自动生成。
  • progressUpdate 是平台可读快照;完整私有存档仍用 save/load
  • progressUpdate 的通用字段放顶层: current_level/highest_level/rounds_played/wins/fails/last_result/completion/highest_tile/best_distance/difficulty;游戏私有摘要放 custom_summary
  • 游戏内金币/道具用 resourceEvent;平台可兑积分不可由游戏写入。
  • 关卡事件必须带稳定 level;否则无法做关卡漏斗。
安全与本地开发

SDK 0.3.2 起,client/host 双向 postMessage 都校验具体 origin/source,不再使用 '*'。正常在 jogabox 大厅 iframe 内运行时无需配置;SDK 会从 document.referrer / ancestorOrigins 推断 host origin。特殊本地嵌入可显式传:

const jogabox = createClient({ hostOrigin: 'http://localhost:5173', timeoutMs: 8000 })

无父窗口直接打开游戏时,SDK 自动进入 standalone mock 模式:init() 立即返回假 context,事件输出到 console.debug,广告默认 { granted:false }。也可以显式配置:

const jogabox = createClient({
  mock: true,
  mockContext: { locale: 'pt-BR', game_ref: 'my-game' },
  mockRewarded: { granted: true, points: 10, confirmed_balance: 110 }
})

4. 铁律

  • 不要自己发积分:rewardedBreak 的奖励由服务端发放,游戏只读 granted / confirmed_balance;confirmed_balance 是入账后权威余额,直接展示,不要本地再累加;广告期间暂停 + 静音
  • 资源相对路径(base:'./'):游戏跑在 …/games/<slug>/<version>/ 下,绝对 /path 会指错。
  • 云存档不写经济字段:积分/余额以服务端为准;save 单条建议 < 100KB。
  • account_id 当不透明 ID 用,不含 PII。

5. 打包与上线

npm run build     # → dist/(静态)+ game.zip(模板已配 zip 打包)
  • 打包产物 dist/ 直接在 studio 后台「上传游戏」 上传(CLI 上传后续提供)。
  • 版本化:每次新版本上传为新 version;上线即在大厅目录可见;回滚=切回旧 version。

6. 本地联调

dist/ 放进大厅 apps/arcade/public/games/<slug>/ 并在 studio 设 entry_url=/games/<slug>/index.htmlstatus=active,起 core(:4000) + arcade(:5173),打开 http://localhost:5173 进入游戏,观察 SDK 调用回流(core 日志 / ClickHouse game_event)。


宿主端(大厅集成):import { createGameHost } from '@jogabox/game-sdk/host'

Keywords