Runtime API
在 Extension 中控制對話、聲音、輸入與遊戲狀態。
以下程式放在設定好的 Extension中,ctx 由 createPrismatiXContext() 建立。新增 command 或 Action 時,記得在描述檔登記,並加入該服務需要的能力。
常用服務
| 服務 | 用途 |
|---|---|
variables | 讀寫 session/profile 變數 |
assets | 檢查與讀取已打包的資源 |
session | 讀取對話、選項,推進劇情 |
backlog | 對話紀錄、語音重播與回溯 |
settings | Player 設定 |
ui | 路由、彈出視窗與轉場 |
progress | 已讀紀錄、CG 和場景解鎖 |
audio、video | 媒體播放與控制 |
saves | 儲存、讀取及管理存檔欄位 |
stage、animation、effects | 畫面、時間軸與特效 |
events、input | 事件與操作輸入 |
state | 保存 Extension 自有資料 |
renderer、debug | 繪製與除錯 |
ctx.raw 是底層的 Engine API,px 是全域 Engine 的別名。
訂閱對話更新
const stopObserving = ctx.session.observeDialogue((dialogue) => {
ctx.raw.log('dialogue snapshot', JSON.stringify(dialogue));
});
const choices = ctx.session.choices();
if (choices.length > 0) {
ctx.raw.log('available choices', JSON.stringify(choices));
}
// 在你的畫面或控制器不再使用訂閱時呼叫。
stopObserving();observeDialogue 會先傳入目前資料,之後只在內容改變時通知。observeChoices、backlog.observe、settings.observe 也是相同方式。
範例最後立即停止訂閱,方便展示用法;實際 UI 應保存這個函式,在畫面不再使用資料時呼叫。
ctx.session.advance() 推進對話,ctx.session.selectChoice(index) 選擇選項,索引從 0 開始。這些操作應由玩家輸入或明確的遊戲流程觸發。
對話紀錄與設定
const entries = ctx.backlog.entries();
const last = entries.at(-1);
if (last) {
ctx.backlog.replayVoice(last.sequence);
// 只有玩家真的要求回溯時才呼叫:
// ctx.backlog.rollback(last.sequence);
}
ctx.settings.set('textScale', 1.25);語音重播與回溯使用 sequence,不是資料在陣列中的位置。回溯會還原劇情進度與受管理的狀態。
CG 和場景解鎖使用 ctx.progress.unlockCG(id)、unlockScene(id),並搭配 game catalog 中已登記的內容。畫廊介面仍需另外提供。
聲音與影片
在具有 audio 能力的 callback 中,播放已登記的素材:
ctx.audio.setBGMVolume(0.7);
ctx.audio.playBGM('Assets/evening.wav', {
loop: true,
fadeMilliseconds: 600,
});
ctx.audio.playSE('Assets/bell.wav');
ctx.audio.playVoice('Assets/greeting.wav');
// 需要停止時:
// ctx.audio.stopBGM(400);
// ctx.audio.stopVoice();影片需要 video 能力和原生媒體支援。以下片段放在 async callback 中:
const opening = ctx.video.play('Assets/opening.mp4', {
volume: 0.8,
skippable: true,
});
await opening;影片 handle 提供 pause、resume、stop、skip、status、error、wait、token。音訊 handle 也可控制播放,但 seek 接受的是音訊播放影格,不是秒數。
等待媒體時,要處理取消與失敗;循環音樂不會自行結束,不適合直接等待播完。WASM Preview 沒有原生影片後端,影片請用原生 Preview 或 Player 測試。
事件與輸入
ctx.events.on('tutorial.notice', (payload) => {
ctx.raw.log('tutorial.notice', JSON.stringify(payload));
});
// 在 async callback 中發送:
// await ctx.events.emit('tutorial.notice', { message: 'Ready' });事件通常在 Extension 初始化時註冊一次。events.on 不回傳前面 observe API 的取消訂閱函式。
input.actionPressed 檢查本次觸發,actionDown 檢查是否持續按住。也可以讀取事件,再用 consume 或 suppressDefault 處理。
自訂動作使用 registerAction、bindKey 和 namedActionPressed/namedActionDown。鍵碼採引擎的 scancode,而不是瀏覽器的 KeyboardEvent.key。
ctx.assets.exists(path)、readText(path) 只存取打包資源;需要的資料應先加入專案。
保存 Extension 狀態
一般 JavaScript 變數不會自動跟著存檔。需要保存自有資料時,註冊 state provider:
type VisitState = { visits: number };
let state: VisitState = { visits: 0 };
ctx.state.registerProvider<VisitState>('tutorial.visits', 1, {
capture: () => ({ ...state }),
restore: (saved) => {
state = { ...saved };
},
});資料必須能表示成 JSON,不能包含函式、循環參照或外部資源 handle。capture、restore、migrate 都是同步資料操作,執行期間不可呼叫引擎操作或等待。
資料格式改變時,提高 provider 版本並提供遷移函式,見存檔與更新。恢復非同步 command 或 Action 時,引擎可能重新執行部分程式,因此也要測試讀檔後是否重複產生副作用。
繪製與執行環境
renderer 提供 logicalSize、繪製節點的 upsert/remove/clear,以及 drawImage、drawRect、drawText 等方法。節點要配合畫面生命週期建立與清除;一般選單可優先使用原生 UI,沿用焦點與輸入處理。
Extension 執行於 QuickJS 沙盒,不提供 Node.js、任意檔案存取、網路、DOM、eval、系統時鐘或不受控亂數。等待使用引擎的 time/animation/media API;隨機視覺效果可交給使用固定 seed 的粒子系統。
實作參考:型別與實作、Runtime SDK、存檔與回放。