对ECS系统进行注释、移除JobSystem

This commit is contained in:
yhh
2023-03-13 17:46:16 +08:00
parent 78079252c9
commit 1adc5f1729
17 changed files with 936 additions and 837 deletions

View File

@@ -1668,31 +1668,12 @@ declare module es {
} }
declare module es { declare module es {
/** /**
* 追踪每个实体的冷却时间,当实体的计时器耗尽时进行处理 * 这个类是一个实体系统的基类,其可以被子类继承并在子类中实现具体的实体处理逻辑。
* * 该类提供了实体的添加、删除、更新等基本操作,并支持设置系统的更新时序、检查系统是否需要处理实体、获取系统的场景等方法
* 一个示例系统将是ExpirationSystem该系统将在特定生存期后删除实体。
* 你不必运行会为每个实体递减timeLeft值的系统
* 而只需使用此系统在寿命最短的实体时在将来执行
* 然后重置系统在未来的某一个最短命实体的时间运行
*
* 另一个例子是一个动画系统
* 你知道什么时候你必须对某个实体进行动画制作比如300毫秒内。
* 所以你可以设置系统以300毫秒为单位运行来执行动画
*
* 这将在某些情况下节省CPU周期
*/ */
abstract class DelayedIteratingSystem extends EntitySystem { abstract class DelayedIteratingSystem extends EntitySystem {
/**
* 一个实体应被处理的时间
*/
private delay; private delay;
/**
* 如果系统正在运行,并倒计时延迟
*/
private running; private running;
/**
* 倒计时
*/
private acc; private acc;
constructor(matcher: Matcher); constructor(matcher: Matcher);
protected process(entities: Entity[]): void; protected process(entities: Entity[]): void;
@@ -1702,30 +1683,17 @@ declare module es {
* 如果系统已经停止(不运行),那么提供的延迟将被用来重新启动系统,无论其值如何 * 如果系统已经停止(不运行),那么提供的延迟将被用来重新启动系统,无论其值如何
* 如果系统已经在倒计时,并且提供的延迟大于剩余时间,系统将忽略它。 * 如果系统已经在倒计时,并且提供的延迟大于剩余时间,系统将忽略它。
* 如果提供的延迟时间短于剩余时间,系统将重新启动,以提供的延迟时间运行。 * 如果提供的延迟时间短于剩余时间,系统将重新启动,以提供的延迟时间运行。
* @param offeredDelay * @param offeredDelay 提供的延迟时间,单位为秒
*/ */
offerDelay(offeredDelay: number): void; offerDelay(offeredDelay: number): void;
/**
* 处理本系统感兴趣的实体
* 从实体定义的延迟中抽象出accumulativeDelta
* @param entity
* @param accumulatedDelta 本系统最后一次执行后的delta时间
*/
protected abstract processDelta(entity: Entity, accumulatedDelta: number): any;
protected abstract processExpired(entity: Entity): any;
/**
* 返回该实体处理前的延迟时间
* @param entity
*/
protected abstract getRemainingDelay(entity: Entity): number;
/** /**
* 获取系统被命令处理实体后的初始延迟 * 获取系统被命令处理实体后的初始延迟
*/ */
getInitialTimeDelay(): number; getInitialTimeDelay(): number;
/** /**
* 获取系统计划运行前的时间 * 获取系统计划运行前的时间
* 如果系统没有运行,则返回零 * 如果系统没有运行,则返回零
*/ */
getRemainingTimeUntilProcessing(): number; getRemainingTimeUntilProcessing(): number;
/** /**
* 检查系统是否正在倒计时处理 * 检查系统是否正在倒计时处理
@@ -1735,51 +1703,101 @@ declare module es {
* 停止系统运行,中止当前倒计时 * 停止系统运行,中止当前倒计时
*/ */
stop(): void; stop(): void;
/**
* 处理给定实体的延迟时间的一部分,抽象出累积的 Delta 值。
* @param entity 要处理的实体
* @param accumulatedDelta 本系统最后一次执行后的累积 delta 时间
*/
protected abstract processDelta(entity: Entity, accumulatedDelta: number): any;
/**
* 处理已到期的实体。
* @param entity 要处理的实体
*/
protected abstract processExpired(entity: Entity): any;
/**
* 获取给定实体剩余的延迟时间。
* @param entity 要检查的实体
* @returns 剩余的延迟时间(以秒为单位)
*/
protected abstract getRemainingDelay(entity: Entity): number;
} }
} }
declare module es { declare module es {
/** /**
* 基本实体处理系统。将其用作处理具有特定组件的许多实体的基础 * 定义一个处理实体的抽象类,继承自 EntitySystem 类。
* * 子类需要实现 processEntity 方法,用于实现具体的实体处理逻辑。
* 按实体引用遍历实体订阅成员实体的系统
* 当你需要处理与Matcher相匹配的实体并且你更喜欢使用Entity的时候可以使用这个功能。
*/ */
abstract class EntityProcessingSystem extends EntitySystem { abstract class EntityProcessingSystem extends EntitySystem {
/**
* 是否启用系统,默认为启用。
*/
enabled: boolean; enabled: boolean;
/**
* 构造函数,初始化实体匹配器。
* @param matcher 实体匹配器
*/
constructor(matcher: Matcher); constructor(matcher: Matcher);
/** /**
* 处理特定的实体 * 处理单个实体,由子类实现。
* @param entity * @param entity 待处理的实体
*/
abstract processEntity(entity: Entity): void;
/**
* 在晚于 update 的时间更新实体,由子类实现。
* @param entity 待处理的实体
*/ */
abstract processEntity(entity: Entity): any;
lateProcessEntity(entity: Entity): void; lateProcessEntity(entity: Entity): void;
/** /**
* 遍历这个系统的所有实体逐个处理它们 * 遍历系统的所有实体逐个进行实体处理。
* @param entities * @param entities 实体数组
*/ */
protected process(entities: Entity[]): void; protected process(entities: Entity[]): void;
/**
* 在晚于 update 的时间更新实体。
* @param entities 实体数组
*/
protected lateProcess(entities: Entity[]): void; protected lateProcess(entities: Entity[]): void;
/**
* 判断系统是否需要进行实体处理。
* 如果启用了系统,则需要进行实体处理,返回 true
* 否则不需要进行实体处理,返回 false。
*/
protected checkProcessing(): boolean; protected checkProcessing(): boolean;
} }
} }
declare module es { declare module es {
/** /**
* 实体系统以一定的时间间隔进行处理 * 定义一个按时间间隔处理的抽象类,继承自 EntitySystem 类。
* 子类需要实现 process 方法,用于实现具体的处理逻辑。
*/ */
abstract class IntervalSystem extends EntitySystem { abstract class IntervalSystem extends EntitySystem {
/** /**
* 累积增量以跟踪间隔 * 累积增量以跟踪间隔
*/ */
protected acc: number; private acc;
/** /**
* 更新之间需要等待多长时间 * 更新之间需要等待多长时间
*/ */
private readonly interval; private readonly interval;
private intervalDelta; /**
* 时间间隔的余数,用于计算下一次需要等待的时间
*/
private intervalRemainder;
/**
* 构造函数,初始化时间间隔。
* @param matcher 实体匹配器
* @param interval 时间间隔
*/
constructor(matcher: Matcher, interval: number); constructor(matcher: Matcher, interval: number);
/**
* 判断是否需要进行处理。
* 如果需要进行处理,则更新累积增量和时间间隔余数,返回 true
* 否则返回 false。
*/
protected checkProcessing(): boolean; protected checkProcessing(): boolean;
/** /**
* 获取本系统上次处理后的实际delta * 获取本系统上次处理后的实际 delta 值。
* 实际 delta 值等于时间间隔加上时间间隔余数。
*/ */
protected getIntervalDelta(): number; protected getIntervalDelta(): number;
} }
@@ -1804,52 +1822,42 @@ declare module es {
} }
declare module es { declare module es {
/** /**
* JobSystem使用实体的子集调用Executeentities并在指定数量的线程上分配工作负载 * 定义一个被动的实体系统,继承自 EntitySystem 类
* 被动的实体系统不会对实体进行任何修改,只会被动地接收实体的变化事件。
*/ */
abstract class JobSystem extends EntitySystem {
readonly _threads: number;
readonly _jobs: Job[];
readonly _executeStr: string;
constructor(matcher: Matcher, threads: number);
protected process(entities: Entity[]): void;
private queueOnThread;
/**
* 当操作完成时,改变的值需要用户进行手动传递
* 由于worker数据无法共享所以这块需要特殊处理
* @example this.test = job[0].context.test;
* @param job
*/
protected abstract resetJob(job: Job): any;
/**
* 对指定实体进行多线程操作
* @param entity
*/
protected abstract execute(entity: Entity): any;
}
class Job {
entities: Entity[];
from: number;
to: number;
worker: Worker;
execute: string;
err: string;
context: any;
set(entities: Entity[], from: number, to: number, execute: string, context: any): void;
}
}
declare module es {
abstract class PassiveSystem extends EntitySystem { abstract class PassiveSystem extends EntitySystem {
/**
* 当实体发生变化时,不进行任何操作。
* @param entity 发生变化的实体
*/
onChanged(entity: Entity): void; onChanged(entity: Entity): void;
/**
* 不进行任何处理,只进行开始和结束计时。
* @param entities 实体数组,未被使用
*/
protected process(entities: Entity[]): void; protected process(entities: Entity[]): void;
} }
} }
/** 用于协调其他系统的通用系统基类 */
declare module es { declare module es {
/**
* 定义一个处理实体的抽象类,继承自 EntitySystem 类。
* 子类需要实现 processSystem 方法,用于实现具体的处理逻辑。
*/
abstract class ProcessingSystem extends EntitySystem { abstract class ProcessingSystem extends EntitySystem {
/**
* 当实体发生变化时,不进行任何操作。
* @param entity 发生变化的实体
*/
onChanged(entity: Entity): void; onChanged(entity: Entity): void;
/** 处理我们的系统 每帧调用 */ /**
abstract processSystem(): any; * 处理实体,每帧调用 processSystem 方法进行处理。
* @param entities 实体数组,未被使用
*/
protected process(entities: Entity[]): void; protected process(entities: Entity[]): void;
/**
* 处理实体的具体方法,由子类实现。
*/
abstract processSystem(): void;
} }
} }
declare module es { declare module es {
@@ -1939,19 +1947,52 @@ declare module es {
} }
} }
declare module es { declare module es {
/**
* 组件类型工厂,用于生成和管理组件类型。
* 维护了一个类型映射表,将组件类型与其唯一索引相对应,以便在运行时高效地检查实体是否包含特定的组件类型。
*/
class ComponentTypeFactory { class ComponentTypeFactory {
private componentTypes_; /** 组件类型与其唯一索引的映射表 */
private componentTypeCount_; private componentTypes;
types: Bag<ComponentType>; /** 组件类型列表,按索引访问组件类型 */
constructor(); readonly types: Bag<ComponentType>;
getTypeFor(c: any): ComponentType; /** 当前组件类型的计数器 */
getIndexFor(c: any): number; private componentTypeCount;
/**
* 获取给定组件类型的唯一索引。
* 如果该组件类型尚未存在于类型映射表中,则创建一个新的组件类型,并将其添加到映射表和类型列表中。
* @param c 要查找或创建的组件类型
* @returns 组件类型的唯一索引
*/
getIndexFor(c: new (...args: any[]) => any): number;
/**
* 获取给定组件类型的ComponentType对象。
* 如果该组件类型尚未存在于类型映射表中则创建一个新的ComponentType对象并将其添加到映射表和类型列表中。
* @param c 要查找或创建的组件类型
* @returns 组件类型的ComponentType对象
*/
getTypeFor(c: new (...args: any[]) => any): ComponentType;
} }
} }
declare module es { declare module es {
/**
* 组件类型管理器,维护了一个组件类型和它们对应的位掩码之间的映射关系。
* 用于实现实体匹配器中组件类型的比较操作,以确定实体是否符合给定的匹配器条件。
*/
class ComponentTypeManager { class ComponentTypeManager {
/** 存储组件类型和它们对应的位掩码的Map */
private static _componentTypesMask; private static _componentTypesMask;
/**
* 将给定的组件类型添加到组件类型列表中,并分配一个唯一的位掩码。
* @param type 要添加的组件类型
*/
static add(type: any): void; static add(type: any): void;
/**
* 获取给定组件类型的位掩码。
* 如果该组件类型还没有分配位掩码,则将其添加到列表中,并分配一个唯一的位掩码。
* @param type 要获取位掩码的组件类型
* @returns 组件类型的位掩码
*/
static getIndexFor(type: any): number; static getIndexFor(type: any): number;
} }
} }
@@ -2119,6 +2160,9 @@ declare module es {
} }
} }
declare module es { declare module es {
/**
* 定义一个实体匹配器类。
*/
class Matcher { class Matcher {
protected allSet: (new (...args: any[]) => Component)[]; protected allSet: (new (...args: any[]) => Component)[];
protected exclusionSet: (new (...args: any[]) => Component)[]; protected exclusionSet: (new (...args: any[]) => Component)[];
@@ -2129,9 +2173,21 @@ declare module es {
getOneSet(): (new (...args: any[]) => Component)[]; getOneSet(): (new (...args: any[]) => Component)[];
isInterestedEntity(e: Entity): boolean; isInterestedEntity(e: Entity): boolean;
isInterested(components: Bits): boolean; isInterested(components: Bits): boolean;
all(...types: any[]): Matcher; /**
exclude(...types: any[]): this; * 添加所有包含的组件类型。
one(...types: any[]): this; * @param types 所有包含的组件类型列表
*/
all(...types: (new (...args: any[]) => Component)[]): Matcher;
/**
* 添加排除包含的组件类型。
* @param types 排除包含的组件类型列表
*/
exclude(...types: (new (...args: any[]) => Component)[]): Matcher;
/**
* 添加至少包含其中之一的组件类型。
* @param types 至少包含其中之一的组件类型列表
*/
one(...types: (new (...args: any[]) => Component)[]): Matcher;
} }
} }
declare module es { declare module es {
@@ -2324,23 +2380,6 @@ declare class TimeUtils {
*/ */
static timeToMillisecond(time: string, partition?: string): string; static timeToMillisecond(time: string, partition?: string): string;
} }
declare module es {
/**
* 开辟一个新线程
* 注意:它无法获得主线程中的上下文
*/
class WorkerUtils {
/** 正在执行的队列 */
private static readonly pendingJobs;
private static jobIdGen;
/**
* 创建一个worker
* @param doFunc worker所能做的事情
*/
static makeWorker(doFunc: Function): Worker;
static workerMessage(worker: Worker): (...message: any[]) => Promise<{}>;
}
}
declare module es { declare module es {
/** /**
* 三次方和二次方贝塞尔帮助器(cubic and quadratic bezier helper) * 三次方和二次方贝塞尔帮助器(cubic and quadratic bezier helper)
@@ -4697,6 +4736,12 @@ declare module es {
* @param data 事件数据 * @param data 事件数据
*/ */
emit(eventType: T, ...data: any[]): void; emit(eventType: T, ...data: any[]): void;
/**
* 判断是否存在该类型的观察者
* @param eventType 事件类型
* @param handler 事件函数
*/
hasObserver(eventType: T, handler: Function): boolean;
} }
} }
declare module es { declare module es {
@@ -5173,44 +5218,46 @@ declare module es {
} }
} }
declare module es { declare module es {
/**
* 用于池任何对象
*/
class Pool { class Pool {
private static _objectQueue; private static _objectQueue;
/** /**
* 预热缓存使用最大的cacheCount对象填充缓存 * 预热缓存使用最大的cacheCount对象填充缓存
* @param type * @param type 要预热的类型
* @param cacheCount * @param cacheCount 预热缓存数量
*/ */
static warmCache<T>(type: new (...args: any[]) => T, cacheCount: number): void; static warmCache<T>(type: new (...args: any[]) => T, cacheCount: number): void;
/** /**
* 将缓存修剪为cacheCount项目 * 将缓存修剪为cacheCount项目
* @param cacheCount * @param type 要修剪的类型
*/ * @param cacheCount 修剪后的缓存数量
*/
static trimCache<T>(type: new (...args: any[]) => T, cacheCount: number): void; static trimCache<T>(type: new (...args: any[]) => T, cacheCount: number): void;
/** /**
* 清除缓存 * 清除缓存
* @param type 要清除缓存的类型
*/ */
static clearCache<T>(type: new (...args: any[]) => T): void; static clearCache<T>(type: new (...args: any[]) => T): void;
/** /**
* 如果可以的话,从堆栈中弹出一个项 * 如果可以的话,从缓存中获取一个对象
* @param type 要获取的类型
*/ */
static obtain<T>(type: new (...args: any[]) => T): T; static obtain<T>(type: new (...args: any[]) => T): T;
/** /**
* 将项推回堆栈 * 将对象推回缓存
* @param obj * @param type 对象的类型
* @param obj 要推回的对象
*/ */
static free<T>(type: new (...args: any[]) => T, obj: T): void; static free<T>(type: new (...args: any[]) => T, obj: T): void;
/**
* 检查缓存中是否已存在给定类型的对象池,如果不存在则创建一个
* @param type 要检查的类型
*/
private static checkCreate; private static checkCreate;
} }
interface IPoolable { interface IPoolable {
/** reset(): void;
* 重置对象以供重用。对象引用应该为空,字段可以设置为默认值
*/
reset(): any;
} }
var isIPoolable: (props: any) => props is IPoolable; const isIPoolable: (props: any) => props is IPoolable;
} }
declare module es { declare module es {
/** /**
@@ -5248,7 +5295,7 @@ declare module es {
* CoroutineManager用于隐藏Coroutine所需数据的内部类 * CoroutineManager用于隐藏Coroutine所需数据的内部类
*/ */
class CoroutineImpl implements ICoroutine, IPoolable { class CoroutineImpl implements ICoroutine, IPoolable {
enumerator: Generator; enumerator: any;
/** /**
* 每当产生一个延迟它就会被添加到跟踪延迟的waitTimer中 * 每当产生一个延迟它就会被添加到跟踪延迟的waitTimer中
*/ */
@@ -5278,7 +5325,9 @@ declare module es {
* Coroutine在每一帧调用Update之前被执行 * Coroutine在每一帧调用Update之前被执行
* @param enumerator * @param enumerator
*/ */
startCoroutine(enumerator: any): CoroutineImpl; startCoroutine<T>(enumerator: Iterator<T> | (() => Iterator<T>)): CoroutineImpl | null;
private getOrCreateCoroutine;
private addCoroutine;
update(): void; update(): void;
/** /**
* 勾选一个coroutine如果该coroutine应该在下一帧继续运行则返回true。本方法会将完成的coroutine放回Pool * 勾选一个coroutine如果该coroutine应该在下一帧继续运行则返回true。本方法会将完成的coroutine放回Pool

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -164,17 +164,23 @@ module es {
} }
public startDebugDraw() { public startDebugDraw() {
// 如果debug标志未开启则直接返回
if (!this.debug) return; if (!this.debug) return;
this._frameCounter++;
this._frameCounterElapsedTime += Time.deltaTime; // 计算帧率和内存使用情况
if (this._frameCounterElapsedTime >= 1) { this._frameCounter++; // 帧计数器递增
let memoryInfo = window.performance["memory"]; this._frameCounterElapsedTime += Time.deltaTime; // 帧计数器累加时间
if (memoryInfo != null) { if (this._frameCounterElapsedTime >= 1) { // 如果时间已经超过1秒则计算帧率和内存使用情况
let memoryInfo = window.performance["memory"]; // 获取内存使用情况
if (memoryInfo != null) { // 如果内存使用情况存在
// 计算内存使用情况并保留2位小数
this._totalMemory = Number((memoryInfo.totalJSHeapSize / 1048576).toFixed(2)); this._totalMemory = Number((memoryInfo.totalJSHeapSize / 1048576).toFixed(2));
} }
if (this._titleMemory) this._titleMemory(this._totalMemory, this._frameCounter); if (this._titleMemory) { // 如果回调函数存在,则执行回调函数,更新标题栏显示
this._frameCounter = 0; this._titleMemory(this._totalMemory, this._frameCounter);
this._frameCounterElapsedTime -= 1; }
this._frameCounter = 0; // 重置帧计数器
this._frameCounterElapsedTime -= 1; // 减去1秒时间
} }
} }

View File

@@ -1,51 +1,35 @@
///<reference path="./EntitySystem.ts"/> ///<reference path="./EntitySystem.ts"/>
module es { module es {
/** /**
* 追踪每个实体的冷却时间,当实体的计时器耗尽时进行处理 * 这个类是一个实体系统的基类,其可以被子类继承并在子类中实现具体的实体处理逻辑。
* * 该类提供了实体的添加、删除、更新等基本操作,并支持设置系统的更新时序、检查系统是否需要处理实体、获取系统的场景等方法
* 一个示例系统将是ExpirationSystem该系统将在特定生存期后删除实体。
* 你不必运行会为每个实体递减timeLeft值的系统
* 而只需使用此系统在寿命最短的实体时在将来执行
* 然后重置系统在未来的某一个最短命实体的时间运行
*
* 另一个例子是一个动画系统
* 你知道什么时候你必须对某个实体进行动画制作比如300毫秒内。
* 所以你可以设置系统以300毫秒为单位运行来执行动画
*
* 这将在某些情况下节省CPU周期
*/ */
export abstract class DelayedIteratingSystem extends EntitySystem { export abstract class DelayedIteratingSystem extends EntitySystem {
/** private delay = 0;
* 一个实体应被处理的时间 private running = false;
*/ private acc = 0;
private delay: number = 0;
/**
* 如果系统正在运行,并倒计时延迟
*/
private running: boolean = false;
/**
* 倒计时
*/
private acc: number = 0;
constructor(matcher: Matcher) { constructor(matcher: Matcher) {
super(matcher); super(matcher);
} }
protected process(entities: Entity[]) { protected process(entities: Entity[]) {
let processed = entities.length; const processed = entities.length;
if (processed == 0) {
if (processed === 0) {
this.stop(); this.stop();
return; return;
} }
this.delay = Number.MAX_VALUE; this.delay = Number.MAX_VALUE;
for (let i = 0; processed > i; i++) {
let e = entities[i]; for (let i = 0; i < processed; i++) {
this.processDelta(e, this.acc); const entity = entities[i];
let remaining = this.getRemainingDelay(e); this.processDelta(entity, this.acc);
const remaining = this.getRemainingDelay(entity);
if (remaining <= 0) { if (remaining <= 0) {
this.processExpired(e); this.processExpired(entity);
} else { } else {
this.offerDelay(remaining); this.offerDelay(remaining);
} }
@@ -59,6 +43,7 @@ module es {
this.acc += Time.deltaTime; this.acc += Time.deltaTime;
return this.acc >= this.delay; return this.acc >= this.delay;
} }
return false; return false;
} }
@@ -67,7 +52,7 @@ module es {
* 如果系统已经停止(不运行),那么提供的延迟将被用来重新启动系统,无论其值如何 * 如果系统已经停止(不运行),那么提供的延迟将被用来重新启动系统,无论其值如何
* 如果系统已经在倒计时,并且提供的延迟大于剩余时间,系统将忽略它。 * 如果系统已经在倒计时,并且提供的延迟大于剩余时间,系统将忽略它。
* 如果提供的延迟时间短于剩余时间,系统将重新启动,以提供的延迟时间运行。 * 如果提供的延迟时间短于剩余时间,系统将重新启动,以提供的延迟时间运行。
* @param offeredDelay * @param offeredDelay 提供的延迟时间,单位为秒
*/ */
public offerDelay(offeredDelay: number) { public offerDelay(offeredDelay: number) {
if (!this.running) { if (!this.running) {
@@ -78,22 +63,6 @@ module es {
} }
} }
/**
* 处理本系统感兴趣的实体
* 从实体定义的延迟中抽象出accumulativeDelta
* @param entity
* @param accumulatedDelta 本系统最后一次执行后的delta时间
*/
protected abstract processDelta(entity: Entity, accumulatedDelta: number);
protected abstract processExpired(entity: Entity);
/**
* 返回该实体处理前的延迟时间
* @param entity
*/
protected abstract getRemainingDelay(entity: Entity): number;
/** /**
* 获取系统被命令处理实体后的初始延迟 * 获取系统被命令处理实体后的初始延迟
*/ */
@@ -102,9 +71,9 @@ module es {
} }
/** /**
* 获取系统计划运行前的时间 * 获取系统计划运行前的时间
* 如果系统没有运行,则返回零 * 如果系统没有运行,则返回零
*/ */
public getRemainingTimeUntilProcessing(): number { public getRemainingTimeUntilProcessing(): number {
if (this.running) { if (this.running) {
return this.delay - this.acc; return this.delay - this.acc;
@@ -127,5 +96,25 @@ module es {
this.running = false; this.running = false;
this.acc = 0; this.acc = 0;
} }
/**
* 处理给定实体的延迟时间的一部分,抽象出累积的 Delta 值。
* @param entity 要处理的实体
* @param accumulatedDelta 本系统最后一次执行后的累积 delta 时间
*/
protected abstract processDelta(entity: Entity, accumulatedDelta: number);
/**
* 处理已到期的实体。
* @param entity 要处理的实体
*/
protected abstract processExpired(entity: Entity);
/**
* 获取给定实体剩余的延迟时间。
* @param entity 要检查的实体
* @returns 剩余的延迟时间(以秒为单位)
*/
protected abstract getRemainingDelay(entity: Entity): number;
} }
} }

View File

@@ -1,53 +1,76 @@
///<reference path="./EntitySystem.ts" /> ///<reference path="./EntitySystem.ts" />
module es { module es {
/** /**
* 基本实体处理系统。将其用作处理具有特定组件的许多实体的基础 * 定义一个处理实体的抽象类,继承自 EntitySystem 类。
* * 子类需要实现 processEntity 方法,用于实现具体的实体处理逻辑。
* 按实体引用遍历实体订阅成员实体的系统
* 当你需要处理与Matcher相匹配的实体并且你更喜欢使用Entity的时候可以使用这个功能。
*/ */
export abstract class EntityProcessingSystem extends EntitySystem { export abstract class EntityProcessingSystem extends EntitySystem {
/**
* 是否启用系统,默认为启用。
*/
public enabled: boolean = true; public enabled: boolean = true;
/**
* 构造函数,初始化实体匹配器。
* @param matcher 实体匹配器
*/
constructor(matcher: Matcher) { constructor(matcher: Matcher) {
super(matcher); super(matcher);
} }
/**
* 处理单个实体,由子类实现。
* @param entity 待处理的实体
*/
public abstract processEntity(entity: Entity): void;
/** /**
* 处理特定的实体 * 在晚于 update 的时间更新实体,由子类实现。
* @param entity * @param entity 待处理的实体
*/ */
public abstract processEntity(entity: Entity); public lateProcessEntity(entity: Entity): void {
// do nothing
public lateProcessEntity(entity: Entity) {
} }
/** /**
* 遍历这个系统的所有实体逐个处理它们 * 遍历系统的所有实体逐个进行实体处理。
* @param entities * @param entities 实体数组
*/ */
protected process(entities: Entity[]) { protected process(entities: Entity[]) {
if (entities.length == 0) // 如果实体数组为空,则直接返回
if (entities.length === 0) {
return; return;
}
for (let i = 0, s = entities.length; i < s; ++ i) {
let entity = entities[i]; // 遍历实体数组,逐个进行实体处理
for (let i = 0, len = entities.length; i < len; i++) {
const entity = entities[i];
this.processEntity(entity); this.processEntity(entity);
} }
} }
/**
* 在晚于 update 的时间更新实体。
* @param entities 实体数组
*/
protected lateProcess(entities: Entity[]) { protected lateProcess(entities: Entity[]) {
if (entities.length == 0) // 如果实体数组为空,则直接返回
if (entities.length === 0) {
return; return;
}
for (let i = 0, s = entities.length; i < s; ++ i) { // 遍历实体数组,逐个进行实体处理
let entity = entities[i]; for (let i = 0, len = entities.length; i < len; i++) {
const entity = entities[i];
this.lateProcessEntity(entity); this.lateProcessEntity(entity);
} }
} }
/**
* 判断系统是否需要进行实体处理。
* 如果启用了系统,则需要进行实体处理,返回 true
* 否则不需要进行实体处理,返回 false。
*/
protected checkProcessing(): boolean { protected checkProcessing(): boolean {
return this.enabled; return this.enabled;
} }

View File

@@ -1,40 +1,63 @@
module es { module es {
/** /**
* 实体系统以一定的时间间隔进行处理 * 定义一个按时间间隔处理的抽象类,继承自 EntitySystem 类。
* 子类需要实现 process 方法,用于实现具体的处理逻辑。
*/ */
export abstract class IntervalSystem extends EntitySystem { export abstract class IntervalSystem extends EntitySystem {
/** /**
* 累积增量以跟踪间隔 * 累积增量以跟踪间隔
*/ */
protected acc: number = 0; private acc: number = 0;
/** /**
* 更新之间需要等待多长时间 * 更新之间需要等待多长时间
*/ */
private readonly interval: number = 0; private readonly interval: number;
private intervalDelta: number = 0;
/**
* 时间间隔的余数,用于计算下一次需要等待的时间
*/
private intervalRemainder: number = 0;
/**
* 构造函数,初始化时间间隔。
* @param matcher 实体匹配器
* @param interval 时间间隔
*/
constructor(matcher: Matcher, interval: number) { constructor(matcher: Matcher, interval: number) {
super(matcher); super(matcher);
this.interval = interval; this.interval = interval;
} }
protected checkProcessing() { /**
* 判断是否需要进行处理。
* 如果需要进行处理,则更新累积增量和时间间隔余数,返回 true
* 否则返回 false。
*/
protected checkProcessing(): boolean {
// 更新累积增量
this.acc += Time.deltaTime; this.acc += Time.deltaTime;
if (this.acc >= this.interval) {
this.acc -= this.interval;
this.intervalDelta = (this.acc - this.intervalDelta);
// 如果累积增量超过时间间隔,则进行处理
if (this.acc >= this.interval) {
// 更新时间间隔余数
this.intervalRemainder = this.acc - this.interval;
// 重置累积增量
this.acc = 0;
// 返回 true表示需要进行处理
return true; return true;
} }
// 返回 false表示不需要进行处理
return false; return false;
} }
/** /**
* 获取本系统上次处理后的实际delta * 获取本系统上次处理后的实际 delta 值。
* 实际 delta 值等于时间间隔加上时间间隔余数。
*/ */
protected getIntervalDelta() { protected getIntervalDelta(): number {
return this.interval + this.intervalDelta; return this.interval + this.intervalRemainder;
} }
} }
} }

View File

@@ -1,102 +0,0 @@
module es {
/**
* JobSystem使用实体的子集调用Executeentities并在指定数量的线程上分配工作负载。
*/
export abstract class JobSystem extends EntitySystem {
public readonly _threads: number;
public readonly _jobs: Job[];
public readonly _executeStr: string;
constructor(matcher: Matcher, threads: number) {
super(matcher);
this._threads = threads;
this._jobs = new Array(threads);
for (let i = 0; i < this._jobs.length; i++) {
this._jobs[i] = new Job();
}
this._executeStr = JSON.stringify(this.execute, function (key, val) {
if (typeof val === 'function') {
return val + '';
}
return val;
});
}
protected process(entities: Entity[]) {
let remainder = entities.length & this._threads;
let slice = entities.length / this._threads + (remainder == 0 ? 0 : 1);
for (let t = 0; t < this._threads; t++) {
let from = t * slice;
let to = from + slice;
if (to > entities.length) {
to = entities.length;
}
let job = this._jobs[t];
job.set(entities, from, to, this._executeStr, this);
if (from != to) {
const worker = WorkerUtils.makeWorker(this.queueOnThread);
const workerDo = WorkerUtils.workerMessage(worker);
workerDo(job).then((message) => {
let job = message as Job;
this.resetJob(job);
worker.terminate();
}).catch((err) => {
job.err = err;
worker.terminate();
});
}
}
}
private queueOnThread() {
onmessage = ({ data: { jobId, message } }) => {
let job = message[0] as Job;
let executeFunc: Function = JSON.parse(job.execute, function (k, v) {
if (v.indexOf && v.indexOf('function') > -1) {
return eval("(function(){return " + v + " })()")
}
return v;
});
for (let i = job.from; i < job.to; i++) {
executeFunc.call(job.context, job.entities[i]);
}
postMessage({ jobId, result: message }, null);
};
}
/**
* 当操作完成时,改变的值需要用户进行手动传递
* 由于worker数据无法共享所以这块需要特殊处理
* @example this.test = job[0].context.test;
* @param job
*/
protected abstract resetJob(job: Job);
/**
* 对指定实体进行多线程操作
* @param entity
*/
protected abstract execute(entity: Entity);
}
class Job {
public entities: Entity[];
public from: number;
public to: number;
public worker: Worker;
public execute: string;
public err: string;
public context;
public set(entities: Entity[], from: number, to: number, execute: string, context: any) {
this.entities = entities;
this.from = from;
this.to = to;
this.execute = execute;
this.context = context;
}
}
}

View File

@@ -1,11 +1,21 @@
module es { module es {
/**
* 定义一个被动的实体系统,继承自 EntitySystem 类。
* 被动的实体系统不会对实体进行任何修改,只会被动地接收实体的变化事件。
*/
export abstract class PassiveSystem extends EntitySystem { export abstract class PassiveSystem extends EntitySystem {
public onChanged(entity: Entity) { /**
* 当实体发生变化时,不进行任何操作。
} * @param entity 发生变化的实体
*/
public onChanged(entity: Entity) { }
/**
* 不进行任何处理,只进行开始和结束计时。
* @param entities 实体数组,未被使用
*/
protected process(entities: Entity[]) { protected process(entities: Entity[]) {
// 我们用我们自己的不考虑实体的基本实体系统来代替 // 调用 begin 和 end 方法,开始和结束计时
this.begin(); this.begin();
this.end(); this.end();
} }

View File

@@ -1,17 +1,30 @@
/** 用于协调其他系统的通用系统基类 */
module es { module es {
/**
* 定义一个处理实体的抽象类,继承自 EntitySystem 类。
* 子类需要实现 processSystem 方法,用于实现具体的处理逻辑。
*/
export abstract class ProcessingSystem extends EntitySystem { export abstract class ProcessingSystem extends EntitySystem {
public onChanged(entity: Entity) { /**
* 当实体发生变化时,不进行任何操作。
} * @param entity 发生变化的实体
*/
/** 处理我们的系统 每帧调用 */ public onChanged(entity: Entity) { }
public abstract processSystem();
/**
* 处理实体,每帧调用 processSystem 方法进行处理。
* @param entities 实体数组,未被使用
*/
protected process(entities: Entity[]) { protected process(entities: Entity[]) {
// 调用 begin 和 end 方法,开始和结束计时
this.begin(); this.begin();
// 调用子类实现的 processSystem 方法进行实体处理
this.processSystem(); this.processSystem();
this.end(); this.end();
} }
/**
* 处理实体的具体方法,由子类实现。
*/
public abstract processSystem(): void;
} }
} }

View File

@@ -1,39 +1,51 @@
module es { module es {
interface IdentityHashMap { /**
[key: string]: ComponentType; * 组件类型工厂,用于生成和管理组件类型。
} * 维护了一个类型映射表,将组件类型与其唯一索引相对应,以便在运行时高效地检查实体是否包含特定的组件类型。
*/
export class ComponentTypeFactory { export class ComponentTypeFactory {
private componentTypes_: IdentityHashMap; /** 组件类型与其唯一索引的映射表 */
private componentTypes: Record<string, ComponentType> = {};
/** 组件类型列表,按索引访问组件类型 */
public readonly types: Bag<ComponentType> = new Bag<ComponentType>();
/** 当前组件类型的计数器 */
private componentTypeCount = 0;
private componentTypeCount_ = 0; /**
* 获取给定组件类型的唯一索引。
public types: Bag<ComponentType>; * 如果该组件类型尚未存在于类型映射表中,则创建一个新的组件类型,并将其添加到映射表和类型列表中。
* @param c 要查找或创建的组件类型
constructor() { * @returns 组件类型的唯一索引
this.componentTypes_ = {}; */
this.types = new Bag<ComponentType>(); public getIndexFor(c: new (...args: any[]) => any): number {
return this.getTypeFor(c).getIndex();
} }
public getTypeFor(c): ComponentType { /**
if ("number" === typeof c) { * 获取给定组件类型的ComponentType对象。
* 如果该组件类型尚未存在于类型映射表中则创建一个新的ComponentType对象并将其添加到映射表和类型列表中。
* @param c 要查找或创建的组件类型
* @returns 组件类型的ComponentType对象
*/
public getTypeFor(c: new (...args: any[]) => any): ComponentType {
// 如果给定的组件类型是一个已有的索引则直接返回对应的ComponentType对象
if (typeof c === "number") {
return this.types.get(c); return this.types.get(c);
} }
let type: ComponentType = this.componentTypes_[getClassName(c)]; // 获取给定组件类型对应的类名
const className = getClassName(c);
if (type == null) { // 如果类型映射表中不存在该组件类型则创建一个新的ComponentType对象
const index: number = this.componentTypeCount_++; if (!this.componentTypes[className]) {
type = new ComponentType(c, index); const index = this.componentTypeCount++;
this.componentTypes_[getClassName(c)] = type; const type = new ComponentType(c, index);
this.componentTypes[className] = type;
this.types.set(index, type); this.types.set(index, type);
} }
return type; // 返回对应的ComponentType对象
} return this.componentTypes[className];
public getIndexFor(c): number {
return this.getTypeFor(c).getIndex();
} }
} }
} }

View File

@@ -1,12 +1,28 @@
module es { module es {
/**
* 组件类型管理器,维护了一个组件类型和它们对应的位掩码之间的映射关系。
* 用于实现实体匹配器中组件类型的比较操作,以确定实体是否符合给定的匹配器条件。
*/
export class ComponentTypeManager { export class ComponentTypeManager {
/** 存储组件类型和它们对应的位掩码的Map */
private static _componentTypesMask: Map<any, number> = new Map<any, number>(); private static _componentTypesMask: Map<any, number> = new Map<any, number>();
/**
* 将给定的组件类型添加到组件类型列表中,并分配一个唯一的位掩码。
* @param type 要添加的组件类型
*/
public static add(type) { public static add(type) {
if (!this._componentTypesMask.has(type)) if (!this._componentTypesMask.has(type)) {
this._componentTypesMask.set(type, this._componentTypesMask.size); this._componentTypesMask.set(type, this._componentTypesMask.size);
}
} }
/**
* 获取给定组件类型的位掩码。
* 如果该组件类型还没有分配位掩码,则将其添加到列表中,并分配一个唯一的位掩码。
* @param type 要获取位掩码的组件类型
* @returns 组件类型的位掩码
*/
public static getIndexFor(type) { public static getIndexFor(type) {
let v = -1; let v = -1;
if (!this._componentTypesMask.has(type)) { if (!this._componentTypesMask.has(type)) {

View File

@@ -1,4 +1,7 @@
module es { module es {
/**
* 定义一个实体匹配器类。
*/
export class Matcher { export class Matcher {
protected allSet: (new (...args: any[]) => Component)[] = []; protected allSet: (new (...args: any[]) => Component)[] = [];
protected exclusionSet: (new (...args: any[]) => Component)[] = []; protected exclusionSet: (new (...args: any[]) => Component)[] = [];
@@ -25,59 +28,61 @@ module es {
} }
public isInterested(components: Bits) { public isInterested(components: Bits) {
if (this.allSet.length != 0) { if (this.allSet.length !== 0) {
for (let i = 0, s = this.allSet.length; i < s; ++ i) { for (let i = 0; i < this.allSet.length; i++) {
let type = this.allSet[i]; const type = this.allSet[i];
if (!components.get(ComponentTypeManager.getIndexFor(type))) if (!components.get(ComponentTypeManager.getIndexFor(type))) {
return false; return false;
}
} }
} }
if (this.exclusionSet.length != 0) { if (this.exclusionSet.length !== 0) {
for (let i = 0, s = this.exclusionSet.length; i < s; ++ i) { for (let i = 0; i < this.exclusionSet.length; i++) {
let type = this.exclusionSet[i]; const type = this.exclusionSet[i];
if (components.get(ComponentTypeManager.getIndexFor(type))) if (components.get(ComponentTypeManager.getIndexFor(type))) {
return false; return false;
}
} }
} }
if (this.oneSet.length != 0) { if (this.oneSet.length !== 0) {
for (let i = 0, s = this.oneSet.length; i < s; ++ i) { for (let i = 0; i < this.oneSet.length; i++) {
let type = this.oneSet[i]; const type = this.oneSet[i];
if (components.get(ComponentTypeManager.getIndexFor(type))) if (components.get(ComponentTypeManager.getIndexFor(type))) {
return true; return true;
}
} }
return false;
} }
return true; return true;
} }
public all(...types: any[]): Matcher { /**
let t; * 添加所有包含的组件类型。
for (let i = 0, s = types.length; i < s; ++ i) { * @param types 所有包含的组件类型列表
t = types[i]; */
this.allSet.push(t); public all(...types: (new (...args: any[]) => Component)[]): Matcher {
} this.allSet.push(...types);
return this; return this;
} }
public exclude(...types: any[]) { /**
let t; * 添加排除包含的组件类型。
for (let i = 0, s = types.length; i < s; ++ i) { * @param types 排除包含的组件类型列表
t = types[i]; */
this.exclusionSet.push(t); public exclude(...types: (new (...args: any[]) => Component)[]): Matcher {
} this.exclusionSet.push(...types);
return this; return this;
} }
public one(...types: any[]) { /**
for (let i = 0, s = types.length; i < s; ++ i) { * 添加至少包含其中之一的组件类型。
const t = types[i]; * @param types 至少包含其中之一的组件类型列表
this.oneSet.push(t); */
} public one(...types: (new (...args: any[]) => Component)[]): Matcher {
this.oneSet.push(...types);
return this; return this;
} }
} }

View File

@@ -1,38 +0,0 @@
module es {
/**
* 开辟一个新线程
* 注意:它无法获得主线程中的上下文
*/
export class WorkerUtils {
/** 正在执行的队列 */
private static readonly pendingJobs = {};
private static jobIdGen = 0;
/**
* 创建一个worker
* @param doFunc worker所能做的事情
*/
public static makeWorker(doFunc: Function) {
const worker = new Worker(URL.createObjectURL(new Blob([`(${doFunc.toString()})()`])));
return worker;
}
public static workerMessage(worker: Worker) {
worker.onmessage = ({ data: { result, jobId } }) => {
if (typeof this.pendingJobs[jobId] == 'function')
this.pendingJobs[jobId](result);
delete this.pendingJobs[jobId];
};
return (...message: any[]) => {
return new Promise(resolve => {
const jobId = this.jobIdGen++;
this.pendingJobs[jobId] = resolve;
worker.postMessage({ jobId, message });
});
}
}
}
}

View File

@@ -1,79 +1,103 @@
module es { module es {
/**
* 用于池任何对象
*/
export class Pool { export class Pool {
private static _objectQueue: Map<any, any[]> = new Map(); private static _objectQueue = new Map<new () => any, any[]>();
/** /**
* 预热缓存使用最大的cacheCount对象填充缓存 * 预热缓存使用最大的cacheCount对象填充缓存
* @param type * @param type 要预热的类型
* @param cacheCount * @param cacheCount 预热缓存数量
*/ */
public static warmCache<T>(type: new (...args) => T, cacheCount: number) { public static warmCache<T>(type: new (...args: any[]) => T, cacheCount: number) {
this.checkCreate(type); this.checkCreate(type);
cacheCount -= this._objectQueue.get(type).length; const queue = this._objectQueue.get(type);
cacheCount -= queue.length;
// 如果需要预热更多的对象,则创建并添加到缓存
if (cacheCount > 0) { if (cacheCount > 0) {
for (let i = 0; i < cacheCount; i++) { for (let i = 0; i < cacheCount; i++) {
this._objectQueue.get(type).push(new type()); queue.push(new type());
} }
} }
} }
/** /**
* 将缓存修剪为cacheCount项目 * 将缓存修剪为cacheCount项目
* @param cacheCount * @param type 要修剪的类型
*/ * @param cacheCount 修剪后的缓存数量
*/
public static trimCache<T>(type: new (...args) => T, cacheCount: number) { public static trimCache<T>(type: new (...args) => T, cacheCount: number) {
this.checkCreate(type); this.checkCreate(type);
while (cacheCount > this._objectQueue.get(type).length) const objectQueue = this._objectQueue.get(type);
this._objectQueue.get(type).splice(0, 1);
// 如果需要修剪缓存,则弹出多余的对象
while (cacheCount < objectQueue.length) {
objectQueue.pop();
}
} }
/** /**
* 清除缓存 * 清除缓存
* @param type 要清除缓存的类型
*/ */
public static clearCache<T>(type: new (...args) => T) { public static clearCache<T>(type: new (...args) => T) {
this.checkCreate(type); this.checkCreate(type);
this._objectQueue.get(type).length = 0; const objectQueue = this._objectQueue.get(type);
// 清空缓存数组
objectQueue.length = 0;
} }
/** /**
* 如果可以的话,从堆栈中弹出一个项 * 如果可以的话,从缓存中获取一个对象
* @param type 要获取的类型
*/ */
public static obtain<T>(type: new (...args) => T): T { public static obtain<T>(type: new (...args) => T): T {
this.checkCreate(type); this.checkCreate(type);
if (this._objectQueue.get(type).length > 0) const objectQueue = this._objectQueue.get(type);
return this._objectQueue.get(type).shift();
// 如果缓存中有对象,弹出一个并返回
if (objectQueue.length > 0) {
return objectQueue.pop();
}
// 如果没有缓存对象,则创建一个新的对象并返回
return new type() as T; return new type() as T;
} }
/** /**
* 将项推回堆栈 * 将对象推回缓存
* @param obj * @param type 对象的类型
* @param obj 要推回的对象
*/ */
public static free<T>(type: new (...args) => T, obj: T) { public static free<T>(type: new (...args) => T, obj: T) {
this.checkCreate(type); this.checkCreate(type);
this._objectQueue.get(type).push(obj); const objectQueue = this._objectQueue.get(type);
// 将对象推回缓存
objectQueue.push(obj);
// 如果对象实现了IPoolable接口则调用reset方法重置对象
if (isIPoolable(obj)) { if (isIPoolable(obj)) {
obj["reset"](); obj.reset();
} }
} }
private static checkCreate<T>(type: new (...args) => T) { /**
if (!this._objectQueue.has(type)) * 检查缓存中是否已存在给定类型的对象池,如果不存在则创建一个
* @param type 要检查的类型
*/
private static checkCreate<T>(type: new (...args: any[]) => T) {
if (!this._objectQueue.has(type)) {
this._objectQueue.set(type, []); this._objectQueue.set(type, []);
}
} }
} }
export interface IPoolable { export interface IPoolable {
/** reset(): void;
* 重置对象以供重用。对象引用应该为空,字段可以设置为默认值
*/
reset();
} }
export var isIPoolable = (props: any): props is IPoolable => typeof (props as IPoolable)['reset'] !== 'undefined'; export const isIPoolable = (props: any): props is IPoolable => {
return typeof props.reset === 'function';
};
} }

View File

@@ -3,7 +3,7 @@ module es {
* CoroutineManager用于隐藏Coroutine所需数据的内部类 * CoroutineManager用于隐藏Coroutine所需数据的内部类
*/ */
export class CoroutineImpl implements ICoroutine, IPoolable { export class CoroutineImpl implements ICoroutine, IPoolable {
public enumerator: Generator; public enumerator;
/** /**
* 每当产生一个延迟它就会被添加到跟踪延迟的waitTimer中 * 每当产生一个延迟它就会被添加到跟踪延迟的waitTimer中
@@ -50,11 +50,11 @@ module es {
* 立即停止并清除所有协程 * 立即停止并清除所有协程
*/ */
public clearAllCoroutines() { public clearAllCoroutines() {
for (let i = 0; i < this._unblockedCoroutines.length; i ++) { for (let i = 0; i < this._unblockedCoroutines.length; i++) {
Pool.free(CoroutineImpl, this._unblockedCoroutines[i]); Pool.free(CoroutineImpl, this._unblockedCoroutines[i]);
} }
for (let i = 0; i < this._shouldRunNextFrame.length; i ++) { for (let i = 0; i < this._shouldRunNextFrame.length; i++) {
Pool.free(CoroutineImpl, this._shouldRunNextFrame[i]); Pool.free(CoroutineImpl, this._shouldRunNextFrame[i]);
} }
@@ -67,60 +67,72 @@ module es {
* Coroutine在每一帧调用Update之前被执行 * Coroutine在每一帧调用Update之前被执行
* @param enumerator * @param enumerator
*/ */
public startCoroutine(enumerator: any) { public startCoroutine<T>(enumerator: Iterator<T> | (() => Iterator<T>)): CoroutineImpl | null {
// 找到或创建一个CoroutineImpl const coroutine = this.getOrCreateCoroutine();
let coroutine = Pool.obtain<CoroutineImpl>(CoroutineImpl);
coroutine.prepareForUse(); coroutine.prepareForUse();
coroutine.enumerator = typeof enumerator === 'function' ? enumerator() : enumerator;
// 设置coroutine并添加它 if (this.tickCoroutine(coroutine)) {
coroutine.enumerator = enumerator; this.addCoroutine(coroutine);
let shouldContinueCoroutine = this.tickCoroutine(coroutine); return coroutine;
}
if (!shouldContinueCoroutine) return null;
return null; }
private getOrCreateCoroutine(): CoroutineImpl {
const coroutine = Pool.obtain<CoroutineImpl>(CoroutineImpl);
coroutine.prepareForUse();
return coroutine;
}
private addCoroutine(coroutine: CoroutineImpl) {
if (this._isInUpdate) if (this._isInUpdate)
this._shouldRunNextFrame.push(coroutine); this._shouldRunNextFrame.push(coroutine);
else else
this._unblockedCoroutines.push(coroutine); this._unblockedCoroutines.push(coroutine);
return coroutine;
} }
public update() { public update() {
this._isInUpdate = true; this._isInUpdate = true;
for (let i = 0; i < this._unblockedCoroutines.length; i++) {
let coroutine = this._unblockedCoroutines[i]; const unblockedCoroutines = this._unblockedCoroutines;
const shouldRunNextFrame = this._shouldRunNextFrame;
for (let i = unblockedCoroutines.length - 1; i >= 0; i--) {
const coroutine = unblockedCoroutines[i];
if (coroutine.isDone) { if (coroutine.isDone) {
Pool.free(CoroutineImpl, coroutine); Pool.free(CoroutineImpl, coroutine);
unblockedCoroutines.splice(i, 1);
continue; continue;
} }
if (coroutine.waitForCoroutine != null) { const waitForCoroutine = coroutine.waitForCoroutine;
if (coroutine.waitForCoroutine.isDone) { if (waitForCoroutine != null) {
if (waitForCoroutine.isDone) {
coroutine.waitForCoroutine = null; coroutine.waitForCoroutine = null;
} else { } else {
this._shouldRunNextFrame.push(coroutine); shouldRunNextFrame.push(coroutine);
continue; continue;
} }
} }
if (coroutine.waitTimer > 0) { const waitTimer = coroutine.waitTimer;
if (waitTimer > 0) {
// 递减然后再运行下一帧确保用适当的deltaTime递减 // 递减然后再运行下一帧确保用适当的deltaTime递减
coroutine.waitTimer -= coroutine.useUnscaledDeltaTime ? Time.unscaledDeltaTime : Time.deltaTime; coroutine.waitTimer = waitTimer - (coroutine.useUnscaledDeltaTime ? Time.unscaledDeltaTime : Time.deltaTime);
this._shouldRunNextFrame.push(coroutine); shouldRunNextFrame.push(coroutine);
continue; continue;
} }
if (this.tickCoroutine(coroutine)) if (this.tickCoroutine(coroutine)) {
this._shouldRunNextFrame.push(coroutine); shouldRunNextFrame.push(coroutine);
}
} }
let linqCoroutines = new es.List(this._unblockedCoroutines); unblockedCoroutines.push(...shouldRunNextFrame);
linqCoroutines.clear(); shouldRunNextFrame.length = 0;
linqCoroutines.addRange(this._shouldRunNextFrame);
this._shouldRunNextFrame.length = 0;
this._isInUpdate = false; this._isInUpdate = false;
} }
@@ -130,47 +142,57 @@ module es {
* @param coroutine * @param coroutine
*/ */
public tickCoroutine(coroutine: CoroutineImpl) { public tickCoroutine(coroutine: CoroutineImpl) {
let chain = coroutine.enumerator.next(); const { enumerator } = coroutine;
if (chain.done || coroutine.isDone) { const { value, done } = enumerator.next();
if (done || coroutine.isDone) {
// 当协程执行完或标记为结束时,回收协程实例并返回 false。
Pool.free(CoroutineImpl, coroutine); Pool.free(CoroutineImpl, coroutine);
return false; return false;
} }
if (chain.value == null) { if (!value) {
// 下一帧再运行 // 如果下一帧没有指定任务,返回 true 让协程继续等待下一帧执行。
return true; return true;
} }
if (chain.value instanceof WaitForSeconds) { if (value instanceof WaitForSeconds) {
coroutine.waitTimer = chain.value.waitTime; // 如果下一帧需要等待指定时间,则记录等待时间并返回 true。
coroutine.waitTimer = value.waitTime;
return true; return true;
} }
if (typeof chain.value == 'number') { if (typeof value === 'number') {
coroutine.waitTimer = chain.value; // 如果下一帧需要等待指定时间,则记录等待时间并返回 true。
coroutine.waitTimer = value;
return true; return true;
} }
if (typeof chain.value == 'string') { if (typeof value === 'string') {
if (chain.value == 'break') { // 如果下一帧返回 'break',标记协程为结束并返回 false。
if (value === 'break') {
Pool.free(CoroutineImpl, coroutine); Pool.free(CoroutineImpl, coroutine);
return false; return false;
} }
// 否则返回 true 让协程继续等待下一帧执行。
return true; return true;
} }
if (typeof chain.value == 'function') { if (typeof value === 'function') {
coroutine.waitForCoroutine = this.startCoroutine(chain.value); // 如果下一帧需要等待另一个协程完成,启动并记录另一个协程实例,并返回 true。
coroutine.waitForCoroutine = this.startCoroutine(value);
return true; return true;
} }
if (chain.value instanceof CoroutineImpl) { if (value instanceof CoroutineImpl) {
coroutine.waitForCoroutine = chain.value; // 如果下一帧需要等待另一个协程完成,记录另一个协程实例,并返回 true。
return true; coroutine.waitForCoroutine = value;
} else {
return true; return true;
} }
// 否则返回 true 让协程继续等待下一帧执行。
return true;
} }
} }
} }

View File

@@ -19,11 +19,11 @@ module es {
*/ */
export class Emitter<T> { export class Emitter<T> {
private _messageTable: Map<T, FuncPack[]>; private _messageTable: Map<T, FuncPack[]>;
constructor() { constructor() {
this._messageTable = new Map<T, FuncPack[]>(); this._messageTable = new Map<T, FuncPack[]>();
} }
/** /**
* 开始监听项 * 开始监听项
* @param eventType 监听类型 * @param eventType 监听类型
@@ -31,16 +31,17 @@ module es {
* @param context 监听上下文 * @param context 监听上下文
*/ */
public addObserver(eventType: T, handler: Function, context: any) { public addObserver(eventType: T, handler: Function, context: any) {
let list: FuncPack[] = this._messageTable.get(eventType); let list = this._messageTable.get(eventType);
if (!list) { if (!list) {
list = []; list = [];
this._messageTable.set(eventType, list); this._messageTable.set(eventType, list);
} }
Insist.isFalse(list.findIndex(funcPack => funcPack.func == handler) != -1, "您试图添加相同的观察者两次"); if (!this.hasObserver(eventType, handler)) {
list.push(new FuncPack(handler, context)); list.push(new FuncPack(handler, context));
}
} }
/** /**
* 移除监听项 * 移除监听项
* @param eventType 事件类型 * @param eventType 事件类型
@@ -48,22 +49,35 @@ module es {
*/ */
public removeObserver(eventType: T, handler: Function) { public removeObserver(eventType: T, handler: Function) {
let messageData = this._messageTable.get(eventType); let messageData = this._messageTable.get(eventType);
let index = messageData.findIndex(data => data.func == handler); if (messageData) {
if (index != -1) let index = messageData.findIndex(data => data.func == handler);
messageData.splice(index, 1); if (index != -1)
messageData.splice(index, 1);
}
} }
/** /**
* 触发该事件 * 触发该事件
* @param eventType 事件类型 * @param eventType 事件类型
* @param data 事件数据 * @param data 事件数据
*/ */
public emit(eventType: T, ...data: any[]) { public emit(eventType: T, ...data: any[]) {
let list: FuncPack[] = this._messageTable.get(eventType); let list = this._messageTable.get(eventType);
if (list) { if (list) {
for (let i = list.length - 1; i >= 0; i--) for (let observer of list) {
list[i].func.call(list[i].context, ...data); observer.func.call(observer.context, ...data);
}
} }
} }
/**
* 判断是否存在该类型的观察者
* @param eventType 事件类型
* @param handler 事件函数
*/
public hasObserver(eventType: T, handler: Function): boolean {
let list = this._messageTable.get(eventType);
return list ? list.some(observer => observer.func === handler) : false;
}
} }
} }