diff --git a/examples/src/gameStart.ts b/examples/src/gameStart.ts new file mode 100644 index 00000000..4b5dde1e --- /dev/null +++ b/examples/src/gameStart.ts @@ -0,0 +1,77 @@ +import { RendererSystem } from "@eva/plugin-renderer"; +import { Game, GameObject, RESOURCE_TYPE, resource } from "@eva/eva.js" +import { Img, ImgSystem } from "@eva/plugin-renderer-img"; +export const name = 'gameStart'; +export async function init(canvas) { + resource.addResource([ + { + name: 'imageName', + type: RESOURCE_TYPE.IMAGE, + src: { + image: { + type: 'png', + url: 'https://gw.alicdn.com/tfs/TB1DNzoOvb2gK0jSZK9XXaEgFXa-658-1152.webp', + }, + }, + preload: true, + }, + ]); + const game = new Game({ + // autoStart: false, + frameRate: 45, + systems: [ + new RendererSystem({ + canvas, + width: 750, + height: 1000, + }), + new ImgSystem(), + ], + }); + + + + const image = new GameObject('image', { + size: { width: 750, height: 1319 }, + origin: { x: 0, y: 0 }, + position: { + x: 0, + y: -319, + }, + anchor: { + x: 0, + y: 0, + }, + }); + window.game = game + + let start = performance.now() + console.log(game.ticker.time.currentTime, 'add') + game.ticker.setTimeout(() => { + console.log(game.ticker.time.currentTime, 'begin') + console.log(performance.now() - start,3) + + image.addComponent( + new Img({ + resource: 'imageName', + }), + ); + }, 1000) + + + // game.ticker.setTimeout(() => { + // console.log(game.ticker.time.frameCount) + // console.log(performance.now() - start,1) + // }, 2890) + + // game.ticker.setTimeout(() => { + // console.log(game.ticker.time.frameCount) + // console.log(performance.now() - start, 2) + // }, 2990) + + game.scene.addChild(image); + + // setTimeout(()=>{ + // game.start() + // }, 3000) +} \ No newline at end of file diff --git a/packages/eva.js/lib/game/Ticker.ts b/packages/eva.js/lib/game/Ticker.ts index ae94927a..ecba698b 100644 --- a/packages/eva.js/lib/game/Ticker.ts +++ b/packages/eva.js/lib/game/Ticker.ts @@ -48,6 +48,32 @@ class Ticker { /** Represents the status of the Ticker, If ticker has started, the value is true */ private _started: boolean; + private _timeoutList: { + timeoutId: number; + startTime: number; + endTime: number; + callback: Function; + delay: number; + args?: any[]; + }[] = [] + private _timeoutId: number = 0 + + private _frameDelayList: { + execFrameNumber: number; + callback: Function; + frameDelayId: number; + }[] = [] + + private _frameDelayId: number = 0 + + public time: UpdateParams = { + deltaTime: 0, + time: 0, + currentTime: 0, + frameCount: 0, + fps: 0, + } + /** * @param autoStart - auto start game * @param frameRate - game frame rate @@ -78,6 +104,72 @@ class Ticker { } } + setFrameDelay(callback, frameCount: number) { + if (frameCount < 1 || !frameCount) { + throw 'frameCount must greater than 0' + } + const frameDelayInfo = { + frameDelayId: this._frameDelayId++, + callback, + execFrameNumber: this.time.frameCount + frameCount + } + this._frameDelayList.push(frameDelayInfo) + return frameDelayInfo.frameDelayId; + } + + resolveFrameDelay() { + const index = this._frameDelayList.findIndex(event => event.execFrameNumber <= this.time.frameCount) + if (index === -1) return; + const needResolve = this._frameDelayList.splice(0, index + 1) + for (const delayInfo of needResolve) { + try { + delayInfo.callback() + } catch (e) { + throw e + } + } + } + + clearFrameDelay(frameDelayId: number) { + const index = this._frameDelayList.findIndex(event => event.frameDelayId === frameDelayId) + if (index === -1) return + this._frameDelayList.splice(index, 1) + } + + setTimeout(callback, delay, ...args) { + const delayInfo = { + timeoutId: this._timeoutId++, + startTime: this.time.currentTime, + endTime: this.time.currentTime + delay, + callback, + delay, + args + } + const index = this._timeoutList.findIndex(event => delayInfo.endTime >= event.endTime) + this._timeoutList.splice(index + 1, 0, delayInfo) + + return delayInfo.timeoutId + } + + clearTimeout(timeoutId: number) { + const index = this._timeoutList.findIndex(event => event.timeoutId === timeoutId) + if (index === -1) return + this._timeoutList.splice(index, 1) + } + + private resolveSetTimeout() { + const index = this._timeoutList.findIndex(event => event.endTime <= this.time.currentTime + 0.0001) + if (index === -1) return; + const needResolve = this._timeoutList.splice(0, index + 1) + for (const delayInfo of needResolve) { + try { + delayInfo.callback(...delayInfo.args) + } catch (e) { + throw e + } + } + } + /** Main loop, all _tickers will called in this method */ update() { const currentTime = this.timeline.currentTime; @@ -95,12 +187,16 @@ class Ticker { frameCount: ++this._frameCount, fps: Math.round(1000 / deltaTime), }; + this.time = options for (const func of this._tickers) { if (typeof func === 'function') { func(options); } } + + this.resolveFrameDelay() + this.resolveSetTimeout() } }