新增 CoroutineManager 协同程序
This commit is contained in:
Vendored
+55
@@ -198,6 +198,7 @@ declare module es {
|
||||
_nextScene: Scene;
|
||||
_sceneTransition: SceneTransition;
|
||||
_globalManagers: GlobalManager[];
|
||||
_coroutineManager: CoroutineManager;
|
||||
_timerManager: TimerManager;
|
||||
constructor();
|
||||
static readonly Instance: Core;
|
||||
@@ -207,6 +208,7 @@ declare module es {
|
||||
static registerGlobalManager(manager: es.GlobalManager): void;
|
||||
static unregisterGlobalManager(manager: es.GlobalManager): void;
|
||||
static getGlobalManager<T extends es.GlobalManager>(type: any): T;
|
||||
static startCoroutine(enumerator: IEnumerator): CoroutineImpl;
|
||||
static schedule(timeInSeconds: number, repeats: boolean, context: any, onTime: (timer: ITimer) => void): Timer;
|
||||
onOrientationChanged(): void;
|
||||
draw(): Promise<void>;
|
||||
@@ -2064,6 +2066,19 @@ declare module es {
|
||||
equals(other: Pair<T>): boolean;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
class Pool<T> {
|
||||
private static _objectQueue;
|
||||
static warmCache(type: any, cacheCount: number): void;
|
||||
static trimCache(cacheCount: number): void;
|
||||
static clearCache(): void;
|
||||
static obtain<T>(type: any): T;
|
||||
static free<T>(obj: T): void;
|
||||
}
|
||||
interface IPoolable {
|
||||
reset(): any;
|
||||
}
|
||||
}
|
||||
declare class RandomUtils {
|
||||
static randrange(start: number, stop: number, step?: number): number;
|
||||
static randint(a: number, b: number): number;
|
||||
@@ -2264,6 +2279,46 @@ declare module es {
|
||||
initialized: boolean;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
interface ICoroutine {
|
||||
stop(): any;
|
||||
setUseUnscaledDeltaTime(useUnscaledDeltaTime: any): ICoroutine;
|
||||
}
|
||||
class Coroutine {
|
||||
static waitForSeconds(seconds: number): WaitForSeconds;
|
||||
}
|
||||
class WaitForSeconds {
|
||||
static waiter: WaitForSeconds;
|
||||
waitTime: number;
|
||||
wait(seconds: number): WaitForSeconds;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
class CoroutineImpl implements ICoroutine, IPoolable {
|
||||
enumerator: IEnumerator;
|
||||
waitTimer: number;
|
||||
isDone: boolean;
|
||||
waitForCoroutine: CoroutineImpl;
|
||||
useUnscaledDeltaTime: boolean;
|
||||
stop(): void;
|
||||
setUseUnscaledDeltaTime(useUnscaledDeltaTime: any): es.ICoroutine;
|
||||
prepareForuse(): void;
|
||||
reset(): void;
|
||||
}
|
||||
interface IEnumerator {
|
||||
current: any;
|
||||
moveNext(): boolean;
|
||||
reset(): any;
|
||||
}
|
||||
class CoroutineManager extends GlobalManager {
|
||||
_isInUpdate: boolean;
|
||||
_unblockedCoroutines: CoroutineImpl[];
|
||||
_shouldRunNextFrame: CoroutineImpl[];
|
||||
startCoroutine(enumerator: IEnumerator): CoroutineImpl;
|
||||
update(): void;
|
||||
tickCoroutine(coroutine: CoroutineImpl): boolean;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
class TouchState {
|
||||
x: number;
|
||||
|
||||
+181
-11
@@ -966,11 +966,13 @@ var es;
|
||||
function Core() {
|
||||
var _this = _super.call(this) || this;
|
||||
_this._globalManagers = [];
|
||||
_this._coroutineManager = new es.CoroutineManager();
|
||||
_this._timerManager = new es.TimerManager();
|
||||
Core._instance = _this;
|
||||
Core.emitter = new es.Emitter();
|
||||
Core.content = new es.ContentManager();
|
||||
_this.addEventListener(egret.Event.ADDED_TO_STAGE, _this.onAddToStage, _this);
|
||||
Core.registerGlobalManager(_this._coroutineManager);
|
||||
Core.registerGlobalManager(_this._timerManager);
|
||||
return _this;
|
||||
}
|
||||
@@ -1028,6 +1030,9 @@ var es;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Core.startCoroutine = function (enumerator) {
|
||||
return this._instance._coroutineManager.startCoroutine(enumerator);
|
||||
};
|
||||
Core.schedule = function (timeInSeconds, repeats, context, onTime) {
|
||||
if (repeats === void 0) { repeats = false; }
|
||||
if (context === void 0) { context = null; }
|
||||
@@ -3067,8 +3072,8 @@ var es;
|
||||
set: function (value) {
|
||||
this._textureScale = value;
|
||||
this._inverseTexScale = new es.Vector2(1 / this._textureScale.x, 1 / this._textureScale.y);
|
||||
this._sourceRect.width = this._sprite.sourceRect.width * this._inverseTexScale.x;
|
||||
this._sourceRect.height = this._sprite.sourceRect.height * this._inverseTexScale.y;
|
||||
this._sourceRect.width = Math.floor(this._sprite.sourceRect.width * this._inverseTexScale.x);
|
||||
this._sourceRect.height = Math.floor(this._sprite.sourceRect.height * this._inverseTexScale.y);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
@@ -3186,8 +3191,8 @@ var es;
|
||||
return;
|
||||
this._scrollX += this.scrollSpeedX * es.Time.deltaTime;
|
||||
this._scrollY += this.scroolSpeedY * es.Time.deltaTime;
|
||||
this._sourceRect.x = this._scrollX;
|
||||
this._sourceRect.y = this._scrollY;
|
||||
this._sourceRect.x = Math.floor(this._scrollX);
|
||||
this._sourceRect.y = Math.floor(this._scrollY);
|
||||
this._sourceRect.width = this._scrollWidth + Math.abs(this._scrollX);
|
||||
this._sourceRect.height = this._scrollHeight + Math.abs(this._scrollY);
|
||||
};
|
||||
@@ -5254,7 +5259,7 @@ var es;
|
||||
this._timeSinceSceneLoad = 0;
|
||||
};
|
||||
Time.checkEvery = function (interval) {
|
||||
return (this._timeSinceSceneLoad / interval) > ((this._timeSinceSceneLoad - this.deltaTime) / interval);
|
||||
return Math.floor(this._timeSinceSceneLoad / interval) > Math.floor((this._timeSinceSceneLoad - this.deltaTime) / interval);
|
||||
};
|
||||
Time.deltaTime = 0;
|
||||
Time.timeScale = 1;
|
||||
@@ -6627,7 +6632,7 @@ var es;
|
||||
}
|
||||
SubpixelFloat.prototype.update = function (amount) {
|
||||
this.remainder += amount;
|
||||
var motion = Math.trunc(this.remainder);
|
||||
var motion = Math.floor(Math.trunc(this.remainder));
|
||||
this.remainder -= motion;
|
||||
amount = motion;
|
||||
return amount;
|
||||
@@ -7808,11 +7813,11 @@ var es;
|
||||
}
|
||||
while (currentCell.x != lastCell.x || currentCell.y != lastCell.y) {
|
||||
if (tMaxX < tMaxY) {
|
||||
currentCell.x = es.MathHelper.approach(currentCell.x, lastCell.x, Math.abs(stepX));
|
||||
currentCell.x = Math.floor(es.MathHelper.approach(currentCell.x, lastCell.x, Math.abs(stepX)));
|
||||
tMaxX += tDeltaX;
|
||||
}
|
||||
else {
|
||||
currentCell.y = es.MathHelper.approach(currentCell.y, lastCell.y, Math.abs(stepY));
|
||||
currentCell.y = Math.floor(es.MathHelper.approach(currentCell.y, lastCell.y, Math.abs(stepY)));
|
||||
tMaxY += tDeltaY;
|
||||
}
|
||||
cell = this.cellAtPosition(currentCell.x, currentCell.y);
|
||||
@@ -8058,7 +8063,7 @@ var es;
|
||||
flip = (rawGid & TmxLayerTile.FLIPPED_VERTICALLY_FLAG) != 0;
|
||||
this.verticalFlip = flip;
|
||||
rawGid &= ~(TmxLayerTile.FLIPPED_HORIZONTALLY_FLAG | TmxLayerTile.FLIPPED_VERTICALLY_FLAG);
|
||||
this.gid = rawGid;
|
||||
this.gid = Math.floor(rawGid);
|
||||
this.tileset = map.getTilesetForTileGid(this.gid);
|
||||
}
|
||||
Object.defineProperty(TmxLayerTile.prototype, "position", {
|
||||
@@ -9949,6 +9954,42 @@ var es;
|
||||
}());
|
||||
es.Pair = Pair;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var Pool = (function () {
|
||||
function Pool() {
|
||||
}
|
||||
Pool.warmCache = function (type, cacheCount) {
|
||||
cacheCount -= this._objectQueue.length;
|
||||
if (cacheCount > 0) {
|
||||
for (var i = 0; i < cacheCount; i++) {
|
||||
this._objectQueue.unshift(new type());
|
||||
}
|
||||
}
|
||||
};
|
||||
Pool.trimCache = function (cacheCount) {
|
||||
while (cacheCount > this._objectQueue.length)
|
||||
this._objectQueue.shift();
|
||||
};
|
||||
Pool.clearCache = function () {
|
||||
this._objectQueue.length = 0;
|
||||
};
|
||||
Pool.obtain = function (type) {
|
||||
if (this._objectQueue.length > 0)
|
||||
return this._objectQueue.shift();
|
||||
return new type();
|
||||
};
|
||||
Pool.free = function (obj) {
|
||||
this._objectQueue.unshift(obj);
|
||||
if (egret.is(obj, "IPoolable")) {
|
||||
obj["reset"]();
|
||||
}
|
||||
};
|
||||
Pool._objectQueue = new Array(10);
|
||||
return Pool;
|
||||
}());
|
||||
es.Pool = Pool;
|
||||
})(es || (es = {}));
|
||||
var RandomUtils = (function () {
|
||||
function RandomUtils() {
|
||||
}
|
||||
@@ -10476,7 +10517,7 @@ var es;
|
||||
for (var i = 0; i < this._logs.length; ++i)
|
||||
this._logs[i] = new FrameLog();
|
||||
this.sampleFrames = this.targetSampleFrames = 1;
|
||||
this.width = es.Core.graphicsDevice.viewport.width * 0.8;
|
||||
this.width = Math.floor(es.Core.graphicsDevice.viewport.width * 0.8);
|
||||
es.Core.emitter.addObserver(es.CoreEvents.GraphicsDeviceReset, this.onGraphicsDeviceReset, this);
|
||||
this.onGraphicsDeviceReset();
|
||||
}
|
||||
@@ -10629,7 +10670,7 @@ var es;
|
||||
}
|
||||
if (Math.max(this._frameAdjust) > TimeRuler.autoAdjustDelay) {
|
||||
this.sampleFrames = Math.min(TimeRuler.maxSampleFrames, this.sampleFrames);
|
||||
this.sampleFrames = Math.max(this.targetSampleFrames, (maxTime / frameSpan) + 1);
|
||||
this.sampleFrames = Math.max(this.targetSampleFrames, Math.floor(maxTime / frameSpan) + 1);
|
||||
this._frameAdjust = 0;
|
||||
}
|
||||
var msToPs = width / sampleSpan;
|
||||
@@ -10747,6 +10788,135 @@ var es;
|
||||
es.MarkerLog = MarkerLog;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var Coroutine = (function () {
|
||||
function Coroutine() {
|
||||
}
|
||||
Coroutine.waitForSeconds = function (seconds) {
|
||||
return WaitForSeconds.waiter.wait(seconds);
|
||||
};
|
||||
return Coroutine;
|
||||
}());
|
||||
es.Coroutine = Coroutine;
|
||||
var WaitForSeconds = (function () {
|
||||
function WaitForSeconds() {
|
||||
}
|
||||
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) {
|
||||
var CoroutineImpl = (function () {
|
||||
function CoroutineImpl() {
|
||||
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 = (function (_super) {
|
||||
__extends(CoroutineManager, _super);
|
||||
function CoroutineManager() {
|
||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||
_this._unblockedCoroutines = [];
|
||||
_this._shouldRunNextFrame = [];
|
||||
return _this;
|
||||
}
|
||||
CoroutineManager.prototype.startCoroutine = function (enumerator) {
|
||||
var coroutine = es.Pool.obtain(CoroutineImpl);
|
||||
coroutine.prepareForuse();
|
||||
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) {
|
||||
coroutine.waitTimer -= coroutine.useUnscaledDeltaTime ? es.Time.unscaledDeltaTime : es.Time.deltaTime;
|
||||
this._shouldRunNextFrame.push(coroutine);
|
||||
continue;
|
||||
}
|
||||
if (this.tickCoroutine(coroutine))
|
||||
this._shouldRunNextFrame.push(coroutine);
|
||||
}
|
||||
this._unblockedCoroutines.length = 0;
|
||||
this._unblockedCoroutines.concat(this._shouldRunNextFrame);
|
||||
this._shouldRunNextFrame.length = 0;
|
||||
this._isInUpdate = false;
|
||||
};
|
||||
CoroutineManager.prototype.tickCoroutine = function (coroutine) {
|
||||
if (!coroutine.enumerator.moveNext() || coroutine.isDone) {
|
||||
es.Pool.free(coroutine);
|
||||
return false;
|
||||
}
|
||||
if (coroutine.enumerator.current == null) {
|
||||
return true;
|
||||
}
|
||||
if (coroutine.enumerator.current instanceof es.WaitForSeconds) {
|
||||
coroutine.waitTimer = coroutine.enumerator.current.waitTime;
|
||||
return true;
|
||||
}
|
||||
if (coroutine.enumerator.current instanceof Number) {
|
||||
console.warn("协同程序检查返回一个Number类型,请不要在生产环境使用");
|
||||
coroutine.waitTimer = Number(coroutine.enumerator.current);
|
||||
return true;
|
||||
}
|
||||
if (coroutine.enumerator.current instanceof CoroutineImpl) {
|
||||
coroutine.waitForCoroutine = coroutine.enumerator.current;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return CoroutineManager;
|
||||
}(es.GlobalManager));
|
||||
es.CoroutineManager = CoroutineManager;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var TouchState = (function () {
|
||||
function TouchState() {
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -58,8 +58,8 @@ module es {
|
||||
this._scrollX += this.scrollSpeedX * Time.deltaTime;
|
||||
this._scrollY += this.scroolSpeedY * Time.deltaTime;
|
||||
|
||||
this._sourceRect.x = this._scrollX;
|
||||
this._sourceRect.y = this._scrollY;
|
||||
this._sourceRect.x = Math.floor(this._scrollX);
|
||||
this._sourceRect.y = Math.floor(this._scrollY);
|
||||
this._sourceRect.width = this._scrollWidth + Math.abs(this._scrollX);
|
||||
this._sourceRect.height = this._scrollHeight + Math.abs(this._scrollY);
|
||||
}
|
||||
|
||||
@@ -65,8 +65,8 @@ module es {
|
||||
|
||||
// 重新计算我们的inverseTextureScale和源矩形大小
|
||||
this._inverseTexScale = new Vector2(1 / this._textureScale.x, 1 / this._textureScale.y);
|
||||
this._sourceRect.width = this._sprite.sourceRect.width * this._inverseTexScale.x;
|
||||
this._sourceRect.height = this._sprite.sourceRect.height * this._inverseTexScale.y;
|
||||
this._sourceRect.width = Math.floor(this._sprite.sourceRect.width * this._inverseTexScale.x);
|
||||
this._sourceRect.height = Math.floor(this._sprite.sourceRect.height * this._inverseTexScale.y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,7 @@ module es {
|
||||
* 全局访问系统
|
||||
*/
|
||||
public _globalManagers: GlobalManager[] = [];
|
||||
public _coroutineManager: CoroutineManager = new CoroutineManager();
|
||||
public _timerManager: TimerManager = new TimerManager();
|
||||
|
||||
constructor() {
|
||||
@@ -40,6 +41,7 @@ module es {
|
||||
|
||||
this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
|
||||
|
||||
Core.registerGlobalManager(this._coroutineManager);
|
||||
Core.registerGlobalManager(this._timerManager);
|
||||
}
|
||||
|
||||
@@ -126,6 +128,15 @@ module es {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始了一个协同程序。协程可以使用number延迟几秒,也可以使其他对startCoroutine的调用延迟几秒。
|
||||
* 返回null将使协程在下一帧中被执行。
|
||||
* @param enumerator
|
||||
*/
|
||||
public static startCoroutine(enumerator: IEnumerator){
|
||||
return this._instance._coroutineManager.startCoroutine(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调度一个一次性或重复的计时器,该计时器将调用已传递的动作
|
||||
* @param timeInSeconds
|
||||
|
||||
@@ -33,7 +33,7 @@ module es {
|
||||
*/
|
||||
public static checkEvery(interval: number) {
|
||||
// 我们减去了delta,因为timeSinceSceneLoad已经包含了这个update ticks delta
|
||||
return (this._timeSinceSceneLoad / interval) > ((this._timeSinceSceneLoad - this.deltaTime) / interval);
|
||||
return Math.floor(this._timeSinceSceneLoad / interval) > Math.floor((this._timeSinceSceneLoad - this.deltaTime) / interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ module es {
|
||||
*/
|
||||
public update(amount: number){
|
||||
this.remainder += amount;
|
||||
let motion = Math.trunc(this.remainder);
|
||||
let motion = Math.floor(Math.trunc(this.remainder));
|
||||
this.remainder -= motion;
|
||||
amount = motion;
|
||||
return amount;
|
||||
|
||||
@@ -191,11 +191,11 @@ module es {
|
||||
|
||||
while (currentCell.x != lastCell.x || currentCell.y != lastCell.y){
|
||||
if (tMaxX < tMaxY){
|
||||
currentCell.x = MathHelper.approach(currentCell.x, lastCell.x, Math.abs(stepX));
|
||||
currentCell.x = Math.floor(MathHelper.approach(currentCell.x, lastCell.x, Math.abs(stepX)));
|
||||
|
||||
tMaxX += tDeltaX;
|
||||
}else{
|
||||
currentCell.y = MathHelper.approach(currentCell.y, lastCell.y, Math.abs(stepY));
|
||||
currentCell.y = Math.floor(MathHelper.approach(currentCell.y, lastCell.y, Math.abs(stepY)));
|
||||
|
||||
tMaxY += tDeltaY;
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ module es {
|
||||
rawGid &= ~(TmxLayerTile.FLIPPED_HORIZONTALLY_FLAG | TmxLayerTile.FLIPPED_VERTICALLY_FLAG);
|
||||
|
||||
// 将GID保存
|
||||
this.gid = rawGid;
|
||||
this.gid = Math.floor(rawGid);
|
||||
this.tileset = map.getTilesetForTileGid(this.gid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ module es {
|
||||
this._logs[i] = new FrameLog();
|
||||
|
||||
this.sampleFrames = this.targetSampleFrames = 1;
|
||||
this.width = Core.graphicsDevice.viewport.width * 0.8;
|
||||
this.width = Math.floor(Core.graphicsDevice.viewport.width * 0.8);
|
||||
|
||||
es.Core.emitter.addObserver(CoreEvents.GraphicsDeviceReset, this.onGraphicsDeviceReset, this);
|
||||
this.onGraphicsDeviceReset();
|
||||
@@ -269,7 +269,7 @@ module es {
|
||||
|
||||
if (Math.max(this._frameAdjust) > TimeRuler.autoAdjustDelay) {
|
||||
this.sampleFrames = Math.min(TimeRuler.maxSampleFrames, this.sampleFrames);
|
||||
this.sampleFrames = Math.max(this.targetSampleFrames, (maxTime / frameSpan) + 1);
|
||||
this.sampleFrames = Math.max(this.targetSampleFrames, Math.floor(maxTime / frameSpan) + 1);
|
||||
|
||||
this._frameAdjust = 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
module es {
|
||||
/**
|
||||
* startCoroutine返回的接口,提供了在执行中停止协同程序的能力
|
||||
*/
|
||||
export interface ICoroutine {
|
||||
/**
|
||||
* 停止协同程序
|
||||
*/
|
||||
stop();
|
||||
|
||||
/**
|
||||
* 设置协程应该使用时间增量还是使用非缩放时间增量来计时
|
||||
* @param useUnscaledDeltaTime
|
||||
*/
|
||||
setUseUnscaledDeltaTime(useUnscaledDeltaTime): ICoroutine;
|
||||
}
|
||||
|
||||
export class Coroutine {
|
||||
public static waitForSeconds(seconds: number){
|
||||
return WaitForSeconds.waiter.wait(seconds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 协作程序需要暂停一段时间时的助手类。
|
||||
* 返回协同程序。
|
||||
* waitForSeconds返回number。
|
||||
*/
|
||||
export class WaitForSeconds {
|
||||
public static waiter: WaitForSeconds = new WaitForSeconds();
|
||||
public waitTime: number;
|
||||
|
||||
public wait(seconds: number): WaitForSeconds {
|
||||
WaitForSeconds.waiter.waitTime = seconds;
|
||||
return WaitForSeconds.waiter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
module es {
|
||||
/**
|
||||
* CoroutineManager使用的内部类,用于隐藏协同程序所需的数据
|
||||
*/
|
||||
export class CoroutineImpl implements ICoroutine, IPoolable {
|
||||
public enumerator: IEnumerator;
|
||||
/**
|
||||
* 每当产生延迟时,它就被添加到跟踪延迟的waitTimer中
|
||||
*/
|
||||
public waitTimer: number;
|
||||
public isDone: boolean;
|
||||
public waitForCoroutine: CoroutineImpl;
|
||||
public useUnscaledDeltaTime: boolean = false;
|
||||
|
||||
public stop(){
|
||||
this.isDone = true;
|
||||
}
|
||||
|
||||
public setUseUnscaledDeltaTime(useUnscaledDeltaTime): es.ICoroutine {
|
||||
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 interface IEnumerator {
|
||||
current: any;
|
||||
moveNext(): boolean;
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* 基本CoroutineManager。协同程序可以做以下事情:
|
||||
* - return null(在下一帧继续执行)
|
||||
* - return Coroutine.waitForSeconds(3)。等待3秒(延时3秒后再次执行)
|
||||
* - return startCoroutine(another())(在再次执行之前等待另一个协程)
|
||||
*/
|
||||
export class CoroutineManager extends GlobalManager {
|
||||
/**
|
||||
* 标记来跟踪何时处于更新循环中。
|
||||
* 如果一个新的协程在更新循环期间启动,我们必须将其插入到shouldRunNextFrame列表中,以避免在迭代时修改列表。
|
||||
*/
|
||||
public _isInUpdate: boolean;
|
||||
|
||||
public _unblockedCoroutines: CoroutineImpl[] = [];
|
||||
public _shouldRunNextFrame: CoroutineImpl[] = [];
|
||||
|
||||
/**
|
||||
* 将i枚举器添加到CoroutineManager。协程在每一帧调用更新之前被执行。
|
||||
* @param enumerator
|
||||
*/
|
||||
public startCoroutine(enumerator: IEnumerator) {
|
||||
// 查找或创建CoroutineImpl
|
||||
let coroutine = Pool.obtain<CoroutineImpl>(CoroutineImpl);
|
||||
coroutine.prepareForuse();
|
||||
|
||||
// 设置协程并添加它
|
||||
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<CoroutineImpl>(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);
|
||||
}
|
||||
|
||||
this._unblockedCoroutines.length = 0;
|
||||
this._unblockedCoroutines.concat(this._shouldRunNextFrame);
|
||||
this._shouldRunNextFrame.length = 0;
|
||||
|
||||
this._isInUpdate = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果协同程序在下一帧继续运行,则返回true。此方法将把完成的协程放回池中!
|
||||
* @param coroutine
|
||||
*/
|
||||
public tickCoroutine(coroutine: CoroutineImpl){
|
||||
// 这个协同程序已经完成了
|
||||
if (!coroutine.enumerator.moveNext() || coroutine.isDone){
|
||||
Pool.free<CoroutineImpl>(coroutine);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (coroutine.enumerator.current == null){
|
||||
// 再运行下一帧
|
||||
return true;
|
||||
}
|
||||
|
||||
if (coroutine.enumerator.current instanceof WaitForSeconds){
|
||||
coroutine.waitTimer = (coroutine.enumerator.current as WaitForSeconds).waitTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (coroutine.enumerator.current instanceof Number){
|
||||
console.warn("协同程序检查返回一个Number类型,请不要在生产环境使用");
|
||||
coroutine.waitTimer = Number(coroutine.enumerator.current);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (coroutine.enumerator.current instanceof CoroutineImpl){
|
||||
coroutine.waitForCoroutine = coroutine.enumerator.current as CoroutineImpl;
|
||||
return true;
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
module es {
|
||||
/**
|
||||
* 用于池任何对象
|
||||
*/
|
||||
export class Pool<T> {
|
||||
private static _objectQueue = new Array(10);
|
||||
|
||||
/**
|
||||
* 预热缓存,使用最大的cacheCount对象填充缓存
|
||||
* @param type
|
||||
* @param cacheCount
|
||||
*/
|
||||
public static warmCache(type: any, cacheCount: number){
|
||||
cacheCount -= this._objectQueue.length;
|
||||
if (cacheCount > 0) {
|
||||
for (let i = 0; i < cacheCount; i++) {
|
||||
this._objectQueue.unshift(new type());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将缓存修剪为cacheCount项目
|
||||
* @param cacheCount
|
||||
*/
|
||||
public static trimCache(cacheCount: number){
|
||||
while (cacheCount > this._objectQueue.length)
|
||||
this._objectQueue.shift();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除缓存
|
||||
*/
|
||||
public static clearCache() {
|
||||
this._objectQueue.length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果可以的话,从堆栈中弹出一个项
|
||||
*/
|
||||
public static obtain<T>(type: any): T {
|
||||
if (this._objectQueue.length > 0)
|
||||
return this._objectQueue.shift();
|
||||
|
||||
return new type() as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将项推回堆栈
|
||||
* @param obj
|
||||
*/
|
||||
public static free<T>(obj: T) {
|
||||
this._objectQueue.unshift(obj);
|
||||
|
||||
if (egret.is(obj, "IPoolable")){
|
||||
obj["reset"]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface IPoolable {
|
||||
/**
|
||||
* 重置对象以供重用。对象引用应该为空,字段可以设置为默认值
|
||||
*/
|
||||
reset();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user