hzengine-core
Version:
An Visual Novel Engine for Zepp OS
125 lines (112 loc) • 3.42 kB
text/typescript
import { HZEngineCore, Storage } from "../index.js";
import { Save } from "../storage/decorator.js";
import { ZeppTimer } from "./zeppos_timer.js";
// import { Time } from "@zos/sensor";
export class Async {
static _nextTickCallbacks: (() => void)[] = [];
static _nextTickTimerId: number | null = null;
static nextTick(callback: () => void) {
this._nextTickCallbacks.push(callback);
if (this._nextTickTimerId == null) {
this._nextTickTimerId = setTimeout(() => {
this._nextTickTimerCallback();
}, 30) as unknown as number;
}
}
static _nextTickTimerCallback() {
this._nextTickTimerId = null;
const callbacks = this._nextTickCallbacks;
this._nextTickCallbacks = [];
callbacks.forEach((cb) => {
cb();
});
}
// private _fps = 45;
// private _hmTime = new Time();
private _lastTime: number;
constructor(public _core: HZEngineCore) {
// console.log("async init");
// let timer = new ZeppTimer(() => {
// // console.log(`async timer cb`);
// this._scheduleTask();
// }, ~~(1000 / this._fps));
// timer.start();
this._lastTime = this._core.platform.getTime();
// setInterval(() => {
// this._scheduleTask();
// }, ~~(1000 / this._fps));
_core.platform.setFrameInterval(() => {
this._scheduleTask();
});
}
_scheduleTask() {
// TODO 沒有充分考慮存檔時產生的問題(this._delayTasks引用變化),及其它問題
let now = this._core.platform.getTime();
let deltaTime = now - this._lastTime;
this._lastTime = now;
// console.log(`async timer cb d=${deltaTime}`);
for (let id in this._delayTasks) {
let task = this._delayTasks[id];
task.next -= deltaTime;
if (task.next <= 0) {
this._core.emit(task.event, ...task.args);
if (task.repeat >= 0) {
// interval
task.next += task.repeat;
} else {
delete this._delayTasks[id];
}
}
}
}
("async.nextTimerId")
private accessor _nextTimerId: number = 50;
// tasks
("async.delayTasks")
private accessor _delayTasks: Record<number, Async.Task> = {};
// 注意在task執行中立即創建一個新的task,會在同一個js task中執行
// 注意周期實際為1個frame的時間的整數倍
addDelayTask(
event: string,
args: Storage.Saveable<unknown>[],
delayMs: number
): number {
let task: Async.Task = {
event,
args,
next: delayMs,
repeat: -1,
};
let id = this._nextTimerId++;
this._delayTasks[id] = task;
return id;
}
addRepeatTask(
event: string,
args: Storage.Saveable<unknown>[],
intervalMs: number,
delayMs?: number
): number {
intervalMs = intervalMs >= 0 ? intervalMs : 0;
let task: Async.Task = {
event,
args,
next: delayMs ?? intervalMs,
repeat: intervalMs,
};
let id = this._nextTimerId++;
this._delayTasks[id] = task;
return id;
}
removeTask(id: number) {
delete this._delayTasks[id];
}
}
export namespace Async {
export interface Task {
event: string;
args: Storage.Saveable<unknown>[];
next: number; // remaining time in ms
repeat: number; // -1 for once ; >=0 for repeat circle
}
}