新增Coroutine

This commit is contained in:
yhh
2020-12-23 17:14:16 +08:00
parent 8ed3eb24c3
commit fa10d5d4d5
9 changed files with 449 additions and 189 deletions

View File

@@ -33,6 +33,7 @@ module es {
* 全局访问系统
*/
public _globalManagers: GlobalManager[] = [];
public _coroutineManager: CoroutineManager = new CoroutineManager();
public _timerManager: TimerManager = new TimerManager();
public width: number;
public height: number;
@@ -45,6 +46,7 @@ module es {
Core.emitter = new Emitter<CoreEvents>();
Core.emitter.addObserver(CoreEvents.FrameUpdated, this.update, this);
Core.registerGlobalManager(this._coroutineManager);
Core.registerGlobalManager(this._timerManager);
Core.entitySystemsEnabled = enableEntitySystems;
@@ -123,6 +125,15 @@ module es {
return null;
}
/**
* 启动一个coroutine。Coroutine可以将number延时几秒或延时到其他startCoroutine.Yielding
* null将使coroutine在下一帧被执行。
* @param enumerator
*/
public static startCoroutine(enumerator): ICoroutine {
return this._instance._coroutineManager.startCoroutine(enumerator);
}
/**
* 调度一个一次性或重复的计时器,该计时器将调用已传递的动作
* @param timeInSeconds
@@ -130,7 +141,7 @@ module es {
* @param context
* @param onTime
*/
public static schedule(timeInSeconds: number, repeats: boolean = false, context: any = null, onTime: (timer: ITimer)=>void){
public static schedule(timeInSeconds: number, repeats: boolean = false, context: any = null, onTime: (timer: ITimer) => void) {
return this._instance._timerManager.schedule(timeInSeconds, repeats, context, onTime);
}
@@ -139,7 +150,7 @@ module es {
}
public startDebugDraw() {
this._frameCounter ++;
this._frameCounter++;
this._frameCounterElapsedTime += Time.deltaTime;
if (this._frameCounterElapsedTime >= 1) {
let memoryInfo = window.performance["memory"];
@@ -165,7 +176,7 @@ module es {
*/
protected onGraphicsDeviceReset() {
// 我们用这些来避免垃圾事件的发生
if (this._graphicsDeviceChangeTimer != null){
if (this._graphicsDeviceChangeTimer != null) {
this._graphicsDeviceChangeTimer.reset();
} else {
this._graphicsDeviceChangeTimer = Core.schedule(0.05, false, this, t => {
@@ -176,7 +187,7 @@ module es {
}
protected initialize() {
}
protected async update(currentTime?: number) {

View File

@@ -0,0 +1,39 @@
module es {
/**
* startCoroutine返回的接口它提供了中途停止coroutine的能力。
*/
export interface ICoroutine {
/**
* 停止Coroutine
*/
stop();
/**
* 设置Coroutine是否应该使用deltaTime或unscaledDeltaTime进行计时
* @param useUnscaledDeltaTime
*/
setUseUnscaledDeltaTime(useUnscaledDeltaTime: boolean): ICoroutine;
}
export class Coroutine {
/**
* 导致Coroutine在指定的时间内暂停。在Coroutine.waitForSeconds的基础上在Coroutine中使用Yield
* @param seconds
*/
public static waitForSeconds(seconds: number) {
return WaitForSeconds.waiter.wait(seconds);
}
}
/**
* 帮助类用于当一个coroutine想要暂停一段时间时。返回Coroutine.waitForSeconds返回其中一个
*/
export class WaitForSeconds {
public static waiter: WaitForSeconds = new WaitForSeconds();
public waitTime: number = 0;
public wait(seconds: number): WaitForSeconds {
WaitForSeconds.waiter.waitTime = seconds;
return WaitForSeconds.waiter;
}
}
}

View File

@@ -0,0 +1,146 @@
module es {
/**
* CoroutineManager用于隐藏Coroutine所需数据的内部类
*/
export class CoroutineImpl implements ICoroutine, IPoolable {
public enumerator: any;
/**
* 每当产生一个延迟它就会被添加到跟踪延迟的waitTimer中
*/
public waitTimer: number = 0;
public isDone: boolean;
public waitForCoroutine: CoroutineImpl;
public useUnscaledDeltaTime: boolean = false;
public stop() {
this.isDone = true;
}
public setUseUnscaledDeltaTime(useUnscaledDeltaTime: boolean) {
this.useUnscaledDeltaTime = useUnscaledDeltaTime;
return this;
}
public prepareForUse() {
this.isDone = false;
}
public reset() {
this.isDone = true;
this.waitTimer = 0;
this.waitForCoroutine = null;
this.enumerator = null;
this.useUnscaledDeltaTime = false;
}
}
export class CoroutineManager extends GlobalManager {
/**
* 标志来跟踪我们何时处于更新循环中。
* 如果在更新循环中启动了一个新的coroutine我们必须将它贴在shouldRunNextFrame列表中以避免在迭代时修改一个数组
*/
public _isInUpdate: boolean;
public _unblockedCoroutines: CoroutineImpl[] = [];
public _shouldRunNextFrame: CoroutineImpl[] = [];
/**
* 将IEnumerator添加到CoroutineManager中
* Coroutine在每一帧调用Update之前被执行
* @param enumerator
*/
public startCoroutine(enumerator: any) {
// 找到或创建一个CoroutineImpl
let coroutine = Pool.obtain<CoroutineImpl>(CoroutineImpl);
coroutine.prepareForUse();
// 设置coroutine并添加它
coroutine.enumerator = enumerator;
let shouldContinueCoroutine = this.tickCoroutine(coroutine);
if (!shouldContinueCoroutine)
return null;
if (this._isInUpdate)
this._shouldRunNextFrame.push(coroutine);
else
this._unblockedCoroutines.push(coroutine);
return coroutine;
}
public update() {
this._isInUpdate = true;
for (let i = 0; i < this._unblockedCoroutines.length; i++) {
let coroutine = this._unblockedCoroutines[i];
if (coroutine.isDone) {
Pool.free(coroutine);
continue;
}
if (coroutine.waitForCoroutine != null) {
if (coroutine.waitForCoroutine.isDone) {
coroutine.waitForCoroutine = null;
} else {
this._shouldRunNextFrame.push(coroutine);
continue;
}
}
if (coroutine.waitTimer > 0) {
// 递减然后再运行下一帧确保用适当的deltaTime递减
coroutine.waitTimer -= coroutine.useUnscaledDeltaTime ? Time.unscaledDeltaTime : Time.deltaTime;
this._shouldRunNextFrame.push(coroutine);
continue;
}
if (this.tickCoroutine(coroutine))
this._shouldRunNextFrame.push(coroutine);
}
let linqCoroutines = new linq.List(this._unblockedCoroutines);
linqCoroutines.clear();
linqCoroutines.addRange(this._shouldRunNextFrame);
this._shouldRunNextFrame.length = 0;
this._isInUpdate = false;
}
/**
* 勾选一个coroutine如果该coroutine应该在下一帧继续运行则返回true。本方法会将完成的coroutine放回Pool
* @param coroutine
*/
public tickCoroutine(coroutine: CoroutineImpl) {
let chain = coroutine.enumerator.next();
if (chain.done || coroutine.isDone) {
Pool.free(coroutine);
return false;
}
if (chain.value == null) {
// 下一帧再运行
return true;
}
if (chain.value instanceof WaitForSeconds) {
coroutine.waitTimer = chain.value.waitTime;
return true;
}
if (typeof chain.value == 'number') {
coroutine.waitTimer = chain.value;
return true;
}
if (chain.value instanceof CoroutineImpl) {
coroutine.waitForCoroutine = chain.value;
return true;
} else {
return true;
}
}
}
}