1.新增es.TimeUtils

2.优化并给部分类添加注释
3.移除fasterDictionary
This commit is contained in:
yhh
2023-03-13 23:32:24 +08:00
parent 323fb6a5fe
commit caa3ffc8f5
14 changed files with 2240 additions and 1796 deletions
+287 -154
View File
@@ -216,10 +216,35 @@ declare module es {
onDisabled(): void; onDisabled(): void;
setEnabled(isEnabled: boolean): this; setEnabled(isEnabled: boolean): this;
setUpdateOrder(updateOrder: number): this; setUpdateOrder(updateOrder: number): this;
/**
* 添加组件
* @param component 要添加的组件实例
* @returns 返回添加的组件实例
*/
addComponent<T extends Component>(component: T): T; addComponent<T extends Component>(component: T): T;
/**
* 获取组件
* @param type 组件类型
* @returns 返回获取到的组件实例
*/
getComponent<T extends Component>(type: new (...args: any[]) => T): T; getComponent<T extends Component>(type: new (...args: any[]) => T): T;
/**
* 获取一组指定类型的组件
* @param typeName 组件类型名
* @param componentList 可选参数,存储组件实例的数组
* @returns 返回指定类型的组件实例数组
*/
getComponents(typeName: any, componentList?: any[]): any[]; getComponents(typeName: any, componentList?: any[]): any[];
/**
* 判断实体是否包含指定类型的组件
* @param type 组件类型
* @returns 如果实体包含指定类型的组件,返回 true,否则返回 false。
*/
hasComponent(type: new (...args: any[]) => Component): boolean; hasComponent(type: new (...args: any[]) => Component): boolean;
/**
* 删除组件
* @param component 可选参数,要删除的组件实例。如果未指定该参数,则删除当前实例上的组件。
*/
removeComponent(component?: Component): void; removeComponent(component?: Component): void;
} }
} }
@@ -1610,7 +1635,7 @@ declare module es {
} }
declare module es { declare module es {
/** /**
* 追踪实体的子集,但不实现任何排序或迭代 * 实体系统的基类,用于处理一组实体
*/ */
abstract class EntitySystem { abstract class EntitySystem {
private _entities; private _entities;
@@ -1634,7 +1659,7 @@ declare module es {
readonly matcher: Matcher; readonly matcher: Matcher;
/** /**
* 设置更新时序 * 设置更新时序
* @param order * @param order 更新时序
*/ */
setUpdateOrder(order: number): void; setUpdateOrder(order: number): void;
initialize(): void; initialize(): void;
@@ -1804,11 +1829,7 @@ declare module es {
} }
declare module es { declare module es {
/** /**
* 每x个ticks处理一个实体的子集 * 定时遍历处理实体的系统,用于按指定的时间间隔遍历并处理感兴趣的实体。
*
* 典型的用法是每隔一定的时间间隔重新生成弹药或生命值
* 而无需在每个游戏循环中都进行
* 而是每100毫秒一次或每秒
*/ */
abstract class IntervalIteratingSystem extends IntervalSystem { abstract class IntervalIteratingSystem extends IntervalSystem {
constructor(matcher: Matcher, interval: number); constructor(matcher: Matcher, interval: number);
@@ -1817,6 +1838,10 @@ declare module es {
* @param entity * @param entity
*/ */
abstract processEntity(entity: Entity): any; abstract processEntity(entity: Entity): any;
/**
* 遍历处理实体。
* @param entities 本系统感兴趣的实体列表
*/
protected process(entities: Entity[]): void; protected process(entities: Entity[]): void;
} }
} }
@@ -1861,83 +1886,142 @@ declare module es {
} }
} }
declare module es { declare module es {
/**
* 位操作类,用于操作一个位数组。
*/
class Bits { class Bits {
private _bit; private _bit;
/**
* 设置指定位置的位值。
* @param index 位置索引
* @param value 位值(0 或 1
*/
set(index: number, value: number): void; set(index: number, value: number): void;
/**
* 获取指定位置的位值。
* @param index 位置索引
* @returns 位值(0 或 1
*/
get(index: number): number; get(index: number): number;
} }
} }
declare module es { declare module es {
class ComponentList { class ComponentList {
/** /**
* 组件列表的全局updateOrder排序 * 比较IUpdatable对象的更新顺序。
*/ */
static compareUpdatableOrder: IUpdatableComparer; static compareUpdatableOrder: IUpdatableComparer;
_entity: Entity; _entity: Entity;
/** /**
* 添加到实体的组件列表 * 实体的组件列表
*/ */
_components: Component[]; _components: Component[];
/** /**
* 所有需要更新的组件列表 * 更新的组件列表
*/ */
_updatableComponents: IUpdatable[]; _updatableComponents: IUpdatable[];
/** /**
* 添加到此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工 * 等待添加到实体的组件列表。
*/ */
_componentsToAdd: { _componentsToAdd: {
[index: number]: Component; [index: number]: Component;
}; };
/** /**
* 标记要删除此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工 * 等待从实体中移除的组件列表。
*/ */
_componentsToRemove: { _componentsToRemove: {
[index: number]: Component; [index: number]: Component;
}; };
/**
* 等待添加到实体的组件列表(作为数组)。
*/
_componentsToAddList: Component[]; _componentsToAddList: Component[];
/**
* 等待从实体中移除的组件列表(作为数组)。
*/
_componentsToRemoveList: Component[]; _componentsToRemoveList: Component[];
/**
* 临时的组件缓冲列表。
*/
_tempBufferList: Component[]; _tempBufferList: Component[];
/** /**
* 用于确定是否需要对该框架中的组件进行排序的标志 * 指示组件列表是否已排序的标志
*/ */
_isComponentListUnsorted: boolean; _isComponentListUnsorted: boolean;
/**
* 按组件类型组织的组件列表字典。
*/
private componentsByType; private componentsByType;
/**
* 按组件类型组织的等待添加到实体的组件列表字典。
*/
private componentsToAddByType; private componentsToAddByType;
constructor(entity: Entity); constructor(entity: Entity);
readonly count: number; readonly count: number;
readonly buffer: Component[]; readonly buffer: Component[];
markEntityListUnsorted(): void; markEntityListUnsorted(): void;
/**
* 将组件添加到实体的组件列表中,并添加到组件类型字典中。
* @param component 要添加的组件。
*/
add(component: Component): void; add(component: Component): void;
/**
* 从实体的组件列表中移除组件,并从相应的组件类型字典中移除组件。
* @param component 要从实体中移除的组件。
*/
remove(component: Component): void; remove(component: Component): void;
/** /**
* 立即从组件列表中删除所有组件 * 立即从组件列表中删除所有组件
*/ */
removeAllComponents(): void; removeAllComponents(): void;
/**
* 从实体的所有组件上注销并从相关数据结构中删除它们。
*/
deregisterAllComponents(): void; deregisterAllComponents(): void;
/**
* 注册实体的所有组件,并将它们添加到相应的数据结构中。
*/
registerAllComponents(): void; registerAllComponents(): void;
/**
* 从实体的位掩码中减去组件类型的索引。
* @param component 要从实体中删除的组件。
*/
private decreaseBits; private decreaseBits;
/**
* 在实体的位掩码中添加组件类型的索引。
* @param component 要添加到实体的组件。
*/
private addBits; private addBits;
/** /**
* 处理任何需要删除或添加的组件 * 更新实体的组件列表和相关数据结构。
* 如果有组件要添加或删除,它将相应地更新组件列表和其他数据结构。
*/ */
updateLists(): void; updateLists(): void;
handleRemove(component: Component): void; handleRemove(component: Component): void;
private removeComponentsByType; private removeComponentsByType;
private addComponentsByType; private addComponentsByType;
/**
* 从待添加组件列表中移除指定类型的组件。
* @param component 要移除的组件
*/
private removeComponentsToAddByType; private removeComponentsToAddByType;
/**
* 向待添加组件列表中添加指定类型的组件。
* @param component 要添加的组件
*/
private addComponentsToAddByType; private addComponentsToAddByType;
/** /**
* 获取类型T的第一个组件并返回它 * 获取指定类型的第一个组件实例。
* 可以选择跳过检查未初始化的组件(尚未调用onAddedToEntity方法的组件) * @param type 组件类型
* 如果没有找到组件,则返回null。 * @param onlyReturnInitializedComponents 是否仅返回已初始化的组件
* @param type * @returns 指定类型的第一个组件实例,如果不存在则返回 null
* @param onlyReturnInitializedComponents
*/ */
getComponent<T extends Component>(type: any, onlyReturnInitializedComponents: boolean): T; getComponent<T extends Component>(type: new (...args: any[]) => T, onlyReturnInitializedComponents: boolean): T;
/** /**
* 获取T类型的所有组件,但不使用列表分配 * 获取指定类型的所有组件实例。
* @param typeName * @param typeName 组件类型名称
* @param components * @param components 存储组件实例的数组
* @returns 存储了指定类型的所有组件实例的数组
*/ */
getComponents(typeName: any, components?: any[]): any[]; getComponents(typeName: any, components?: any[]): any[];
update(): void; update(): void;
@@ -1998,33 +2082,45 @@ declare module es {
} }
declare module es { declare module es {
class EntityList { class EntityList {
/**
* 场景引用
*/
scene: Scene; scene: Scene;
/** /**
* 场景中添加的实体列表 * 实体列表
*/ */
_entities: Entity[]; _entities: Entity[];
/** /**
* 本帧添加的实体列表。用于对实体进行分组,以便我们可以同时处理它们 * 添加的实体字典
*/ */
_entitiesToAdded: { _entitiesToAdded: {
[index: number]: Entity; [index: number]: Entity;
}; };
/** /**
* 本帧被标记为删除的实体列表。用于对实体进行分组,以便我们可以同时处理它们 * 待移除的实体字典
*/ */
_entitiesToRemove: { _entitiesToRemove: {
[index: number]: Entity; [index: number]: Entity;
}; };
/**
* 待添加的实体列表
*/
_entitiesToAddedList: Entity[]; _entitiesToAddedList: Entity[];
/**
* 待移除的实体列表
*/
_entitiesToRemoveList: Entity[]; _entitiesToRemoveList: Entity[];
/** /**
* 标志,用于确定我们是否需要在这一帧中对实体进行排序 * 实体列表是否已排序
*/ */
_isEntityListUnsorted: boolean; _isEntityListUnsorted: boolean;
/** /**
* 通过标签跟踪实体,便于检索 * 实体字典,以实体标签为键
*/ */
_entityDict: Map<number, Set<Entity>>; _entityDict: Map<number, Set<Entity>>;
/**
* 未排序的标签集合
*/
_unsortedTags: Set<number>; _unsortedTags: Set<number>;
constructor(scene: Scene); constructor(scene: Scene);
readonly count: number; readonly count: number;
@@ -2037,23 +2133,45 @@ declare module es {
*/ */
add(entity: Entity): void; add(entity: Entity): void;
/** /**
* 从列表中删除一个实体。所有的生命周期方法将在下一帧中被调用 * 从场景中移除实体。
* @param entity * @param entity 要从场景中移除的实体。
*/ */
remove(entity: Entity): void; remove(entity: Entity): void;
/** /**
* 从实体列表中删除所有实体 * 从场景中移除所有实体
*/ */
removeAllEntities(): void; removeAllEntities(): void;
/** /**
* 检查实体目前是否由这个EntityList管理 * 检查实体是否已经被添加到场景中。
* @param entity * @param entity 要检查的实体
* @returns 如果实体已经被添加到场景中,则返回true;否则返回false
*/ */
contains(entity: Entity): boolean; contains(entity: Entity): boolean;
/**
* 获取具有指定标签的实体列表。
* 如果列表不存在,则创建一个新列表并返回。
* @param tag 实体标签
* @returns 具有指定标签的实体列表
*/
getTagList(tag: number): Set<Entity>; getTagList(tag: number): Set<Entity>;
/**
* 添加实体到标签列表中。
* @param entity 实体
*/
addToTagList(entity: Entity): void; addToTagList(entity: Entity): void;
/**
* 从标签列表中移除实体。
* @param entity 实体
*/
removeFromTagList(entity: Entity): void; removeFromTagList(entity: Entity): void;
/**
* 更新场景中所有启用的实体的Update方法
* 如果实体的UpdateInterval为1或Time.frameCount模除UpdateInterval为0,则每帧调用Update
*/
update(): void; update(): void;
/**
* 更新场景中实体的列表。
*/
updateLists(): void; updateLists(): void;
/** /**
* 返回第一个找到的名字为name的实体。如果没有找到则返回null * 返回第一个找到的名字为name的实体。如果没有找到则返回null
@@ -2061,15 +2179,15 @@ declare module es {
*/ */
findEntity(name: string): Entity; findEntity(name: string): Entity;
/** /**
* * 通过实体ID在场景中查找对应实体
* @param id * @param id 实体ID
* @returns * @returns 返回找到的实体,如果没有找到则返回 null
*/ */
findEntityById(id: number): Entity; findEntityById(id: number): Entity;
/** /**
* 返回带有标签的所有实体列表。如果没有实体有标签,则返回一个空列表。 * 获取标签对应的实体列表
* 返回的List可以通过ListPool.free放回池中 * @param tag 实体的标签
* @param tag * @returns 返回所有拥有该标签的实体列表
*/ */
entitiesWithTag(tag: number): Entity[]; entitiesWithTag(tag: number): Entity[];
/** /**
@@ -2079,20 +2197,21 @@ declare module es {
*/ */
entityWithTag(tag: number): Entity; entityWithTag(tag: number): Entity;
/** /**
* 返回在场景中找到的第一个T类型的组件。 * 在场景中查找具有给定类型的组件。
* @param type * @param type 要查找的组件类型。
* @returns 如果找到,则返回该组件;否则返回null。
*/ */
findComponentOfType<T extends Component>(type: any): T; findComponentOfType<T extends Component>(type: new (...args: any[]) => T): T | null;
/** /**
* 返回在场景中找到的所有T类型的组件。 * 在场景中查找具有给定类型的所有组件。
* 返回的List可以通过ListPool.free放回池中 * @param type 要查找的组件类型
* @param type * @returns 具有给定类型的所有组件的列表。
*/ */
findComponentsOfType<T extends Component>(type: any): T[]; findComponentsOfType<T extends Component>(type: new (...args: any[]) => T): T[];
/** /**
* 返回场景中包含特定组件的实体列表 * 返回拥有指定类型组件的所有实体
* @param types * @param types 要查询的组件类型列表
* @returns * @returns 返回拥有指定类型组件的所有实体
*/ */
findEntitiesOfComponent(...types: any[]): Entity[]; findEntitiesOfComponent(...types: any[]): Entity[];
} }
@@ -2101,53 +2220,100 @@ declare module es {
class EntityProcessorList { class EntityProcessorList {
private _processors; private _processors;
private _orderDirty; private _orderDirty;
/** 获取系统列表 */ /** 获取处理器列表 */
readonly processors: EntitySystem[]; readonly processors: EntitySystem[];
/** 系统数量 */ /** 获取处理器数量 */
readonly count: number; readonly count: number;
/**
* 添加处理器
* @param processor 要添加的处理器
*/
add(processor: EntitySystem): void; add(processor: EntitySystem): void;
/**
* 移除处理器
* @param processor 要移除的处理器
*/
remove(processor: EntitySystem): void; remove(processor: EntitySystem): void;
/**
* 在实体上添加组件时被调用
* @param entity 添加组件的实体
*/
onComponentAdded(entity: Entity): void; onComponentAdded(entity: Entity): void;
/**
* 在实体上移除组件时被调用
* @param entity 移除组件的实体
*/
onComponentRemoved(entity: Entity): void; onComponentRemoved(entity: Entity): void;
/**
* 在场景中添加实体时被调用
* @param entity 添加的实体
*/
onEntityAdded(entity: Entity): void; onEntityAdded(entity: Entity): void;
/**
* 在场景中移除实体时被调用
* @param entity 移除的实体
*/
onEntityRemoved(entity: Entity): void; onEntityRemoved(entity: Entity): void;
/** 在处理器列表上开始循环 */
begin(): void; begin(): void;
/** 更新处理器列表 */
update(): void; update(): void;
lateUpdate(): void; /** 在处理器列表上完成循环 */
end(): void; end(): void;
/** 设置处理器排序标志 */
setDirty(): void; setDirty(): void;
/** 清除处理器排序标志 */
clearDirty(): void; clearDirty(): void;
/**
* 获取指定类型的处理器
* @param type 指定类型的构造函数
* @returns 指定类型的处理器
*/
getProcessor<T extends EntitySystem>(type: new (...args: any[]) => T): T; getProcessor<T extends EntitySystem>(type: new (...args: any[]) => T): T;
/**
* 通知处理器实体已更改
* @param entity 发生更改的实体
*/
protected notifyEntityChanged(entity: Entity): void; protected notifyEntityChanged(entity: Entity): void;
/**
* 从处理器列表中移除实体
* @param entity 要移除的实体
*/
protected removeFromProcessors(entity: Entity): void; protected removeFromProcessors(entity: Entity): void;
/** 在处理器列表上进行后期更新 */
lateUpdate(): void;
} }
} }
declare module es { declare module es {
class HashHelpers { class HashHelpers {
static readonly hashCollisionThreshold: number; static readonly hashCollisionThreshold: number;
static readonly hashPrime: number; static readonly hashPrime: number;
/**
* 用来作为哈希表大小的质数表。
* 一个典型的调整大小的算法会在这个数组中选取比之前容量大两倍的最小质数。
* 假设我们的Hashtable当前的容量为x,并且添加了足够多的元素,因此需要进行大小调整。
* 调整大小首先计算2x,然后在表中找到第一个大于2x的质数,即如果质数的顺序是p_1,p_2,...p_i...,则找到p_n,使p_n-1 < 2x < p_n。
* 双倍对于保持哈希特操作的渐近复杂度是很重要的,比如添加。
* 拥有一个质数可以保证双倍哈希不会导致无限循环。 IE,你的哈希函数将是h1(key)+i*h2(key)0 <= i < size.h2和size必须是相对质数。
*/
static readonly primes: number[]; static readonly primes: number[];
/**
* 这是比Array.MaxArrayLength小的最大质数
*/
static readonly maxPrimeArrayLength: number; static readonly maxPrimeArrayLength: number;
/**
* 判断一个数是否为质数
* @param candidate 要判断的数
* @returns 是否为质数
*/
static isPrime(candidate: number): boolean; static isPrime(candidate: number): boolean;
/**
* 获取大于等于指定值的最小质数
* @param min 指定值
* @returns 大于等于指定值的最小质数
*/
static getPrime(min: number): number; static getPrime(min: number): number;
/** /**
* * 扩展哈希表容量
* @param oldSize * @param oldSize 原哈希表容量
* @returns 返回要增长的哈希特表的大小 * @returns 扩展后的哈希表容量
*/ */
static expandPrime(oldSize: number): number; static expandPrime(oldSize: number): number;
static getHashCode(str: any): number; /**
* 计算字符串的哈希值
* @param str 要计算哈希值的字符串
* @returns 哈希值
*/
static getHashCode(str: string): number;
} }
} }
declare module es { declare module es {
@@ -2281,57 +2447,74 @@ declare module es {
} }
} }
declare module es { declare module es {
/** 提供帧定时信息 */ /**
* 时间管理器,用于管理游戏中的时间相关属性
*/
class Time { class Time {
/** 游戏运行的总时间 */ /** 游戏运行的总时间,单位为秒 */
static totalTime: number; static totalTime: number;
/** deltaTime的未缩放版本不受时间尺度的影响 */ /** deltaTime 的未缩放版本不受时间尺度的影响 */
static unscaledDeltaTime: number; static unscaledDeltaTime: number;
/** 前一帧到当前帧的时间增量,按时间刻度进行缩放 */ /** 前一帧到当前帧的时间增量,按时间刻度进行缩放 */
static deltaTime: number; static deltaTime: number;
/** 时间刻度缩放 */ /** 时间刻度缩放,可以加快或减慢游戏时间 */
static timeScale: number; static timeScale: number;
/** DeltaTime可以为的最大值 */ /** DeltaTime 可以为的最大值,避免游戏出现卡顿情况 */
static maxDeltaTime: number; static maxDeltaTime: number;
/** 已传递的帧总数 */ /** 已传递的帧总数 */
static frameCount: number; static frameCount: number;
/** 自场景加载以来的总时间 */ /** 自场景加载以来的总时间,单位为秒 */
static timeSinceSceneLoad: number; static timeSinceSceneLoad: number;
/** 上一次记录的时间,用于计算两次调用 update 之间的时间差 */
private static _lastTime; private static _lastTime;
/**
* 更新时间管理器
* @param currentTime 当前时间
* @param useEngineTime 是否使用引擎时间
*/
static update(currentTime: number, useEngineTime: boolean): void; static update(currentTime: number, useEngineTime: boolean): void;
static sceneChanged(): void; static sceneChanged(): void;
/** /**
* 允许在间隔检查。只应该使用高于delta的间隔值,否则它将始终返回true。 * 检查指定时间间隔是否已过去
* @param interval * @param interval 指定时间间隔
* @returns 是否已过去指定时间间隔
*/ */
static checkEvery(interval: number): boolean; static checkEvery(interval: number): boolean;
} }
} }
declare class TimeUtils { declare module es {
class TimeUtils {
/** /**
* 计算月份ID * 获取日期对应的年份和月份的数字组合
* @param d 指定计算日期 * @param d 要获取月份的日期对象,不传则默认为当前时间
* @returns 月ID * @returns 返回数字组合的年份和月份
*/ */
static monthId(d?: Date): number; static monthId(d?: Date): number;
/** /**
* 计算日期ID * 获取日期的数字组合
* @param d 指定计算日期 * @param t - 可选参数,传入时间,若不传入则使用当前时间
* @returns 日期ID * @returns 数字组合
*/ */
static dateId(t?: Date): number; static dateId(t?: Date): number;
/** /**
* 计算周ID * 获取当前日期所在周的数字组合
* @param d 指定计算日期 * @param d - 可选参数,传入日期,若不传入则使用当前日期
* @returns 周ID * @param first - 是否将当前周视为本年度的第1周,默认为true
* @returns 数字组合
*/ */
static weekId(d?: Date, first?: boolean): number; static weekId(d?: Date, first?: boolean): number;
/** /**
* 计算俩日期时间差,如果a比b小,返回负 * 计算两个日期之间相差的天
* @param a 第一个日期
* @param b 第二个日期
* @param fixOne 是否将相差天数四舍五入到整数
* @returns 两个日期之间相差的天数
*/ */
static diffDay(a: Date, b: Date, fixOne?: boolean): number; static diffDay(a: Date, b: Date, fixOne?: boolean): number;
/** /**
* 获取本周一 凌晨时间 * 获取指定日期所在周的第一天
* @param d 指定日期,默认值为今天
* @returns 指定日期所在周的第一天
*/ */
static getFirstDayOfWeek(d?: Date): Date; static getFirstDayOfWeek(d?: Date): Date;
/** /**
@@ -2343,42 +2526,39 @@ declare class TimeUtils {
*/ */
static getNextFirstOfDay(d?: Date): Date; static getNextFirstOfDay(d?: Date): Date;
/** /**
* @returns 2018-12-12 * 格式化日期为 "YYYY-MM-DD" 的字符串形式
* @param date 要格式化的日期
* @returns 格式化后的日期字符串
*/ */
static formatDate(date: Date): string; static formatDate(date: Date): string;
/** /**
* @returns 2018-12-12 12:12:12 * 将日期对象格式化为 "YYYY-MM-DD HH:mm:ss" 的字符串
* @param date 日期对象
* @returns 格式化后的字符串
*/ */
static formatDateTime(date: Date): string; static formatDateTime(date: Date): string;
/** /**
* @returns s 2018-12-12 或者 2018-12-12 12:12:12 * 将字符串解析为Date对象
* @param s 要解析的日期字符串,例如:2022-01-01
* @returns 返回解析后的Date对象,如果解析失败,则返回当前时间的Date对象
*/ */
static parseDate(s: string): Date; static parseDate(s: string): Date;
/** /**
* 秒数转换为时间形式。 * 秒数转换为时分秒的格式
* @param time 秒数 * @param time 秒数
* @param partition 分隔符 * @param partition 分隔符
* @param showHour 是否显示小时 * @param showHour 是否显示小时
* @return 返回一个以分隔符分割的时, 分, 秒 * @returns 转换后的时间字符串
*
* 比如: time = 4351; secondToTime(time)返回字符串01:12:31;
*/ */
static secondToTime(time?: number, partition?: string, showHour?: boolean): string; static secondToTime(time?: number, partition?: string, showHour?: boolean): string;
/** /**
* 时间形式转换为毫秒数 * 时间字符串转换为毫秒数
* @param time 以指定分隔符分割的时间字符串 * @param time 时间字符串,如 "01:30:15" 表示 1小时30分钟15秒
* @param partition 分隔符 * @param partition 分隔符,默认为 ":"
* @return 毫秒数显示的字符串 * @returns 转换后的毫秒数字符串
* @throws Error Exception
*
* 用法1 trace(MillisecondTransform.timeToMillisecond("00:60:00"))
* 输出 3600000
*
*
* 用法2 trace(MillisecondTransform.timeToMillisecond("00.60.00","."))
* 输出 3600000
*/ */
static timeToMillisecond(time: string, partition?: string): string; static timeToMillisecond(time: string, partition?: string): string;
}
} }
declare module es { declare module es {
/** /**
@@ -5321,53 +5501,6 @@ declare module es {
addAll(items: ImmutableBag<E>): void; addAll(items: ImmutableBag<E>): void;
} }
} }
declare module es {
/**
* 创建这个字典的原因只有一个:
* 我需要一个能让我直接以数组的形式对值进行迭代的字典,而不需要生成一个数组或使用迭代器。
* 对于这个目标是比标准字典快N倍。
* Faster dictionary在大部分操作上也比标准字典快,但差别可以忽略不计。
* 唯一较慢的操作是在添加时调整内存大小,因为与标准数组相比,这个实现需要使用两个单独的数组。
*/
class FasterDictionary<TKey, TValue> {
_values: TValue[];
_valuesInfo: FastNode[];
_buckets: number[];
_freeValueCellIndex: number;
_collisions: number;
constructor(size?: number);
getValuesArray(count: {
value: number;
}): TValue[];
readonly valuesArray: TValue[];
readonly count: number;
add(key: TKey, value: TValue): void;
addValue(key: TKey, value: TValue, indexSet: {
value: number;
}): boolean;
remove(key: TKey): boolean;
trim(): void;
clear(): void;
fastClear(): void;
containsKey(key: TKey): boolean;
tryGetValue(key: TKey): TValue;
tryFindIndex(key: TKey, findIndex: {
value: number;
}): boolean;
getDirectValue(index: number): TValue;
getIndex(key: TKey): number;
static updateLinkedList(index: number, valuesInfo: FastNode[]): void;
static hash(key: any): number;
static reduce(x: number, n: number): number;
}
class FastNode {
readonly key: any;
readonly hashcode: number;
previous: number;
next: number;
constructor(key: any, hash: number, previousNode?: number);
}
}
declare module es { declare module es {
interface ImmutableBag<E> { interface ImmutableBag<E> {
get(index: number): E; get(index: number): E;
+792 -555
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+29 -4
View File
@@ -117,23 +117,48 @@ module es {
return this; return this;
} }
/**
*
* @param component
* @returns
*/
public addComponent<T extends Component>(component: T): T { public addComponent<T extends Component>(component: T): T {
return this.entity.addComponent<T>(component); return this.entity.addComponent<T>(component);
} }
public getComponent<T extends Component>(type: new (...args: any[])=>T): T { /**
*
* @param type
* @returns
*/
public getComponent<T extends Component>(type: new (...args: any[]) => T): T {
return this.entity.getComponent<T>(type); return this.entity.getComponent<T>(type);
} }
public getComponents(typeName: any, componentList?: any[]) { /**
*
* @param typeName
* @param componentList
* @returns
*/
public getComponents(typeName: any, componentList?: any[]): any[] {
return this.entity.getComponents(typeName, componentList); return this.entity.getComponents(typeName, componentList);
} }
public hasComponent(type: new (...args: any[])=>Component) { /**
*
* @param type
* @returns true false
*/
public hasComponent(type: new (...args: any[]) => Component): boolean {
return this.entity.hasComponent(type); return this.entity.hasComponent(type);
} }
public removeComponent(component?: Component) { /**
*
* @param component
*/
public removeComponent(component?: Component): void {
if (component) { if (component) {
this.entity.removeComponent(component); this.entity.removeComponent(component);
} else { } else {
+10 -6
View File
@@ -1,7 +1,7 @@
///<reference path="../../Utils/Collections/HashMap.ts"/> ///<reference path="../../Utils/Collections/HashMap.ts"/>
module es { module es {
/** /**
* *
*/ */
export abstract class EntitySystem { export abstract class EntitySystem {
private _entities: Entity[] = []; private _entities: Entity[] = [];
@@ -53,7 +53,7 @@ module es {
/** /**
* *
* @param order * @param order
*/ */
public setUpdateOrder(order: number) { public setUpdateOrder(order: number) {
this._updateOrder = order; this._updateOrder = order;
@@ -80,14 +80,16 @@ module es {
this.onAdded(entity); this.onAdded(entity);
} }
public onAdded(entity: Entity) { } public onAdded(entity: Entity) {
}
public remove(entity: Entity) { public remove(entity: Entity) {
new es.List(this._entities).remove(entity); new es.List(this._entities).remove(entity);
this.onRemoved(entity); this.onRemoved(entity);
} }
public onRemoved(entity: Entity) { } public onRemoved(entity: Entity) {
}
public update() { public update() {
if (this.checkProcessing()) { if (this.checkProcessing()) {
@@ -114,9 +116,11 @@ module es {
this._startTime = Date.now(); this._startTime = Date.now();
} }
protected process(entities: Entity[]) { } protected process(entities: Entity[]) {
}
protected lateProcess(entities: Entity[]) { } protected lateProcess(entities: Entity[]) {
}
/** /**
* *
@@ -1,13 +1,10 @@
///<reference path="./IntervalSystem.ts"/> ///<reference path="./IntervalSystem.ts"/>
module es { module es {
/** /**
* x个ticks处理一个实体的子集 *
*
*
*
* 100
*/ */
export abstract class IntervalIteratingSystem extends IntervalSystem { export abstract class IntervalIteratingSystem extends IntervalSystem {
constructor(matcher: Matcher, interval: number) { constructor(matcher: Matcher, interval: number) {
super(matcher, interval); super(matcher, interval);
} }
@@ -18,6 +15,10 @@ module es {
*/ */
public abstract processEntity(entity: Entity); public abstract processEntity(entity: Entity);
/**
*
* @param entities
*/
protected process(entities: Entity[]) { protected process(entities: Entity[]) {
entities.forEach(entity => this.processEntity(entity)); entities.forEach(entity => this.processEntity(entity));
} }
+15 -1
View File
@@ -1,14 +1,28 @@
module es { module es {
/**
*
*/
export class Bits { export class Bits {
private _bit: {[index: number]: number} = {}; private _bit: { [index: number]: number } = {};
/**
*
* @param index
* @param value 0 1
*/
public set(index: number, value: number) { public set(index: number, value: number) {
this._bit[index] = value; this._bit[index] = value;
} }
/**
*
* @param index
* @returns 0 1
*/
public get(index: number): number { public get(index: number): number {
let v = this._bit[index]; let v = this._bit[index];
return v == null ? 0 : v; return v == null ? 0 : v;
} }
} }
} }
+186 -70
View File
@@ -2,37 +2,61 @@
module es { module es {
export class ComponentList { export class ComponentList {
/** /**
* updateOrder排序 * IUpdatable对象的更新顺序
*/ */
public static compareUpdatableOrder: IUpdatableComparer = new IUpdatableComparer(); public static compareUpdatableOrder: IUpdatableComparer = new IUpdatableComparer();
public _entity: Entity; public _entity: Entity;
/** /**
* *
*/ */
public _components: Component[] = []; public _components: Component[] = [];
/** /**
* *
*/ */
public _updatableComponents: IUpdatable[] = []; public _updatableComponents: IUpdatable[] = [];
/** /**
* *
*/ */
public _componentsToAdd: { [index: number]: Component } = {}; public _componentsToAdd: { [index: number]: Component } = {};
/** /**
* *
*/ */
public _componentsToRemove: { [index: number]: Component } = {}; public _componentsToRemove: { [index: number]: Component } = {};
public _componentsToAddList: Component[] = [];
public _componentsToRemoveList: Component[] = [];
public _tempBufferList: Component[] = [];
/** /**
* *
*/
public _componentsToAddList: Component[] = [];
/**
*
*/
public _componentsToRemoveList: Component[] = [];
/**
*
*/
public _tempBufferList: Component[] = [];
/**
*
*/ */
public _isComponentListUnsorted: boolean; public _isComponentListUnsorted: boolean;
/**
*
*/
private componentsByType = new Map<new (...args: any[]) => Component, es.Component[]>(); private componentsByType = new Map<new (...args: any[]) => Component, es.Component[]>();
/**
*
*/
private componentsToAddByType = new Map<new (...args: any[]) => Component, es.Component[]>(); private componentsToAddByType = new Map<new (...args: any[]) => Component, es.Component[]>();
constructor(entity: Entity) { constructor(entity: Entity) {
this._entity = entity; this._entity = entity;
} }
@@ -49,32 +73,45 @@ module es {
this._isComponentListUnsorted = true; this._isComponentListUnsorted = true;
} }
/**
*
* @param component
*/
public add(component: Component) { public add(component: Component) {
// 将组件添加到_componentsToAdd和_componentsToAddList中,并添加到相应的组件类型字典中
this._componentsToAdd[component.id] = component; this._componentsToAdd[component.id] = component;
this._componentsToAddList.push(component); this._componentsToAddList.push(component);
this.addComponentsToAddByType(component); this.addComponentsToAddByType(component);
} }
/**
*
* @param component
*/
public remove(component: Component) { public remove(component: Component) {
// 如果组件在_componentsToAdd中,则将其从_componentsToAddList中移除,并从相应的组件类型字典中移除组件
if (this._componentsToAdd[component.id]) { if (this._componentsToAdd[component.id]) {
let index = this._componentsToAddList.findIndex(c => c.id == component.id); const index = this._componentsToAddList.findIndex((c) => c.id === component.id);
if (index != -1) if (index !== -1) {
this._componentsToAddList.splice(index, 1); this._componentsToAddList.splice(index, 1);
}
delete this._componentsToAdd[component.id]; delete this._componentsToAdd[component.id];
this.removeComponentsToAddByType(component); this.removeComponentsToAddByType(component);
return; return;
} }
// 如果组件不在_componentsToAdd中,则将其添加到_componentsToRemove和_componentsToRemoveList中
this._componentsToRemove[component.id] = component; this._componentsToRemove[component.id] = component;
this._componentsToRemoveList.push(component); this._componentsToRemoveList.push(component);
} }
/** /**
* *
*/ */
public removeAllComponents() { public removeAllComponents() {
if (this._components.length > 0) { if (this._components.length > 0) {
for (let i = 0, s = this._components.length; i < s; ++ i) { for (let i = 0, s = this._components.length; i < s; ++i) {
this.handleRemove(this._components[i]); this.handleRemove(this._components[i]);
} }
} }
@@ -89,193 +126,272 @@ module es {
this._componentsToRemoveList.length = 0; this._componentsToRemoveList.length = 0;
} }
/**
*
*/
public deregisterAllComponents() { public deregisterAllComponents() {
if (this._components.length > 0) { if (this._components.length > 0) {
for (let i = 0, s = this._components.length; i < s; ++ i) { for (const component of this._components) {
let component = this._components[i];
if (!component) continue;
// 处理IUpdatable // 处理IUpdatable
if (isIUpdatable(component)) if (isIUpdatable(component)) {
// 创建一个新的List实例,从_updatableComponents中移除组件,以避免并发修改异常
new es.List(this._updatableComponents).remove(component); new es.List(this._updatableComponents).remove(component);
}
// 从位掩码中减去组件类型的索引,通知实体处理器一个组件已被移除
this.decreaseBits(component); this.decreaseBits(component);
this._entity.scene.entityProcessors.onComponentRemoved(this._entity); this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
} }
} }
} }
/**
*
*/
public registerAllComponents() { public registerAllComponents() {
if (this._components.length > 0) { if (this._components.length > 0) {
for (let i = 0, s = this._components.length; i < s; ++ i) { for (const component of this._components) {
let component = this._components[i]; if (isIUpdatable(component)) {
if (isIUpdatable(component)) // 如果组件是可更新的,则将其添加到_updatableComponents中
this._updatableComponents.push(component); this._updatableComponents.push(component);
}
// 将组件类型的索引添加到实体的位掩码中,通知实体处理器一个组件已被添加
this.addBits(component); this.addBits(component);
this._entity.scene.entityProcessors.onComponentAdded(this._entity); this._entity.scene.entityProcessors.onComponentAdded(this._entity);
} }
} }
} }
/**
*
* @param component
*/
private decreaseBits(component: Component) { private decreaseBits(component: Component) {
let bits = this._entity.componentBits; const bits = this._entity.componentBits;
let typeIndex = ComponentTypeManager.getIndexFor(TypeUtils.getType(component));
// 获取组件类型的索引,将其对应位掩码减1
const typeIndex = ComponentTypeManager.getIndexFor(TypeUtils.getType(component));
bits.set(typeIndex, bits.get(typeIndex) - 1); bits.set(typeIndex, bits.get(typeIndex) - 1);
} }
/**
*
* @param component
*/
private addBits(component: Component) { private addBits(component: Component) {
let bits = this._entity.componentBits; const bits = this._entity.componentBits;
let typeIndex = ComponentTypeManager.getIndexFor(TypeUtils.getType(component));
// 获取组件类型的索引,将其对应位掩码加1
const typeIndex = ComponentTypeManager.getIndexFor(TypeUtils.getType(component));
bits.set(typeIndex, bits.get(typeIndex) + 1); bits.set(typeIndex, bits.get(typeIndex) + 1);
} }
/** /**
* *
*
*/ */
public updateLists() { public updateLists() {
// 处理要删除的组件
if (this._componentsToRemoveList.length > 0) { if (this._componentsToRemoveList.length > 0) {
for (let i = 0, l = this._componentsToRemoveList.length; i < l; ++ i) { for (const component of this._componentsToRemoveList) {
let component = this._componentsToRemoveList[i]; // 从实体中删除组件,从组件列表和相关数据结构中删除组件
this.handleRemove(component); this.handleRemove(component);
let index = this._components.findIndex(c => c.id == component.id);
if (index != -1) // 从_components数组中删除组件
const index = this._components.findIndex((c) => c.id === component.id);
if (index !== -1) {
this._components.splice(index, 1); this._components.splice(index, 1);
}
// 从组件类型字典中删除组件
this.removeComponentsByType(component); this.removeComponentsByType(component);
} }
// 清空_componentsToRemove和_componentsToRemoveList
this._componentsToRemove = {}; this._componentsToRemove = {};
this._componentsToRemoveList.length = 0; this._componentsToRemoveList.length = 0;
} }
// 处理要添加的组件
if (this._componentsToAddList.length > 0) { if (this._componentsToAddList.length > 0) {
for (let i = 0, l = this._componentsToAddList.length; i < l; ++ i) { for (const component of this._componentsToAddList) {
let component = this._componentsToAddList[i]; // 如果组件可以更新,则添加到可更新组件列表中
if (isIUpdatable(component)) {
if (isIUpdatable(component))
this._updatableComponents.push(component); this._updatableComponents.push(component);
}
// 更新实体的组件位掩码,通知实体处理器一个组件已经添加
this.addBits(component); this.addBits(component);
this._entity.scene.entityProcessors.onComponentAdded(this._entity); this._entity.scene.entityProcessors.onComponentAdded(this._entity);
// 将组件添加到相应类型的fastList中,将组件添加到_components数组中
this.addComponentsByType(component); this.addComponentsByType(component);
this._components.push(component); this._components.push(component);
// 将组件添加到_tempBufferList中,稍后调用onAddedToEntity和onEnabled
this._tempBufferList.push(component); this._tempBufferList.push(component);
} }
// 在调用onAddedToEntity之前清除,以防添加更多组件 // 清空_componentsToAdd、_componentsToAddList和componentsToAddByType,设置_isComponentListUnsorted标志
this._componentsToAdd = {}; this._componentsToAdd = {};
this._componentsToAddList.length = 0; this._componentsToAddList.length = 0;
this.componentsToAddByType.clear(); this.componentsToAddByType.clear();
this._isComponentListUnsorted = true; this._isComponentListUnsorted = true;
} }
// 调用新添加组件的onAddedToEntity和onEnabled方法
if (this._tempBufferList.length > 0) { if (this._tempBufferList.length > 0) {
// 现在所有的组件都添加到了场景中,我们再次循环并调用onAddedToEntity/onEnabled for (const component of this._tempBufferList) {
for (let i = 0, l = this._tempBufferList.length; i < l; ++ i) {
let component = this._tempBufferList[i];
component.onAddedToEntity(); component.onAddedToEntity();
// enabled检查实体和组件 // 如果组件已启用,则调用onEnabled方法
if (component.enabled) { if (component.enabled) {
component.onEnabled(); component.onEnabled();
} }
} }
// 清空_tempBufferList
this._tempBufferList.length = 0; this._tempBufferList.length = 0;
} }
} }
public handleRemove(component: Component) { public handleRemove(component: Component) {
// 如果组件可以更新,从可更新组件列表中删除该组件
if (isIUpdatable(component) && this._updatableComponents.length > 0) { if (isIUpdatable(component) && this._updatableComponents.length > 0) {
let index = this._updatableComponents.findIndex((c) => (<any>c as Component).id == component.id); const index = this._updatableComponents.findIndex((c) => (<any>c as Component).id === component.id);
if (index != -1) if (index !== -1) {
this._updatableComponents.splice(index, 1); this._updatableComponents.splice(index, 1);
} }
}
// 更新实体的组件位掩码
this.decreaseBits(component); this.decreaseBits(component);
// 通知实体处理器一个组件已被删除
this._entity.scene.entityProcessors.onComponentRemoved(this._entity); this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
// 调用组件的onRemovedFromEntity方法,将其entity属性设置为null
component.onRemovedFromEntity(); component.onRemovedFromEntity();
component.entity = null; component.entity = null;
} }
private removeComponentsByType(component: Component) { private removeComponentsByType(component: Component) {
let fastList = this.componentsByType.get(TypeUtils.getType(component)); // 获取存储指定类型组件的fastList数组
let fastIndex = fastList.findIndex(c => c.id == component.id); const fastList = this.componentsByType.get(TypeUtils.getType(component));
if (fastIndex != -1) {
fastList.splice(fastIndex, 1); // 在fastList中查找要删除的组件
const index = fastList.findIndex((c) => c.id === component.id);
if (index !== -1) {
// 找到组件后,使用splice方法将其从fastList中删除
fastList.splice(index, 1);
} }
} }
private addComponentsByType(component: Component) { private addComponentsByType(component: Component) {
// 获取存储指定类型组件的fastList数组
let fastList = this.componentsByType.get(TypeUtils.getType(component)); let fastList = this.componentsByType.get(TypeUtils.getType(component));
if (!fastList) fastList = [];
// 如果fastList不存在,则创建一个空数组
if (!fastList) {
fastList = [];
}
// 在fastList中添加组件
fastList.push(component); fastList.push(component);
// 更新componentsByType字典,以便它包含fastList数组
this.componentsByType.set(TypeUtils.getType(component), fastList); this.componentsByType.set(TypeUtils.getType(component), fastList);
} }
/**
*
* @param component
*/
private removeComponentsToAddByType(component: Component) { private removeComponentsToAddByType(component: Component) {
// 获取待添加组件列表中指定类型的组件列表
let fastList = this.componentsToAddByType.get(TypeUtils.getType(component)); let fastList = this.componentsToAddByType.get(TypeUtils.getType(component));
// 在该列表中查找指定组件
let fastIndex = fastList.findIndex(c => c.id == component.id); let fastIndex = fastList.findIndex(c => c.id == component.id);
// 如果找到了指定组件,则从列表中移除它
if (fastIndex != -1) { if (fastIndex != -1) {
fastList.splice(fastIndex, 1); fastList.splice(fastIndex, 1);
} }
} }
/**
*
* @param component
*/
private addComponentsToAddByType(component: Component) { private addComponentsToAddByType(component: Component) {
// 获取待添加组件列表中指定类型的组件列表
let fastList = this.componentsToAddByType.get(TypeUtils.getType(component)); let fastList = this.componentsToAddByType.get(TypeUtils.getType(component));
// 如果指定类型的组件列表不存在,则创建一个新的列表
if (!fastList) fastList = []; if (!fastList) fastList = [];
// 向指定类型的组件列表中添加组件
fastList.push(component); fastList.push(component);
// 更新待添加组件列表中指定类型的组件列表
this.componentsToAddByType.set(TypeUtils.getType(component), fastList); this.componentsToAddByType.set(TypeUtils.getType(component), fastList);
} }
/** /**
* T的第一个组件并返回它 *
* (onAddedToEntity方法的组件) * @param type
* null * @param onlyReturnInitializedComponents
* @param type * @returns null
* @param onlyReturnInitializedComponents
*/ */
public getComponent<T extends Component>(type, onlyReturnInitializedComponents: boolean): T { public getComponent<T extends Component>(
type: new (...args: any[]) => T,
onlyReturnInitializedComponents: boolean
): T {
// 获取指定类型的组件列表
let fastList = this.componentsByType.get(type); let fastList = this.componentsByType.get(type);
if (fastList && fastList.length > 0)
return fastList[0] as T;
// 我们可以选择检查挂起的组件,以防addComponent和getComponent在同一个框架中被调用 // 如果指定类型的组件列表存在并且不为空,则返回第一个组件实例
if (fastList && fastList.length > 0) return fastList[0] as T;
// 如果不仅返回已初始化的组件,则检查待添加组件列表中是否存在指定类型的组件
if (!onlyReturnInitializedComponents) { if (!onlyReturnInitializedComponents) {
let fastToAddList = this.componentsToAddByType.get(type); let fastToAddList = this.componentsToAddByType.get(type);
if (fastToAddList && fastToAddList.length > 0) if (fastToAddList && fastToAddList.length > 0)
return fastToAddList[0] as T; return fastToAddList[0] as T;
} }
// 如果指定类型的组件列表为空且待添加组件列表中也不存在该类型的组件,则返回 null
return null; return null;
} }
/** /**
* T类型的所有组件使 *
* @param typeName * @param typeName
* @param components * @param components
* @returns
*/ */
public getComponents(typeName: any, components?: any[]) { public getComponents(typeName: any, components?: any[]) {
if (!components) // 如果没有传入组件实例数组,则创建一个新数组
components = []; if (!components) components = [];
// 获取指定类型的组件列表,并将其添加到组件实例数组中
let fastList = this.componentsByType.get(typeName); let fastList = this.componentsByType.get(typeName);
if (fastList) if (fastList) components = components.concat(fastList);
components = components.concat(fastList);
// 获取待添加组件列表中的指定类型的组件列表,并将其添加到组件实例数组中
let fastToAddList = this.componentsToAddByType.get(typeName); let fastToAddList = this.componentsToAddByType.get(typeName);
if (fastToAddList) if (fastToAddList) components = components.concat(fastToAddList);
components = components.concat(fastToAddList);
// 返回存储了指定类型的所有组件实例的数组
return components; return components;
} }
public update() { public update() {
this.updateLists(); this.updateLists();
if (this._updatableComponents.length > 0) { if (this._updatableComponents.length > 0) {
for (let i = 0, s = this._updatableComponents.length; i < s; ++ i) { for (let i = 0, s = this._updatableComponents.length; i < s; ++i) {
let updateComponent = this._updatableComponents[i]; let updateComponent = this._updatableComponents[i];
if (updateComponent.enabled) if (updateComponent.enabled)
updateComponent.update(); updateComponent.update();
@@ -284,8 +400,8 @@ module es {
} }
public onEntityTransformChanged(comp: ComponentTransform) { public onEntityTransformChanged(comp: ComponentTransform) {
if (this._components.length > 0 ){ if (this._components.length > 0) {
for (let i = 0, s = this._components.length; i < s; ++ i) { for (let i = 0, s = this._components.length; i < s; ++i) {
let component = this._components[i]; let component = this._components[i];
if (component.enabled) if (component.enabled)
component.onEntityTransformChanged(comp); component.onEntityTransformChanged(comp);
@@ -293,7 +409,7 @@ module es {
} }
if (this._componentsToAddList.length > 0) { if (this._componentsToAddList.length > 0) {
for (let i = 0, s = this._componentsToAddList.length; i < s; ++ i) { for (let i = 0, s = this._componentsToAddList.length; i < s; ++i) {
let component = this._componentsToAddList[i]; let component = this._componentsToAddList[i];
if (component.enabled) if (component.enabled)
component.onEntityTransformChanged(comp); component.onEntityTransformChanged(comp);
@@ -303,14 +419,14 @@ module es {
public onEntityEnabled() { public onEntityEnabled() {
if (this._components.length > 0) { if (this._components.length > 0) {
for (let i = 0, s = this._components.length; i < s; i ++) for (let i = 0, s = this._components.length; i < s; i++)
this._components[i].onEnabled(); this._components[i].onEnabled();
} }
} }
public onEntityDisabled() { public onEntityDisabled() {
if (this._components.length > 0) { if (this._components.length > 0) {
for (let i = 0, s = this._components.length; i < s; i ++) for (let i = 0, s = this._components.length; i < s; i++)
this._components[i].onDisabled(); this._components[i].onDisabled();
} }
} }
+196 -103
View File
@@ -1,28 +1,48 @@
module es { module es {
export class EntityList { export class EntityList {
public scene: Scene;
/** /**
* *
*/
public scene: Scene;
/**
*
*/ */
public _entities: Entity[] = []; public _entities: Entity[] = [];
/** /**
* 便 *
*/ */
public _entitiesToAdded: {[index: number]: Entity} = {}; public _entitiesToAdded: { [index: number]: Entity } = {};
/** /**
* 便 *
*/
public _entitiesToRemove: { [index: number]: Entity } = {};
/**
*
*/ */
public _entitiesToRemove: {[index: number]: Entity} = {};
public _entitiesToAddedList: Entity[] = []; public _entitiesToAddedList: Entity[] = [];
public _entitiesToRemoveList: Entity[] = [];
/** /**
* *
*/
public _entitiesToRemoveList: Entity[] = [];
/**
*
*/ */
public _isEntityListUnsorted: boolean; public _isEntityListUnsorted: boolean;
/** /**
* 便 *
*/ */
public _entityDict: Map<number, Set<Entity>> = new Map<number, Set<Entity>>(); public _entityDict: Map<number, Set<Entity>> = new Map<number, Set<Entity>>();
/**
*
*/
public _unsortedTags: Set<number> = new Set<number>(); public _unsortedTags: Set<number> = new Set<number>();
constructor(scene: Scene) { constructor(scene: Scene) {
@@ -55,132 +75,186 @@ module es {
} }
/** /**
* *
* @param entity * @param entity
*/ */
public remove(entity: Entity) { public remove(entity: Entity) {
// 防止在同一帧中添加或删除实体 // 如果实体在添加列表中,则将其从添加列表中移除
if (this._entitiesToAdded[entity.id]) { if (this._entitiesToAdded[entity.id]) {
let index = this._entitiesToAddedList.findIndex(e => e.id == entity.id); const index = this._entitiesToAddedList.findIndex((e) => e.id === entity.id);
if (index != -1) if (index !== -1) {
this._entitiesToAddedList.splice(index, 1); this._entitiesToAddedList.splice(index, 1);
}
delete this._entitiesToAdded[entity.id]; delete this._entitiesToAdded[entity.id];
return; return;
} }
// 如果实体不在添加列表中,则将其添加到移除列表中并将其添加到移除字典中
this._entitiesToRemoveList.push(entity); this._entitiesToRemoveList.push(entity);
if (!this._entitiesToRemove[entity.id]) if (!this._entitiesToRemove[entity.id]) {
this._entitiesToRemove[entity.id] = entity; this._entitiesToRemove[entity.id] = entity;
} }
}
/** /**
* *
*/ */
public removeAllEntities() { public removeAllEntities() {
// 清除字典和列表,以及是否已排序的标志
this._unsortedTags.clear(); this._unsortedTags.clear();
this._entitiesToAdded = {}; this._entitiesToAdded = {};
this._entitiesToAddedList.length = 0; this._entitiesToAddedList.length = 0;
this._isEntityListUnsorted = false; this._isEntityListUnsorted = false;
// 为什么我们要在这里更新列表?主要是为了处理在场景切换前被分离的实体 // 调用updateLists方法,以处理要移除的实体
// 它们仍然会在_entitiesToRemove列表中,这将由updateLists处理。
this.updateLists(); this.updateLists();
for (let i = 0; i < this._entities.length; i++) { // 标记并移除所有实体
this._entities[i]._isDestroyed = true; for (const entity of this._entities) {
this._entities[i].onRemovedFromScene(); entity._isDestroyed = true;
this._entities[i].scene = null; entity.onRemovedFromScene();
entity.scene = null;
} }
// 清空实体列表和实体字典
this._entities.length = 0; this._entities.length = 0;
this._entityDict.clear(); this._entityDict.clear();
} }
/** /**
* EntityList管理 *
* @param entity * @param entity
* @returns truefalse
*/ */
public contains(entity: Entity): boolean { public contains(entity: Entity): boolean {
// 检查实体是否存在于_entitiesToAdded字典中
return !!this._entitiesToAdded[entity.id]; return !!this._entitiesToAdded[entity.id];
} }
public getTagList(tag: number) { /**
*
*
* @param tag
* @returns
*/
public getTagList(tag: number): Set<Entity> {
// 尝试从_entityDict中获取具有指定标签的实体列表
let list = this._entityDict.get(tag); let list = this._entityDict.get(tag);
// 如果列表不存在,则创建一个新的Set实例,并添加到_entityDict中
if (!list) { if (!list) {
list = new Set(); list = new Set<Entity>();
this._entityDict.set(tag, list); this._entityDict.set(tag, list);
} }
return list; return list;
} }
/**
*
* @param entity
*/
public addToTagList(entity: Entity) { public addToTagList(entity: Entity) {
this.getTagList(entity.tag).add(entity); // 获取标签列表
const list = this.getTagList(entity.tag);
// 将实体添加到标签列表中
list.add(entity);
// 添加未排序标志
this._unsortedTags.add(entity.tag); this._unsortedTags.add(entity.tag);
} }
/**
*
* @param entity
*/
public removeFromTagList(entity: Entity) { public removeFromTagList(entity: Entity) {
let list = this._entityDict.get(entity.tag); // 获取实体的标签列表
if (list) const list = this._entityDict.get(entity.tag);
// 如果标签列表存在,则从中移除实体
if (list) {
list.delete(entity); list.delete(entity);
} }
}
/**
* Update方法
* UpdateInterval为1或Time.frameCount模除UpdateInterval为0Update
*/
public update() { public update() {
for (let i = 0, s = this._entities.length; i < s; ++ i) { for (let i = 0; i < this._entities.length; i++) {
let entity = this._entities[i]; const entity = this._entities[i];
if (entity.enabled && (entity.updateInterval == 1 || Time.frameCount % entity.updateInterval == 0)) if (entity.enabled && (entity.updateInterval === 1 || Time.frameCount % entity.updateInterval === 0)) {
entity.update(); entity.update();
} }
} }
}
/**
*
*/
public updateLists() { public updateLists() {
// 处理要移除的实体
if (this._entitiesToRemoveList.length > 0) { if (this._entitiesToRemoveList.length > 0) {
for (let i = 0, s = this._entitiesToRemoveList.length; i < s; ++ i) { for (const entity of this._entitiesToRemoveList) {
let entity = this._entitiesToRemoveList[i]; // 从标签列表中删除实体
this.removeFromTagList(entity); this.removeFromTagList(entity);
// 处理常规实体列表 // 从场景实体列表中删除实体
let index = this._entities.findIndex(e => e.id == entity.id); const index = this._entities.findIndex((e) => e.id === entity.id);
if (index != -1) if (index !== -1) {
this._entities.splice(index, 1); this._entities.splice(index, 1);
}
// 调用实体的onRemovedFromScene方法,并将其scene属性设置为null
entity.onRemovedFromScene(); entity.onRemovedFromScene();
entity.scene = null; entity.scene = null;
// 通知场景实体处理器,一个实体已被移除
this.scene.entityProcessors.onEntityRemoved(entity); this.scene.entityProcessors.onEntityRemoved(entity);
} }
// 清空要移除的实体列表和字典
this._entitiesToRemove = {}; this._entitiesToRemove = {};
this._entitiesToRemoveList.length = 0; this._entitiesToRemoveList.length = 0;
} }
// 处理要添加的实体
if (this._entitiesToAddedList.length > 0) { if (this._entitiesToAddedList.length > 0) {
for (let i = 0, s = this._entitiesToAddedList.length; i < s; ++ i) { // 添加实体到场景实体列表和标签列表中
let entity = this._entitiesToAddedList[i]; for (const entity of this._entitiesToAddedList) {
this._entities.push(entity); this._entities.push(entity);
entity.scene = this.scene; entity.scene = this.scene;
this.addToTagList(entity); this.addToTagList(entity);
}
// 通知场景实体处理器,有新的实体已添加
for (const entity of this._entitiesToAddedList) {
this.scene.entityProcessors.onEntityAdded(entity); this.scene.entityProcessors.onEntityAdded(entity);
} }
for (let i = 0, s = this._entitiesToAddedList.length; i < s; ++ i) { // 调用实体的onAddedToScene方法,以允许它们执行任何场景相关的操作
let entity = this._entitiesToAddedList[i]; for (const entity of this._entitiesToAddedList) {
entity.onAddedToScene(); entity.onAddedToScene();
} }
// 清空要添加的实体列表和字典
this._entitiesToAdded = {}; this._entitiesToAdded = {};
this._entitiesToAddedList.length = 0; this._entitiesToAddedList.length = 0;
} }
} }
/** /**
* name的实体null * name的实体null
* @param name * @param name
*/ */
public findEntity(name: string) { public findEntity(name: string) {
if (this._entities.length > 0) { if (this._entities.length > 0) {
for (let i = 0, s = this._entities.length; i < s; ++ i) { for (let i = 0, s = this._entities.length; i < s; ++i) {
let entity = this._entities[i]; let entity = this._entities[i];
if (entity.name == name) if (entity.name == name)
return entity; return entity;
@@ -188,7 +262,7 @@ module es {
} }
if (this._entitiesToAddedList.length > 0) { if (this._entitiesToAddedList.length > 0) {
for (let i = 0, s = this._entitiesToAddedList.length; i < s; ++ i) { for (let i = 0, s = this._entitiesToAddedList.length; i < s; ++i) {
let entity = this._entitiesToAddedList[i]; let entity = this._entitiesToAddedList[i];
if (entity.name == name) if (entity.name == name)
return entity; return entity;
@@ -199,37 +273,45 @@ module es {
} }
/** /**
* * ID在场景中查找对应实体
* @param id * @param id ID
* @returns * @returns null
*/ */
public findEntityById(id: number) { public findEntityById(id: number) {
// 遍历场景中所有实体
if (this._entities.length > 0) { if (this._entities.length > 0) {
for (let i = 0, s = this._entities.length; i < s; ++ i) { for (let i = 0, s = this._entities.length; i < s; ++i) {
let entity = this._entities[i]; let entity = this._entities[i];
// 如果实体的ID匹配,返回该实体
if (entity.id == id) if (entity.id == id)
return entity; return entity;
} }
} }
// 在未添加的实体列表中查找
return this._entitiesToAdded[id]; return this._entitiesToAdded[id];
} }
/** /**
* *
* List可以通过ListPool.free放回池中 * @param tag
* @param tag * @returns
*/ */
public entitiesWithTag(tag: number) { public entitiesWithTag(tag: number): Entity[] {
let list = this.getTagList(tag); // 从字典中获取对应标签的实体列表
const list = this.getTagList(tag);
// 从对象池中获取 Entity 类型的数组
const returnList = ListPool.obtain<Entity>(Entity);
let returnList = ListPool.obtain<Entity>(Entity);
if (list.size > 0) { if (list.size > 0) {
for (let entity of list) { // 将实体列表中的实体添加到返回列表中
for (const entity of list) {
returnList.push(entity); returnList.push(entity);
} }
} }
// 返回已填充好实体的返回列表
return returnList; return returnList;
} }
@@ -251,98 +333,110 @@ module es {
} }
/** /**
* T类型的组件 *
* @param type * @param type
* @returns null
*/ */
public findComponentOfType<T extends Component>(type): T { public findComponentOfType<T extends Component>(type: new (...args: any[]) => T): T | null {
if (this._entities.length > 0 ){ // 遍历场景中的所有实体,查找具有给定类型的组件
for (let i = 0, s = this._entities.length; i < s; i++) { for (const entity of this._entities) {
let entity = this._entities[i];
if (entity.enabled) { if (entity.enabled) {
let comp = entity.getComponent<T>(type); const comp = entity.getComponent(type);
if (comp) if (comp) {
return comp; return comp;
} }
} }
} }
if (this._entitiesToAddedList.length > 0) { // 遍历待添加的实体列表中的所有实体,查找具有给定类型的组件
for (let i = 0; i < this._entitiesToAddedList.length; i++) { for (const entity of this._entitiesToAddedList) {
let entity = this._entitiesToAddedList[i];
if (entity.enabled) { if (entity.enabled) {
let comp = entity.getComponent<T>(type); const comp = entity.getComponent(type);
if (comp) if (comp) {
return comp; return comp;
} }
} }
} }
// 如果找不到具有给定类型的组件,则返回null
return null; return null;
} }
/** /**
* T类型的组件 *
* List可以通过ListPool.free放回池中 * @param type
* @param type * @returns
*/ */
public findComponentsOfType<T extends Component>(type): T[] { public findComponentsOfType<T extends Component>(type: new (...args: any[]) => T): T[] {
let comps = ListPool.obtain<T>(type); // 从池中获取一个可重用的组件列表
if (this._entities.length > 0) { const comps = ListPool.obtain<T>(type);
for (let i = 0, s = this._entities.length; i < s; i++) {
let entity = this._entities[i]; // 遍历场景中的所有实体,查找具有给定类型的组件并添加到组件列表中
if (entity.enabled) for (const entity of this._entities) {
if (entity.enabled) {
entity.getComponents(type, comps); entity.getComponents(type, comps);
} }
} }
if (this._entitiesToAddedList.length > 0) { // 遍历待添加的实体列表中的所有实体,查找具有给定类型的组件并添加到组件列表中
for (let i = 0, s = this._entitiesToAddedList.length; i < s; i ++) { for (const entity of this._entitiesToAddedList) {
let entity = this._entitiesToAddedList[i]; if (entity.enabled) {
if (entity.enabled)
entity.getComponents(type, comps); entity.getComponents(type, comps);
} }
} }
// 返回具有给定类型的所有组件的列表
return comps; return comps;
} }
/** /**
* *
* @param types * @param types
* @returns * @returns
*/ */
public findEntitiesOfComponent(...types: any[]): Entity[] { public findEntitiesOfComponent(...types: any[]): Entity[] {
let entities = []; const entities = [];
if (this._entities.length > 0) {
for (let i = 0, s = this._entities.length; i < s; i++) { // 遍历所有已存在的实体
if (this._entities[i].enabled) { for (const entity of this._entities) {
// 只有启用的实体才会被考虑
if (entity.enabled) {
// 如果types数组为空,直接将实体添加到结果数组中
if (types.length === 0) {
entities.push(entity);
continue;
}
// 对于每个指定的组件类型,检查实体是否具有该组件
let meet = true; let meet = true;
if (types.length > 0) for (const type of types) {
for (let t = 0, ts = types.length; t < ts; t ++) { const hasComp = entity.hasComponent(type);
let type = types[t];
let hasComp = this._entities[i].hasComponent(type);
if (!hasComp) { if (!hasComp) {
meet = false; meet = false;
break; break;
} }
} }
// 如果实体满足要求,将其添加到结果数组中
if (meet) { if (meet) {
entities.push(this._entities[i]); entities.push(entity);
}
} }
} }
} }
if (this._entitiesToAddedList.length > 0) { // 遍历所有等待添加的实体,和上面的操作类似
for (let i = 0, s = this._entitiesToAddedList.length; i < s; i ++) { for (const entity of this._entitiesToAddedList) {
let entity = this._entitiesToAddedList[i];
if (entity.enabled) { if (entity.enabled) {
if (types.length === 0) {
entities.push(entity);
continue;
}
let meet = true; let meet = true;
if (types.length > 0) for (const type of types) {
for (let t = 0, ts = types.length; t < ts; t ++) { const hasComp = entity.hasComponent(type);
let type = types[t];
let hasComp = entity.hasComponent(type);
if (!hasComp) { if (!hasComp) {
meet = false; meet = false;
break; break;
@@ -354,10 +448,9 @@ module es {
} }
} }
} }
}
return entities; return entities;
} }
} }
} }
+112 -44
View File
@@ -1,113 +1,181 @@
module es { module es {
export class EntityProcessorList { export class EntityProcessorList {
private _processors: EntitySystem[] = []; private _processors: EntitySystem[] = []; // 处理器列表
private _orderDirty: boolean = false; private _orderDirty: boolean = false; // 处理器排序标志
/** 获取系统列表 */
/** 获取处理器列表 */
public get processors() { public get processors() {
return this._processors; return this._processors;
} }
/** 系统数量 */ /** 获取处理器数量 */
public get count() { public get count() {
return this._processors.length; return this._processors.length;
} }
public add(processor: EntitySystem) { /**
*
* @param processor
*/
public add(processor: EntitySystem): void {
this._processors.push(processor); this._processors.push(processor);
} }
public remove(processor: EntitySystem) { /**
*
* @param processor
*/
public remove(processor: EntitySystem): void {
// 使用 es.List 类的 remove() 方法从处理器列表中移除指定处理器
new es.List(this._processors).remove(processor); new es.List(this._processors).remove(processor);
} }
public onComponentAdded(entity: Entity) { /**
*
* @param entity
*/
public onComponentAdded(entity: Entity): void {
this.notifyEntityChanged(entity); this.notifyEntityChanged(entity);
} }
public onComponentRemoved(entity: Entity) { /**
*
* @param entity
*/
public onComponentRemoved(entity: Entity): void {
this.notifyEntityChanged(entity); this.notifyEntityChanged(entity);
} }
public onEntityAdded(entity: Entity) { /**
*
* @param entity
*/
public onEntityAdded(entity: Entity): void {
this.notifyEntityChanged(entity); this.notifyEntityChanged(entity);
} }
public onEntityRemoved(entity: Entity) { /**
*
* @param entity
*/
public onEntityRemoved(entity: Entity): void {
this.removeFromProcessors(entity); this.removeFromProcessors(entity);
} }
public begin() { /** 在处理器列表上开始循环 */
public begin(): void {
} }
public update() { /** 更新处理器列表 */
if (this._processors.length == 0) public update(): void {
// 如果处理器列表为空,则直接返回
if (this._processors.length === 0) {
return; return;
}
// 如果需要重新排序处理器列表
if (this._orderDirty) { if (this._orderDirty) {
// 进行排序 // 对处理器列表进行排序
this._processors = this._processors.sort((a, b) => a.updateOrder - b.updateOrder); this._processors.sort((a, b) => a.updateOrder - b.updateOrder);
for (let i = 0, s = this._processors.length; i < s; ++ i) {
// 重新设置处理器的更新顺序
for (let i = 0, s = this._processors.length; i < s; ++i) {
const processor = this._processors[i]; const processor = this._processors[i];
processor.setUpdateOrder(i); processor.setUpdateOrder(i);
} }
// 将标志设置为“未脏”
this.clearDirty(); this.clearDirty();
} }
for (let i = 0, s = this._processors.length; i < s; ++ i) { // 调用每个处理器的 update() 方法
this._processors[i].update(); for (let i = 0, s = this._processors.length; i < s; ++i) {
const processor = this._processors[i];
processor.update();
} }
} }
public lateUpdate() { /** 在处理器列表上完成循环 */
if (this._processors.length == 0) public end(): void {
return;
for (let i = 0, s = this._processors.length; i < s; ++ i) {
this._processors[i].lateUpdate();
}
} }
public end() { /** 设置处理器排序标志 */
public setDirty(): void {
}
public setDirty() {
this._orderDirty = true; this._orderDirty = true;
} }
public clearDirty() { /** 清除处理器排序标志 */
public clearDirty(): void {
this._orderDirty = false; this._orderDirty = false;
} }
/**
*
* @param type
* @returns
*/
public getProcessor<T extends EntitySystem>(type: new (...args: any[]) => T): T { public getProcessor<T extends EntitySystem>(type: new (...args: any[]) => T): T {
if (this._processors.length == 0) // 如果处理器列表为空,则返回null
if (this._processors.length === 0) {
return null; return null;
}
for (let i = 0, s = this._processors.length; i < s; ++ i) { // 遍历处理器列表,查找指定类型的处理器
let processor = this._processors[i]; for (let i = 0, s = this._processors.length; i < s; ++i) {
if (processor instanceof type) const processor = this._processors[i];
// 如果当前处理器是指定类型的实例,则返回当前处理器
if (processor instanceof type) {
return processor as T; return processor as T;
} }
}
// 如果没有找到指定类型的处理器,则返回null
return null; return null;
} }
protected notifyEntityChanged(entity: Entity) { /**
if (this._processors.length == 0) *
* @param entity
*/
protected notifyEntityChanged(entity: Entity): void {
if (this._processors.length === 0) {
return; return;
}
for (let i = 0, s = this._processors.length; i < s; ++ i) { // 遍历处理器列表,调用每个处理器的 onChanged() 方法
this._processors[i].onChanged(entity); for (let i = 0, s = this._processors.length; i < s; ++i) {
const processor = this._processors[i];
processor.onChanged(entity);
} }
} }
protected removeFromProcessors(entity: Entity) { /**
if (this._processors.length == 0) *
* @param entity
*/
protected removeFromProcessors(entity: Entity): void {
if (this._processors.length === 0) {
return; return;
}
for (let i = 0, s = this._processors.length; i < s; ++ i) { // 遍历处理器列表,调用每个处理器的 remove() 方法
this._processors[i].remove(entity); for (let i = 0, s = this._processors.length; i < s; ++i) {
const processor = this._processors[i];
processor.remove(entity);
}
}
/** 在处理器列表上进行后期更新 */
public lateUpdate(): void {
if (this._processors.length === 0) {
return;
}
// 调用每个处理器的 lateUpdate() 方法
for (let i = 0, s = this._processors.length; i < s; ++i) {
const processor = this._processors[i];
processor.lateUpdate();
} }
} }
} }
+52 -45
View File
@@ -1,89 +1,96 @@
module es { module es {
export class HashHelpers { export class HashHelpers {
// 哈希冲突阈值,超过此值将使用另一种哈希算法
public static readonly hashCollisionThreshold: number = 100; public static readonly hashCollisionThreshold: number = 100;
// 哈希值用于计算哈希表索引的质数
public static readonly hashPrime: number = 101; public static readonly hashPrime: number = 101;
// 一组预定义的质数,用于计算哈希表容量
/** public static readonly primes = [
* 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
*
* Hashtable当前的容量为x
* 2x2x的质数p_1p_2...p_i...p_n使p_n-1 < 2x < p_n
*
* IEh1(key)+i*h2(key)0 <= i < size.h2和size必须是相对质数
*/
public static readonly primes = [3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437, 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369]; 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369
];
/** // 可分配的最大数组长度,用于避免 OutOfMemoryException
* Array.MaxArrayLength小的最大质数
*/
public static readonly maxPrimeArrayLength = 0x7FEFFFFD; public static readonly maxPrimeArrayLength = 0x7FEFFFFD;
/**
*
* @param candidate
* @returns
*/
public static isPrime(candidate: number): boolean { public static isPrime(candidate: number): boolean {
if ((candidate & 1) != 0){ if ((candidate & 1) !== 0) { // 位运算判断奇偶性
let limit = Math.sqrt(candidate); let limit = Math.sqrt(candidate);
for (let divisor = 3; divisor <= limit; divisor += 2){ for (let divisor = 3; divisor <= limit; divisor += 2) { // 奇数因子判断
if ((candidate & divisor) == 0) if ((candidate % divisor) === 0) {
return false; return false;
} }
}
return true; return true;
} }
return (candidate == 2); return (candidate === 2); // 2是质数
} }
public static getPrime(min: number): number{ /**
if (min < 0) *
throw new Error("参数错误 min不能小于0"); * @param min
* @returns
*/
public static getPrime(min: number): number {
if (min < 0) {
throw new Error("参数错误 min 不能小于0");
}
for (let i = 0; i < this.primes.length; i ++){ for (let i = 0; i < this.primes.length; i++) {
let prime = this.primes[i]; let prime = this.primes[i];
if (prime >= min) return prime; if (prime >= min) {
return prime;
}
} }
// 在我们预定义的表之外,计算的方式稍复杂。 // 在预定义的质数列表之外,需要计算最小的质数
for (let i = (min | 1); i < Number.MAX_VALUE; i += 2){ for (let i = (min | 1); i < Number.MAX_VALUE; i += 2) { // 从 min 向上计算奇数
if (this.isPrime(i) && ((i - 1) % this.hashPrime != 0)) if (this.isPrime(i) && ((i - 1) % this.hashPrime !== 0)) { // i是质数且不是hashPrime的倍数
return i; return i;
} }
}
return min; return min;
} }
/** /**
* *
* @param oldSize * @param oldSize
* @returns * @returns
*/ */
public static expandPrime(oldSize: number): number { public static expandPrime(oldSize: number): number {
let newSize = 2 * oldSize; let newSize = 2 * oldSize;
// 在遇到容量溢出之前,允许哈希特表增长到最大可能的大小 // 在遇到容量溢出之前,允许哈希特表增长到最大可能的大小
// 请注意,即使当_items.Length溢出时,这项检查也会起作用 // 请注意,即使当_items.Length溢出时,这项检查也会起作用
if (newSize > this.maxPrimeArrayLength && this.maxPrimeArrayLength > oldSize){ if (newSize > this.maxPrimeArrayLength && this.maxPrimeArrayLength > oldSize) {
return this.maxPrimeArrayLength; return this.maxPrimeArrayLength;
} }
return this.getPrime(newSize); return this.getPrime(newSize);
} }
public static getHashCode(str){ /**
let s; *
if (typeof str == 'object'){ * @param str
s = JSON.stringify(str); * @returns
} else { */
s = str.toString(); public static getHashCode(str: string): number {
}
let hash = 0; let hash = 0;
if (s.length == 0) return hash; if (str.length === 0) {
for (let i = 0; i < s.length; i ++){ return hash;
let char = s.charCodeAt(i); }
hash = ((hash << 5) - hash) + char; for (let i = 0; i < str.length; i++) {
hash = hash & hash; let char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char; // 采用 FNV-1a 哈希算法
hash = hash & hash; // 将hash值转换为32位整数
} }
return hash; return hash;
} }
} }
+47 -14
View File
@@ -1,59 +1,92 @@
module es { module es {
/** 提供帧定时信息 */ /**
*
*/
export class Time { export class Time {
/** 游戏运行的总时间 */ /** 游戏运行的总时间,单位为秒 */
public static totalTime: number = 0; public static totalTime: number = 0;
/** deltaTime的未缩放版本。不受时间尺度的影响 */
/** deltaTime 的未缩放版本,不受时间尺度的影响 */
public static unscaledDeltaTime: number = 0; public static unscaledDeltaTime: number = 0;
/** 前一帧到当前帧的时间增量,按时间刻度进行缩放 */ /** 前一帧到当前帧的时间增量,按时间刻度进行缩放 */
public static deltaTime: number = 0; public static deltaTime: number = 0;
/** 时间刻度缩放 */
/** 时间刻度缩放,可以加快或减慢游戏时间 */
public static timeScale = 1; public static timeScale = 1;
/** DeltaTime可以为的最大值 */
/** DeltaTime 可以为的最大值,避免游戏出现卡顿情况 */
public static maxDeltaTime = Number.MAX_VALUE; public static maxDeltaTime = Number.MAX_VALUE;
/** 已传递的帧总数 */ /** 已传递的帧总数 */
public static frameCount = 0; public static frameCount = 0;
/** 自场景加载以来的总时间 */
/** 自场景加载以来的总时间,单位为秒 */
public static timeSinceSceneLoad: number = 0; public static timeSinceSceneLoad: number = 0;
/** 上一次记录的时间,用于计算两次调用 update 之间的时间差 */
private static _lastTime = -1; private static _lastTime = -1;
/**
*
* @param currentTime
* @param useEngineTime 使
*/
public static update(currentTime: number, useEngineTime: boolean) { public static update(currentTime: number, useEngineTime: boolean) {
let dt = 0; let dt = 0;
if (useEngineTime) { if (useEngineTime) {
dt = currentTime; dt = currentTime;
} else { } else {
if (currentTime == -1) { // 如果当前时间为 -1,则表示使用系统时间
if (currentTime === -1) {
currentTime = Date.now(); currentTime = Date.now();
} }
if (this._lastTime == -1) // 如果上一次记录的时间为 -1,则表示当前为第一次调用 update
if (this._lastTime === -1) {
this._lastTime = currentTime; this._lastTime = currentTime;
}
// 计算两次调用 update 之间的时间差,并将其转换为秒
dt = (currentTime - this._lastTime) / 1000; dt = (currentTime - this._lastTime) / 1000;
} }
if (dt > this.maxDeltaTime) // 如果计算得到的时间差超过了最大时间步长,则将其限制为最大时间步长
if (dt > this.maxDeltaTime) {
dt = this.maxDeltaTime; dt = this.maxDeltaTime;
}
// 更新时间管理器的各个属性
this.totalTime += dt; this.totalTime += dt;
this.deltaTime = dt * this.timeScale; this.deltaTime = dt * this.timeScale;
this.unscaledDeltaTime = dt; this.unscaledDeltaTime = dt;
this.timeSinceSceneLoad += dt; this.timeSinceSceneLoad += dt;
this.frameCount++; this.frameCount++;
// 记录当前时间,以备下一次调用 update 使用
this._lastTime = currentTime; this._lastTime = currentTime;
} }
public static sceneChanged() { public static sceneChanged() {
this.timeSinceSceneLoad = 0; this.timeSinceSceneLoad = 0;
} }
/** /**
* 使delta的间隔值true *
* @param interval * @param interval
* @returns
*/ */
public static checkEvery(interval: number) { public static checkEvery(interval: number): boolean {
// 我们减去了delta,因为timeSinceSceneLoad已经包含了这个update ticks delta // 计算当前时刻所经过的完整时间间隔个数(向下取整)
return MathHelper.toInt(this.timeSinceSceneLoad / interval) > MathHelper.toInt((this.timeSinceSceneLoad - this.deltaTime) / interval); const passedIntervals = Math.floor(this.timeSinceSceneLoad / interval);
// 计算上一帧到当前帧经过的时间所包含的时间间隔个数(向下取整)
const deltaIntervals = Math.floor(this.deltaTime / interval);
// 如果当前时刻所经过的时间间隔数比上一帧所经过的时间间隔数多,则说明时间间隔已过去
return passedIntervals > deltaIntervals;
} }
} }
} }
+80 -50
View File
@@ -1,48 +1,64 @@
class TimeUtils { module es {
export class TimeUtils {
/** /**
* ID *
* @param d * @param d
* @returns ID * @returns
*/ */
public static monthId(d: Date = null): number { public static monthId(d: Date = null): number {
// 如果传入了时间,则使用传入的时间,否则使用当前时间
d = d ? d : new Date(); d = d ? d : new Date();
// 获取当前年份
let y = d.getFullYear(); let y = d.getFullYear();
// 获取当前月份,并将月份转化为两位数的字符串格式
let m = d.getMonth() + 1; let m = d.getMonth() + 1;
let g = m < 10 ? "0" : ""; let g = m < 10 ? "0" : "";
// 返回年份和月份的数字组合
return parseInt(y + g + m); return parseInt(y + g + m);
} }
/** /**
* ID *
* @param d * @param t - 使
* @returns ID * @returns
*/ */
public static dateId(t: Date = null): number { public static dateId(t: Date = null): number {
// 如果传入了时间,则使用传入的时间,否则使用当前时间
t = t ? t : new Date(); t = t ? t : new Date();
// 获取当前月份,并将月份转化为两位数的字符串格式
let m: number = t.getMonth() + 1; let m: number = t.getMonth() + 1;
let a = m < 10 ? "0" : ""; let a = m < 10 ? "0" : "";
// 获取当前日期,并将日期转化为两位数的字符串格式
let d: number = t.getDate(); let d: number = t.getDate();
let b = d < 10 ? "0" : ""; let b = d < 10 ? "0" : "";
// 返回年份、月份和日期的数字组合
return parseInt(t.getFullYear() + a + m + b + d); return parseInt(t.getFullYear() + a + m + b + d);
} }
/** /**
* ID *
* @param d * @param d - 使
* @returns ID * @param first - 1true
* @returns
*/ */
public static weekId(d: Date = null, first: boolean = true): number { public static weekId(d: Date = null, first: boolean = true): number {
d = d ? d : new Date(); d = d ? d : new Date();
let c: Date = new Date(); const c: Date = new Date(d.getTime()); // 复制一个新的日期对象,以免改变原始日期对象
c.setTime(d.getTime());
c.setDate(1); c.setDate(1);
c.setMonth(0);//当年第一天 c.setMonth(0); // 将日期设置为当年第一天
let year: number = c.getFullYear(); const year: number = c.getFullYear();
let firstDay: number = c.getDay(); let firstDay: number = c.getDay();
if (firstDay == 0) { if (firstDay == 0) {
firstDay = 7; firstDay = 7;
} }
let max: boolean = false; let max: boolean = false;
if (firstDay <= 4) { if (firstDay <= 4) {
max = firstDay > 1; max = firstDay > 1;
@@ -50,15 +66,19 @@ class TimeUtils {
} else { } else {
c.setDate(c.getDate() + 7 - firstDay + 1); c.setDate(c.getDate() + 7 - firstDay + 1);
} }
let num: number = this.diffDay(d, c, false);
let num: number = this.diffDay(d, c, false); // 计算当前日期与本年度的第一个星期一之间的天数
if (num < 0) { if (num < 0) {
// 当前日期在本年度第一个星期一之前,则返回上一年度的最后一个星期
c.setDate(1); c.setDate(1);
c.setMonth(0);//当年第一天 c.setMonth(0);
c.setDate(c.getDate() - 1); c.setDate(c.getDate() - 1);
return this.weekId(c, false); return this.weekId(c, false);
} }
let week: number = num / 7;
let weekIdx: number = Math.floor(week) + 1; // 计算当前日期在本年度中是第几个星期
const week: number = Math.floor(num / 7);
const weekIdx: number = Math.floor(week) + 1;
if (weekIdx == 53) { if (weekIdx == 53) {
c.setTime(d.getTime()); c.setTime(d.getTime());
c.setDate(c.getDate() - 1); c.setDate(c.getDate() - 1);
@@ -67,32 +87,41 @@ class TimeUtils {
endDay = 7; endDay = 7;
} }
if (first && (!max || endDay < 4)) { if (first && (!max || endDay < 4)) {
// 如果当前日期在本年度的最后一个星期并且当前年度的星期数不足53或当前日期在本年度第53周的星期4或更早,则返回下一年度的第1周
c.setFullYear(c.getFullYear() + 1); c.setFullYear(c.getFullYear() + 1);
c.setDate(1); c.setDate(1);
c.setMonth(0);//当年第一天 c.setMonth(0);
return this.weekId(c, false); return this.weekId(c, false);
} }
} }
let g: string = weekIdx > 9 ? "" : "0"; const g: string = weekIdx > 9 ? "" : "0";
let s: string = year + "00" + g + weekIdx;//加上00防止和月份ID冲突 const s: string = year + "00" + g + weekIdx; // 加上00防止和月份ID冲突
return parseInt(s); return parseInt(s);
} }
/** /**
* a比b小 *
* @param a
* @param b
* @param fixOne
* @returns
*/ */
public static diffDay(a: Date, b: Date, fixOne: boolean = false): number { public static diffDay(a: Date, b: Date, fixOne: boolean = false): number {
let x = (a.getTime() - b.getTime()) / 86400000; let x = (a.getTime() - b.getTime()) / 86400000; // 计算两个日期相差的毫秒数,然后除以一天的毫秒数,得到相差的天数
return fixOne ? Math.ceil(x) : Math.floor(x); return fixOne ? Math.ceil(x) : Math.floor(x); // 如果 fixOne 参数为 true,则将相差天数四舍五入到整数,否则向下取整
} }
/** /**
* *
* @param d
* @returns
*/ */
public static getFirstDayOfWeek(d?: Date): Date { public static getFirstDayOfWeek(d: Date = new Date()): Date {
d = d ? d : new Date(); // 获取当前日期是星期几,如果是0,则设置为7
let day = d.getDay() || 7; let dayOfWeek = d.getDay() || 7;
return new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1 - day, 0, 0, 0, 0); // 计算出指定日期所在周的第一天,即将指定日期减去星期几再加1
// 这里用1减去dayOfWeek是为了保证星期一为一周的第一天
return new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1 - dayOfWeek, 0, 0, 0, 0);
} }
/** /**
@@ -112,7 +141,9 @@ class TimeUtils {
} }
/** /**
* @returns 2018-12-12 * "YYYY-MM-DD"
* @param date
* @returns
*/ */
public static formatDate(date: Date): string { public static formatDate(date: Date): string {
let y = date.getFullYear(); let y = date.getFullYear();
@@ -123,8 +154,11 @@ class TimeUtils {
return y + '-' + m + '-' + d; return y + '-' + m + '-' + d;
} }
/** /**
* @returns 2018-12-12 12:12:12 * "YYYY-MM-DD HH:mm:ss"
* @param date
* @returns
*/ */
public static formatDateTime(date: Date): string { public static formatDateTime(date: Date): string {
let y = date.getFullYear(); let y = date.getFullYear();
@@ -141,11 +175,14 @@ class TimeUtils {
} }
/** /**
* @returns s 2018-12-12 2018-12-12 12:12:12 * Date对象
* @param s 2022-01-01
* @returns Date对象Date对象
*/ */
public static parseDate(s: string): Date { public static parseDate(s: string): Date {
let t = Date.parse(s); let t = Date.parse(s);
if (!isNaN(t)) { if (!isNaN(t)) {
// 如果日期字符串中的分隔符为“-”,则需要先将其转换为“/”,否则解析会失败
return new Date(Date.parse(s.replace(/-/g, "/"))); return new Date(Date.parse(s.replace(/-/g, "/")));
} else { } else {
return new Date(); return new Date();
@@ -153,13 +190,11 @@ class TimeUtils {
} }
/** /**
* *
* @param time * @param time
* @param partition * @param partition
* @param showHour * @param showHour
* @return , , * @returns
*
* 比如: time = 4351; secondToTime(time)返回字符串01:12:31;
*/ */
public static secondToTime(time: number = 0, partition: string = ":", showHour: boolean = true): string { public static secondToTime(time: number = 0, partition: string = ":", showHour: boolean = true): string {
let hours: number = Math.floor(time / 3600); let hours: number = Math.floor(time / 3600);
@@ -183,30 +218,25 @@ class TimeUtils {
return timeStr; return timeStr;
} }
/** /**
* *
* @param time * @param time "01:30:15" 13015
* @param partition * @param partition ":"
* @return * @returns
* @throws Error Exception
*
* 1 trace(MillisecondTransform.timeToMillisecond("00:60:00"))
* 3600000
*
*
* 2 trace(MillisecondTransform.timeToMillisecond("00.60.00","."))
* 3600000
*/ */
public static timeToMillisecond(time: string, partition: string = ":"): string { public static timeToMillisecond(time: string, partition: string = ":"): string {
let _ary: any[] = time.split(partition); let _ary: any[] = time.split(partition);
let timeNum: number = 0; let timeNum: number = 0;
let len: number = _ary.length; let len: number = _ary.length;
// 将时间转换成毫秒数
for (let i: number = 0; i < len; i++) { for (let i: number = 0; i < len; i++) {
let n: number = <number>_ary[i]; let n: number = <number>_ary[i];
timeNum += n * Math.pow(60, (len - 1 - i)); timeNum += n * Math.pow(60, (len - 1 - i));
} }
timeNum *= 1000; timeNum *= 1000;
return timeNum.toString(); return timeNum.toString();
} }
}
} }
@@ -1,317 +0,0 @@
module es {
/**
*
* 使
* N倍
* Faster dictionary在大部分操作上也比标准字典快
* 使
*/
export class FasterDictionary<TKey, TValue> {
public _values: TValue[];
public _valuesInfo: FastNode[];
public _buckets: number[];
public _freeValueCellIndex: number = 0;
public _collisions: number = 0;
constructor(size: number = 1) {
this._valuesInfo = new Array(size);
this._values = new Array(size);
this._buckets = new Array(HashHelpers.getPrime(size));
}
public getValuesArray(count: {value: number}): TValue[] {
count.value = this._freeValueCellIndex;
return this._values;
}
public get valuesArray(): TValue[] {
return this._values;
}
public get count(): number {
return this._freeValueCellIndex;
}
public add(key: TKey, value: TValue) {
if (!this.addValue(key, value, {value: 0}))
throw new Error("key 已经存在")
}
public addValue(key: TKey, value: TValue, indexSet: {value: number}) {
let hash = HashHelpers.getHashCode(key);
let bucketIndex = FasterDictionary.reduce(hash, this._buckets.length);
if (this._freeValueCellIndex == this._values.length) {
let expandPrime = HashHelpers.expandPrime(this._freeValueCellIndex);
this._values.length = expandPrime;
this._valuesInfo.length = expandPrime;
}
// buckets值-1表示它是空的
let valueIndex = NumberExtension.toNumber(this._buckets[bucketIndex]) - 1;
if (valueIndex == -1) {
// 在最后一个位置创建信息节点,并填入相关信息
this._valuesInfo[this._freeValueCellIndex] = new FastNode(key, hash);
} else {
{
let currentValueIndex = valueIndex;
do {
// 必须检查键是否已经存在于字典中
if (this._valuesInfo[currentValueIndex].hashcode == hash &&
this._valuesInfo[currentValueIndex].key == key) {
// 键已经存在,只需将其值替换掉即可
this._values[currentValueIndex] = value;
indexSet.value = currentValueIndex;
return false;
}
currentValueIndex = this._valuesInfo[currentValueIndex].previous;
}
while (currentValueIndex != -1); // -1表示没有更多的值与相同的哈希值的键
}
this._collisions++;
// 创建一个新的节点,该节点之前的索引指向当前指向桶的节点
this._valuesInfo[this._freeValueCellIndex] = new FastNode(key, hash, valueIndex);
// 更新现有单元格的下一个单元格指向新的单元格,旧的单元格 -> 新的单元格 -> 旧的单元格 <- 下一个单元格
this._valuesInfo[valueIndex].next = this._freeValueCellIndex;
}
// 重要的是:新的节点总是被桶单元格指向的那个节点,所以我可以假设被桶指向的那个节点总是最后添加的值(next = -1)
// item与这个bucketIndex将指向最后创建的值
// TODO: 如果相反,我假设原来的那个是bucket中的那个,我就不需要在这里更新bucket了
this._buckets[bucketIndex] = (this._freeValueCellIndex + 1);
this._values[this._freeValueCellIndex] = value;
indexSet.value = this._freeValueCellIndex;
this._freeValueCellIndex++;
if (this._collisions > this._buckets.length) {
// 我们需要更多的空间和更少的碰撞
this._buckets = new Array(HashHelpers.expandPrime(this._collisions));
this._collisions = 0;
// 我们需要得到目前存储的所有值的哈希码,并将它们分布在新的桶长上
for (let newValueIndex = 0; newValueIndex < this._freeValueCellIndex; newValueIndex++) {
// 获取原始哈希码,并根据新的长度找到新的bucketIndex
bucketIndex = FasterDictionary.reduce(this._valuesInfo[newValueIndex].hashcode, this._buckets.length);
// bucketsIndex可以是-1或下一个值。
// 如果是-1意味着没有碰撞。
// 如果有碰撞,我们创建一个新节点,它的上一个指向旧节点。
// 旧节点指向新节点,新节点指向旧节点,旧节点指向新节点,现在bucket指向新节点,这样我们就可以重建linkedlist.
// 获取当前值Index,如果没有碰撞,则为-1。
let existingValueIndex = NumberExtension.toNumber(this._buckets[bucketIndex]) - 1;
// 将bucket索引更新为共享bucketIndex的当前项目的索引(最后找到的总是bucket中的那个)
this._buckets[bucketIndex] = newValueIndex + 1;
if (existingValueIndex != -1) {
// 这个单元格已经指向了新的bucket list中的一个值,这意味着有一个碰撞,出了问题
this._collisions++;
// bucket将指向这个值,所以新的值将使用以前的索引
this._valuesInfo[newValueIndex].previous = existingValueIndex;
this._valuesInfo[newValueIndex].next = -1;
// 并将之前的下一个索引更新为新的索引
this._valuesInfo[existingValueIndex].next = newValueIndex;
} else {
// 什么都没有被索引,桶是空的。我们需要更新之前的 next 和 previous 的值。
this._valuesInfo[newValueIndex].next = -1;
this._valuesInfo[newValueIndex].previous = -1;
}
}
}
return true;
}
public remove(key: TKey): boolean {
let hash = FasterDictionary.hash(key);
let bucketIndex = FasterDictionary.reduce(hash, this._buckets.length);
// 找桶
let indexToValueToRemove = NumberExtension.toNumber(this._buckets[bucketIndex]) - 1;
// 第一部分:在bucket list中寻找实际的键,如果找到了,我就更新bucket list,使它不再指向要删除的单元格。
while (indexToValueToRemove != -1) {
if (this._valuesInfo[indexToValueToRemove].hashcode == hash &&
this._valuesInfo[indexToValueToRemove].key == key) {
// 如果找到了密钥,并且桶直接指向了要删除的节点
if (this._buckets[bucketIndex] - 1 == indexToValueToRemove){
if (this._valuesInfo[indexToValueToRemove].next != -1)
throw new Error("如果 bucket 指向单元格,那么 next 必须不存在。");
// 如果前一个单元格存在,它的下一个指针必须被更新!
//<---迭代顺序
// B(ucket总是指向最后一个)
// ------- ------- -------
// 1 | | | | 2 | | | 3 | //bucket不能有下一个,只能有上一个。
// ------- ------- -------
//--> 插入
let value = this._valuesInfo[indexToValueToRemove].previous;
this._buckets[bucketIndex] = value + 1;
}else{
if (this._valuesInfo[indexToValueToRemove].next == -1)
throw new Error("如果 bucket 指向另一个单元格,则 NEXT 必须存在");
}
FasterDictionary.updateLinkedList(indexToValueToRemove, this._valuesInfo);
break;
}
indexToValueToRemove = this._valuesInfo[indexToValueToRemove].previous;
}
if (indexToValueToRemove == -1)
return false; // 未找到
this._freeValueCellIndex --; // 少了一个需要反复计算的值
// 第二部分
// 这时节点指针和水桶会被更新,但_values数组会被更新仍然有要删除的值
// 这个字典的目标是能够做到像数组一样对数值进行迭代,所以数值数组必须始终是最新的
// 如果要删除的单元格是列表中的最后一个,我们可以执行较少的操作(不需要交换),否则我们要将最后一个值的单元格移到要删除的值上。
if (indexToValueToRemove != this._freeValueCellIndex){
// 我们可以将两个数组的最后一个值移到要删除的数组中。
// 为了做到这一点,我们需要确保 bucket 指针已经更新了
// 首先我们在桶列表中找到指向要移动的单元格的指针的索引
let movingBucketIndex = FasterDictionary.reduce(this._valuesInfo[this._freeValueCellIndex].hashcode, this._buckets.length);
// 如果找到了键,并且桶直接指向要删除的节点,现在必须指向要移动的单元格。
if (this._buckets[movingBucketIndex] - 1 == this._freeValueCellIndex)
this._buckets[movingBucketIndex] = (indexToValueToRemove + 1);
// 否则意味着有多个键具有相同的哈希值(碰撞),所以我们需要更新链接列表和它的指针
let next = this._valuesInfo[this._freeValueCellIndex].next;
let previous = this._valuesInfo[this._freeValueCellIndex].previous;
// 现在它们指向最后一个值被移入的单元格
if (next != -1)
this._valuesInfo[next].previous = indexToValueToRemove;
if (previous != -1)
this._valuesInfo[previous].next = indexToValueToRemove;
// 最后,实际上是移动值
this._valuesInfo[indexToValueToRemove] = this._valuesInfo[this._freeValueCellIndex];
this._values[indexToValueToRemove] = this._values[this._freeValueCellIndex];
}
return true;
}
public trim(){
let expandPrime = HashHelpers.expandPrime(this._freeValueCellIndex);
if (expandPrime < this._valuesInfo.length){
this._values.length = expandPrime;
this._valuesInfo.length = expandPrime;
}
}
public clear(){
if (this._freeValueCellIndex == 0) return;
this._freeValueCellIndex = 0;
this._buckets.length = 0;
this._values.length = 0;
this._valuesInfo.length = 0;
}
public fastClear(){
if (this._freeValueCellIndex == 0) return;
this._freeValueCellIndex = 0;
this._buckets.length = 0;
this._valuesInfo.length = 0;
}
public containsKey(key: TKey){
if (this.tryFindIndex(key, {value: 0})){
return true;
}
return false;
}
public tryGetValue(key: TKey): TValue {
let findIndex = {value: 0};
if (this.tryFindIndex(key, findIndex)){
return this._values[findIndex.value];
}
return null;
}
public tryFindIndex(key: TKey, findIndex: {value: number}){
// 我把所有的索引都用偏移量+1来存储,这样在bucket list中0就意味着实际上不存在
// 当读取时,偏移量必须再偏移-1才是真实的
// 这样我就避免了将数组初始化为-1
let hash = FasterDictionary.hash(key);
let bucketIndex = FasterDictionary.reduce(hash, this._buckets.length);
let valueIndex = NumberExtension.toNumber(this._buckets[bucketIndex]) - 1;
// 即使我们找到了一个现有的值,我们也需要确定它是我们所要求的值
while (valueIndex != -1){
if (this._valuesInfo[valueIndex].hashcode == hash && this._valuesInfo[valueIndex].key == key){
findIndex.value = valueIndex;
return true;
}
valueIndex = this._valuesInfo[valueIndex].previous;
}
findIndex.value = 0;
return false;
}
public getDirectValue(index: number): TValue {
return this._values[index];
}
public getIndex(key: TKey): number {
let findIndex = {value: 0};
if (this.tryFindIndex(key, findIndex))
return findIndex.value;
throw new Error("未找到key");
}
public static updateLinkedList(index: number, valuesInfo: FastNode[]){
let next = valuesInfo[index].next;
let previous = valuesInfo[index].previous;
if (next != -1)
valuesInfo[next].previous = previous;
if (previous != -1)
valuesInfo[previous].next = next;
}
public static hash(key) {
return HashHelpers.getHashCode(key);
}
public static reduce(x: number, n: number) {
if (x >= n)
return x % n;
return x;
}
}
export class FastNode {
readonly key;
readonly hashcode: number;
previous: number;
next: number;
constructor(key, hash: number, previousNode: number = -1) {
this.key = key;
this.hashcode = hash;
this.previous = previousNode;
this.next = -1;
}
}
}