新增Coroutine
This commit is contained in:
78
source/bin/framework.d.ts
vendored
78
source/bin/framework.d.ts
vendored
@@ -96,6 +96,7 @@ declare module es {
|
||||
* 全局访问系统
|
||||
*/
|
||||
_globalManagers: GlobalManager[];
|
||||
_coroutineManager: CoroutineManager;
|
||||
_timerManager: TimerManager;
|
||||
width: number;
|
||||
height: number;
|
||||
@@ -133,6 +134,12 @@ declare module es {
|
||||
* @param type
|
||||
*/
|
||||
static getGlobalManager<T extends es.GlobalManager>(type: any): T;
|
||||
/**
|
||||
* 启动一个coroutine。Coroutine可以将number延时几秒或延时到其他startCoroutine.Yielding
|
||||
* null将使coroutine在下一帧被执行。
|
||||
* @param enumerator
|
||||
*/
|
||||
static startCoroutine(enumerator: any): ICoroutine;
|
||||
/**
|
||||
* 调度一个一次性或重复的计时器,该计时器将调用已传递的动作
|
||||
* @param timeInSeconds
|
||||
@@ -3497,6 +3504,77 @@ declare module es {
|
||||
areEqual(value1: T, value2: T): boolean;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
/**
|
||||
* startCoroutine返回的接口,它提供了中途停止coroutine的能力。
|
||||
*/
|
||||
interface ICoroutine {
|
||||
/**
|
||||
* 停止Coroutine
|
||||
*/
|
||||
stop(): any;
|
||||
/**
|
||||
* 设置Coroutine是否应该使用deltaTime或unscaledDeltaTime进行计时
|
||||
* @param useUnscaledDeltaTime
|
||||
*/
|
||||
setUseUnscaledDeltaTime(useUnscaledDeltaTime: boolean): ICoroutine;
|
||||
}
|
||||
class Coroutine {
|
||||
/**
|
||||
* 导致Coroutine在指定的时间内暂停。在Coroutine.waitForSeconds的基础上,在Coroutine中使用Yield
|
||||
* @param seconds
|
||||
*/
|
||||
static waitForSeconds(seconds: number): WaitForSeconds;
|
||||
}
|
||||
/**
|
||||
* 帮助类,用于当一个coroutine想要暂停一段时间时。返回Coroutine.waitForSeconds返回其中一个
|
||||
*/
|
||||
class WaitForSeconds {
|
||||
static waiter: WaitForSeconds;
|
||||
waitTime: number;
|
||||
wait(seconds: number): WaitForSeconds;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
/**
|
||||
* CoroutineManager用于隐藏Coroutine所需数据的内部类
|
||||
*/
|
||||
class CoroutineImpl implements ICoroutine, IPoolable {
|
||||
enumerator: any;
|
||||
/**
|
||||
* 每当产生一个延迟,它就会被添加到跟踪延迟的waitTimer中
|
||||
*/
|
||||
waitTimer: number;
|
||||
isDone: boolean;
|
||||
waitForCoroutine: CoroutineImpl;
|
||||
useUnscaledDeltaTime: boolean;
|
||||
stop(): void;
|
||||
setUseUnscaledDeltaTime(useUnscaledDeltaTime: boolean): this;
|
||||
prepareForUse(): void;
|
||||
reset(): void;
|
||||
}
|
||||
class CoroutineManager extends GlobalManager {
|
||||
/**
|
||||
* 标志来跟踪我们何时处于更新循环中。
|
||||
* 如果在更新循环中启动了一个新的coroutine,我们必须将它贴在shouldRunNextFrame列表中,以避免在迭代时修改一个数组
|
||||
*/
|
||||
_isInUpdate: boolean;
|
||||
_unblockedCoroutines: CoroutineImpl[];
|
||||
_shouldRunNextFrame: CoroutineImpl[];
|
||||
/**
|
||||
* 将IEnumerator添加到CoroutineManager中
|
||||
* Coroutine在每一帧调用Update之前被执行
|
||||
* @param enumerator
|
||||
*/
|
||||
startCoroutine(enumerator: any): CoroutineImpl;
|
||||
update(): void;
|
||||
/**
|
||||
* 勾选一个coroutine,如果该coroutine应该在下一帧继续运行,则返回true。本方法会将完成的coroutine放回Pool
|
||||
* @param coroutine
|
||||
*/
|
||||
tickCoroutine(coroutine: CoroutineImpl): boolean;
|
||||
}
|
||||
}
|
||||
declare class ArrayUtils {
|
||||
/**
|
||||
* 执行冒泡排序
|
||||
|
||||
@@ -197,6 +197,7 @@ var es;
|
||||
* 全局访问系统
|
||||
*/
|
||||
this._globalManagers = [];
|
||||
this._coroutineManager = new es.CoroutineManager();
|
||||
this._timerManager = new es.TimerManager();
|
||||
this._frameCounterElapsedTime = 0;
|
||||
this._frameCounter = 0;
|
||||
@@ -206,6 +207,7 @@ var es;
|
||||
Core._instance = this;
|
||||
Core.emitter = new es.Emitter();
|
||||
Core.emitter.addObserver(es.CoreEvents.FrameUpdated, this.update, this);
|
||||
Core.registerGlobalManager(this._coroutineManager);
|
||||
Core.registerGlobalManager(this._timerManager);
|
||||
Core.entitySystemsEnabled = enableEntitySystems;
|
||||
this.initialize();
|
||||
@@ -278,6 +280,14 @@ var es;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
/**
|
||||
* 启动一个coroutine。Coroutine可以将number延时几秒或延时到其他startCoroutine.Yielding
|
||||
* null将使coroutine在下一帧被执行。
|
||||
* @param enumerator
|
||||
*/
|
||||
Core.startCoroutine = function (enumerator) {
|
||||
return this._instance._coroutineManager.startCoroutine(enumerator);
|
||||
};
|
||||
/**
|
||||
* 调度一个一次性或重复的计时器,该计时器将调用已传递的动作
|
||||
* @param timeInSeconds
|
||||
@@ -8827,6 +8837,164 @@ var es;
|
||||
}(Set));
|
||||
es.HashSet = HashSet;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var Coroutine = /** @class */ (function () {
|
||||
function Coroutine() {
|
||||
}
|
||||
/**
|
||||
* 导致Coroutine在指定的时间内暂停。在Coroutine.waitForSeconds的基础上,在Coroutine中使用Yield
|
||||
* @param seconds
|
||||
*/
|
||||
Coroutine.waitForSeconds = function (seconds) {
|
||||
return WaitForSeconds.waiter.wait(seconds);
|
||||
};
|
||||
return Coroutine;
|
||||
}());
|
||||
es.Coroutine = Coroutine;
|
||||
/**
|
||||
* 帮助类,用于当一个coroutine想要暂停一段时间时。返回Coroutine.waitForSeconds返回其中一个
|
||||
*/
|
||||
var WaitForSeconds = /** @class */ (function () {
|
||||
function WaitForSeconds() {
|
||||
this.waitTime = 0;
|
||||
}
|
||||
WaitForSeconds.prototype.wait = function (seconds) {
|
||||
WaitForSeconds.waiter.waitTime = seconds;
|
||||
return WaitForSeconds.waiter;
|
||||
};
|
||||
WaitForSeconds.waiter = new WaitForSeconds();
|
||||
return WaitForSeconds;
|
||||
}());
|
||||
es.WaitForSeconds = WaitForSeconds;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
/**
|
||||
* CoroutineManager用于隐藏Coroutine所需数据的内部类
|
||||
*/
|
||||
var CoroutineImpl = /** @class */ (function () {
|
||||
function CoroutineImpl() {
|
||||
/**
|
||||
* 每当产生一个延迟,它就会被添加到跟踪延迟的waitTimer中
|
||||
*/
|
||||
this.waitTimer = 0;
|
||||
this.useUnscaledDeltaTime = false;
|
||||
}
|
||||
CoroutineImpl.prototype.stop = function () {
|
||||
this.isDone = true;
|
||||
};
|
||||
CoroutineImpl.prototype.setUseUnscaledDeltaTime = function (useUnscaledDeltaTime) {
|
||||
this.useUnscaledDeltaTime = useUnscaledDeltaTime;
|
||||
return this;
|
||||
};
|
||||
CoroutineImpl.prototype.prepareForUse = function () {
|
||||
this.isDone = false;
|
||||
};
|
||||
CoroutineImpl.prototype.reset = function () {
|
||||
this.isDone = true;
|
||||
this.waitTimer = 0;
|
||||
this.waitForCoroutine = null;
|
||||
this.enumerator = null;
|
||||
this.useUnscaledDeltaTime = false;
|
||||
};
|
||||
return CoroutineImpl;
|
||||
}());
|
||||
es.CoroutineImpl = CoroutineImpl;
|
||||
var CoroutineManager = /** @class */ (function (_super) {
|
||||
__extends(CoroutineManager, _super);
|
||||
function CoroutineManager() {
|
||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||
_this._unblockedCoroutines = [];
|
||||
_this._shouldRunNextFrame = [];
|
||||
return _this;
|
||||
}
|
||||
/**
|
||||
* 将IEnumerator添加到CoroutineManager中
|
||||
* Coroutine在每一帧调用Update之前被执行
|
||||
* @param enumerator
|
||||
*/
|
||||
CoroutineManager.prototype.startCoroutine = function (enumerator) {
|
||||
// 找到或创建一个CoroutineImpl
|
||||
var coroutine = es.Pool.obtain(CoroutineImpl);
|
||||
coroutine.prepareForUse();
|
||||
// 设置coroutine并添加它
|
||||
coroutine.enumerator = enumerator;
|
||||
var shouldContinueCoroutine = this.tickCoroutine(coroutine);
|
||||
if (!shouldContinueCoroutine)
|
||||
return null;
|
||||
if (this._isInUpdate)
|
||||
this._shouldRunNextFrame.push(coroutine);
|
||||
else
|
||||
this._unblockedCoroutines.push(coroutine);
|
||||
return coroutine;
|
||||
};
|
||||
CoroutineManager.prototype.update = function () {
|
||||
this._isInUpdate = true;
|
||||
for (var i = 0; i < this._unblockedCoroutines.length; i++) {
|
||||
var coroutine = this._unblockedCoroutines[i];
|
||||
if (coroutine.isDone) {
|
||||
es.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 ? es.Time.unscaledDeltaTime : es.Time.deltaTime;
|
||||
this._shouldRunNextFrame.push(coroutine);
|
||||
continue;
|
||||
}
|
||||
if (this.tickCoroutine(coroutine))
|
||||
this._shouldRunNextFrame.push(coroutine);
|
||||
}
|
||||
var 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
|
||||
*/
|
||||
CoroutineManager.prototype.tickCoroutine = function (coroutine) {
|
||||
var chain = coroutine.enumerator.next();
|
||||
if (chain.done || coroutine.isDone) {
|
||||
es.Pool.free(coroutine);
|
||||
return false;
|
||||
}
|
||||
if (chain.value == null) {
|
||||
// 下一帧再运行
|
||||
return true;
|
||||
}
|
||||
if (chain.value instanceof es.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;
|
||||
}
|
||||
};
|
||||
return CoroutineManager;
|
||||
}(es.GlobalManager));
|
||||
es.CoroutineManager = CoroutineManager;
|
||||
})(es || (es = {}));
|
||||
var ArrayUtils = /** @class */ (function () {
|
||||
function ArrayUtils() {
|
||||
}
|
||||
|
||||
2
source/bin/framework.min.js
vendored
2
source/bin/framework.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -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) {
|
||||
|
||||
39
source/src/Utils/Coroutines/Coroutine.ts
Normal file
39
source/src/Utils/Coroutines/Coroutine.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
146
source/src/Utils/Coroutines/CoroutineManager.ts
Normal file
146
source/src/Utils/Coroutines/CoroutineManager.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user