对ECS系统进行注释、移除JobSystem
This commit is contained in:
311
source/bin/framework.d.ts
vendored
311
source/bin/framework.d.ts
vendored
@@ -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使用实体的子集调用Execute(entities),并在指定数量的线程上分配工作负载。
|
* 定义一个被动的实体系统,继承自 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
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
@@ -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秒时间
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
module es {
|
|
||||||
/**
|
|
||||||
* JobSystem使用实体的子集调用Execute(entities),并在指定数量的线程上分配工作负载。
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user