新增 CoroutineManager 协同程序

This commit is contained in:
yhh
2020-08-28 19:12:21 +08:00
parent 7a308f76b6
commit 358e899e8b
17 changed files with 760 additions and 35 deletions
+55
View File
@@ -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
View File
@@ -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() {
+1 -1
View File
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);
}
/**
+11
View File
@@ -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
+1 -1
View File
@@ -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);
}
}
}
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -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;
}
+1 -1
View File
@@ -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);
}
}
+2 -2
View File
@@ -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;
}
+38
View File
@@ -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;
}
}
}
}
+67
View File
@@ -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();
}
}