优化实体列表add/remove效率。性能大幅度提高

This commit is contained in:
yhh
2021-04-16 17:48:13 +08:00
parent 5a6d1c72fe
commit 17b36f01b0
14 changed files with 1494 additions and 211 deletions

View File

@@ -203,6 +203,17 @@ declare module es {
setUpdateOrder(updateOrder: number): this;
}
}
declare module es {
class ComponentType {
static INDEX: number;
private index_;
private type_;
constructor(type: Class, index?: number);
getName(): string;
getIndex(): number;
toString(): string;
}
}
declare module es {
enum CoreEvents {
/**
@@ -250,6 +261,7 @@ declare module es {
* 返回一个BitSet实例包含实体拥有的组件的位
*/
componentBits: BitSet;
private systemBits_;
constructor(name: string);
_isDestroyed: boolean;
/**
@@ -283,6 +295,7 @@ declare module es {
* @param value
*/
updateOrder: number;
getSystemBits(): BitSet;
parent: Transform;
readonly childCount: number;
position: Vector2;
@@ -562,16 +575,6 @@ declare module es {
}
}
declare module es {
enum SceneResolutionPolicy {
/**
* 默认情况下RenderTarget与屏幕大小匹配。RenderTarget与屏幕大小相匹配
*/
none = 0,
/**
* 该应用程序采用最适合设计分辨率的宽度和高度
*/
bestFit = 1
}
/** 场景 */
class Scene {
/**
@@ -652,11 +655,6 @@ declare module es {
* @returns
*/
findEntityWithTag(tag: number): Entity;
/**
* 返回类型为T的所有实体
* @param type
*/
entitiesOfType<T extends Entity>(type: any): T[];
/**
* 返回第一个启用加载的类型为T的组件
* @param type
@@ -1290,11 +1288,49 @@ declare module es {
}
}
declare module es {
interface Map<K, V> {
clear(): void;
containsKey(key: any): boolean;
containsValue(value: any): boolean;
get(key: any): V;
isEmpty(): boolean;
put(key: any, value: any): void;
remove(key: any): V;
size(): number;
values(): V[];
}
class HashMap<K, V> implements Map<K, V> {
private map_;
private keys_;
constructor();
clear(): void;
values(): V[];
contains(value: any): boolean;
containsKey(key: any): boolean;
containsValue(value: any): boolean;
get(key: K): V;
isEmpty(): boolean;
keys(): K[];
/**
* if key is a string, use as is, else use key.id_ or key.name
*/
put(key: any, value: any): void;
remove(key: any): V;
size(): number;
}
}
declare module es {
class SystemIndexManager {
static INDEX: number;
private static indices;
static getIndexFor(es: Class): number;
}
/**
* 追踪实体的子集,但不实现任何排序或迭代。
*/
abstract class EntitySystem {
private _entities;
private systemIndex_;
constructor(matcher?: Matcher);
private _scene;
/**
@@ -1745,11 +1781,15 @@ declare module es {
/**
* 本帧添加的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/
_entitiesToAdded: HashSet<Entity>;
_entitiesToAdded: {
[index: number]: Entity;
};
/**
* 本帧被标记为删除的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/
_entitiesToRemove: HashSet<Entity>;
_entitiesToRemove: {
[index: number]: Entity;
};
/**
* 标志,用于确定我们是否需要在这一帧中对实体进行排序
*/
@@ -1805,12 +1845,6 @@ declare module es {
* @returns
*/
entityWithTag(tag: number): Entity;
/**
* 返回一个T类型的所有实体的列表。
* 返回的List可以通过ListPool.free放回池中。
* @param type
*/
entitiesOfType<T extends Entity>(type: any): T[];
/**
* 返回在场景中找到的第一个T类型的组件。
* @param type
@@ -3577,6 +3611,16 @@ declare module es {
private initialize;
}
}
declare module es {
class UUID {
static randomUUID(): string;
}
}
declare module es {
interface Class extends Function {
}
function getClassName(klass: any): string;
}
declare namespace es {
/**
* 记录时间的持续时间,一些设计灵感来自物理秒表。
@@ -3690,6 +3734,31 @@ declare namespace es {
readonly duration: number;
}
}
declare module es {
class Bag<E> implements ImmutableBag<E> {
size_: number;
length: number;
private array;
constructor(capacity?: number);
removeAt(index: number): E;
remove(e: E): boolean;
removeLast(): E;
contains(e: E): boolean;
removeAll(bag: ImmutableBag<E>): boolean;
get(index: number): E;
safeGet(index: number): E;
size(): number;
getCapacity(): number;
isIndexWithinBounds(index: number): boolean;
isEmpty(): boolean;
add(e: E): void;
set(index: number, e: E): void;
grow(newCapacity?: number): void;
ensureCapacity(index: number): void;
clear(): void;
addAll(items: ImmutableBag<E>): void;
}
}
declare module es {
/**
* 创建这个字典的原因只有一个:
@@ -3737,6 +3806,14 @@ declare module es {
constructor(key: any, hash: number, previousNode?: number);
}
}
declare module es {
interface ImmutableBag<E> {
get(index: number): E;
size(): number;
isEmpty(): boolean;
contains(e: E): boolean;
}
}
declare module es {
class Node<T> {
element: T;

View File

@@ -543,6 +543,33 @@ var es;
es.Component = Component;
})(es || (es = {}));
var es;
(function (es) {
var ComponentType = /** @class */ (function () {
function ComponentType(type, index) {
this.index_ = 0;
if (index !== undefined) {
this.index_ = ComponentType.INDEX++;
}
else {
this.index_ = index;
}
this.type_ = type;
}
ComponentType.prototype.getName = function () {
return es.getClassName(this.type_);
};
ComponentType.prototype.getIndex = function () {
return this.index_;
};
ComponentType.prototype.toString = function () {
return "ComponentType[" + es.getClassName(ComponentType) + "] (" + this.index_ + ")";
};
ComponentType.INDEX = 0;
return ComponentType;
}());
es.ComponentType = ComponentType;
})(es || (es = {}));
var es;
(function (es) {
var CoreEvents;
(function (CoreEvents) {
@@ -583,6 +610,7 @@ var es;
this.transform = new es.Transform(this);
this.name = name;
this.id = Entity._idGenerator++;
this.systemBits_ = new es.BitSet();
this.componentBits = new es.BitSet();
}
Object.defineProperty(Entity.prototype, "isDestroyed", {
@@ -646,6 +674,9 @@ var es;
enumerable: true,
configurable: true
});
Entity.prototype.getSystemBits = function () {
return this.systemBits_;
};
Object.defineProperty(Entity.prototype, "parent", {
get: function () {
return this.transform.parent;
@@ -1300,17 +1331,6 @@ var es;
var es;
///<reference path="../Math/Vector2.ts" />
(function (es) {
var SceneResolutionPolicy;
(function (SceneResolutionPolicy) {
/**
* 默认情况下RenderTarget与屏幕大小匹配。RenderTarget与屏幕大小相匹配
*/
SceneResolutionPolicy[SceneResolutionPolicy["none"] = 0] = "none";
/**
* 该应用程序采用最适合设计分辨率的宽度和高度
*/
SceneResolutionPolicy[SceneResolutionPolicy["bestFit"] = 1] = "bestFit";
})(SceneResolutionPolicy = es.SceneResolutionPolicy || (es.SceneResolutionPolicy = {}));
/** 场景 */
var Scene = /** @class */ (function () {
function Scene() {
@@ -1463,13 +1483,6 @@ var es;
Scene.prototype.findEntityWithTag = function (tag) {
return this.entities.entityWithTag(tag);
};
/**
* 返回类型为T的所有实体
* @param type
*/
Scene.prototype.entitiesOfType = function (type) {
return this.entities.entitiesOfType(type);
};
/**
* 返回第一个启用加载的类型为T的组件
* @param type
@@ -2974,6 +2987,115 @@ var es;
})(es || (es = {}));
var es;
(function (es) {
function decode(key) {
switch (typeof key) {
case "boolean":
return "" + key;
case "number":
return "" + key;
case "string":
return "" + key;
case "function":
return es.getClassName(key);
default:
key.uuid = key.uuid ? key.uuid : es.UUID.randomUUID();
return key.uuid;
}
}
var HashMap = /** @class */ (function () {
function HashMap() {
this.clear();
}
HashMap.prototype.clear = function () {
this.map_ = {};
this.keys_ = {};
};
HashMap.prototype.values = function () {
var result = [];
var map = this.map_;
for (var key in map) {
result.push(map[key]);
}
return result;
};
HashMap.prototype.contains = function (value) {
var map = this.map_;
for (var key in map) {
if (value === map[key]) {
return true;
}
}
return false;
};
HashMap.prototype.containsKey = function (key) {
return decode(key) in this.map_;
};
HashMap.prototype.containsValue = function (value) {
var map = this.map_;
for (var key in map) {
if (value === map[key]) {
return true;
}
}
return false;
};
HashMap.prototype.get = function (key) {
return this.map_[decode(key)];
};
HashMap.prototype.isEmpty = function () {
return Object.keys(this.map_).length === 0;
};
HashMap.prototype.keys = function () {
var keys = this.map_;
var result = [];
for (var key in keys) {
result.push(keys[key]);
}
return result;
};
/**
* if key is a string, use as is, else use key.id_ or key.name
*/
HashMap.prototype.put = function (key, value) {
var k = decode(key);
this.map_[k] = value;
this.keys_[k] = key;
};
HashMap.prototype.remove = function (key) {
var map = this.map_;
var k = decode(key);
var value = map[k];
delete map[k];
delete this.keys_[k];
return value;
};
HashMap.prototype.size = function () {
return Object.keys(this.map_).length;
};
return HashMap;
}());
es.HashMap = HashMap;
})(es || (es = {}));
///<reference path="../../Utils/Collections/HashMap.ts"/>
var es;
///<reference path="../../Utils/Collections/HashMap.ts"/>
(function (es_1) {
var SystemIndexManager = /** @class */ (function () {
function SystemIndexManager() {
}
SystemIndexManager.getIndexFor = function (es) {
var index = SystemIndexManager.indices.get(es);
if (index === undefined) {
index = SystemIndexManager.INDEX++;
SystemIndexManager.indices.put(es, index);
}
return index;
};
SystemIndexManager.INDEX = 0;
SystemIndexManager.indices = new es_1.HashMap();
return SystemIndexManager;
}());
es_1.SystemIndexManager = SystemIndexManager;
/**
* 追踪实体的子集,但不实现任何排序或迭代。
*/
@@ -2983,7 +3105,8 @@ var es;
this._startTime = 0;
this._endTime = 0;
this._useTime = 0;
this._matcher = matcher ? matcher : es.Matcher.empty();
this._matcher = matcher ? matcher : es_1.Matcher.empty();
this.systemIndex_ = SystemIndexManager.getIndexFor(this.constructor);
this.initialize();
}
Object.defineProperty(EntitySystem.prototype, "scene", {
@@ -3018,7 +3141,7 @@ var es;
EntitySystem.prototype.initialize = function () {
};
EntitySystem.prototype.onChanged = function (entity) {
var contains = new es.List(this._entities).contains(entity);
var contains = entity.getSystemBits().get(this.systemIndex_);
var interest = this._matcher.isInterestedEntity(entity);
if (interest && !contains)
this.add(entity);
@@ -3027,11 +3150,13 @@ var es;
};
EntitySystem.prototype.add = function (entity) {
this._entities.push(entity);
entity.getSystemBits().set(this.systemIndex_);
this.onAdded(entity);
};
EntitySystem.prototype.onAdded = function (entity) { };
EntitySystem.prototype.remove = function (entity) {
new es.List(this._entities).remove(entity);
entity.getSystemBits().clear(this.systemIndex_);
this.onRemoved(entity);
};
EntitySystem.prototype.onRemoved = function (entity) { };
@@ -3052,7 +3177,7 @@ var es;
* 在下一个系统开始处理或新的处理回合开始之前(以先到者为准),使用此方法创建的任何实体都不会激活
*/
EntitySystem.prototype.begin = function () {
if (!es.Core.Instance.debug)
if (!es_1.Core.Instance.debug)
return;
this._startTime = Date.now();
};
@@ -3062,7 +3187,7 @@ var es;
* 系统处理完毕后调用
*/
EntitySystem.prototype.end = function () {
if (!es.Core.Instance.debug)
if (!es_1.Core.Instance.debug)
return;
this._endTime = Date.now();
this._useTime = this._endTime - this._startTime;
@@ -3079,7 +3204,7 @@ var es;
};
return EntitySystem;
}());
es.EntitySystem = EntitySystem;
es_1.EntitySystem = EntitySystem;
})(es || (es = {}));
///<reference path="./EntitySystem.ts"/>
var es;
@@ -4026,10 +4151,10 @@ var es;
}
this._tempBufferList.length = 0;
}
if (this._isComponentListUnsorted) {
this._updatableComponents.sort(ComponentList.compareUpdatableOrder.compare);
this._isComponentListUnsorted = false;
}
// if (this._isComponentListUnsorted) {
// this._updatableComponents.sort(ComponentList.compareUpdatableOrder.compare);
// this._isComponentListUnsorted = false;
// }
};
ComponentList.prototype.handleRemove = function (component) {
if (es.isIUpdatable(component))
@@ -4192,11 +4317,12 @@ var es;
/**
* 本帧添加的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/
this._entitiesToAdded = new es.HashSet();
// public _entitiesToAdded: Entity[] = [];
this._entitiesToAdded = {};
/**
* 本帧被标记为删除的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/
this._entitiesToRemove = new es.HashSet();
this._entitiesToRemove = {};
/**
* 通过标签跟踪实体,便于检索
*/
@@ -4229,28 +4355,27 @@ var es;
* @param entity
*/
EntityList.prototype.add = function (entity) {
this._entitiesToAdded.add(entity);
this._entitiesToAdded[entity.id] = entity;
};
/**
* 从列表中删除一个实体。所有的生命周期方法将在下一帧中被调用
* @param entity
*/
EntityList.prototype.remove = function (entity) {
es.Debug.warnIf(this._entitiesToRemove.contains(entity), "\u60A8\u6B63\u5728\u5C1D\u8BD5\u5220\u9664\u5DF2\u7ECF\u5220\u9664\u7684\u5B9E\u4F53(" + entity.name + ")");
// 防止在同一帧中添加或删除实体
if (this._entitiesToAdded.contains(entity)) {
this._entitiesToAdded.remove(entity);
if (this._entitiesToAdded[entity.id]) {
delete this._entitiesToAdded[entity.id];
return;
}
if (!this._entitiesToRemove.contains(entity))
this._entitiesToRemove.add(entity);
if (!this._entitiesToRemove[entity.id])
this._entitiesToRemove[entity.id] = entity;
};
/**
* 从实体列表中删除所有实体
*/
EntityList.prototype.removeAllEntities = function () {
this._unsortedTags.clear();
this._entitiesToAdded.clear();
this._entitiesToAdded = {};
this._isEntityListUnsorted = false;
// 为什么我们要在这里更新列表?主要是为了处理在场景切换前被分离的实体。
// 它们仍然会在_entitiesToRemove列表中这将由updateLists处理。
@@ -4268,7 +4393,7 @@ var es;
* @param entity
*/
EntityList.prototype.contains = function (entity) {
return new es.List(this._entities).contains(entity) || this._entitiesToAdded.contains(entity);
return !!this._entitiesToAdded[entity.id];
};
EntityList.prototype.getTagList = function (tag) {
var list = this._entityDict.get(tag);
@@ -4305,36 +4430,32 @@ var es;
}
};
EntityList.prototype.updateLists = function () {
var _this = this;
if (this._entitiesToRemove.getCount() > 0) {
this._entitiesToRemove.toArray().forEach(function (entity) {
// 处理标签列表
_this.removeFromTagList(entity);
// 处理常规实体列表
new es.List(_this._entities).remove(entity);
entity.onRemovedFromScene();
entity.scene = null;
_this.scene.entityProcessors.onEntityRemoved(entity);
});
this._entitiesToRemove.clear();
for (var i in this._entitiesToRemove) {
var entity = this._entitiesToRemove[i];
this.removeFromTagList(entity);
// 处理常规实体列表
new es.List(this._entities).remove(entity);
entity.onRemovedFromScene();
entity.scene = null;
this.scene.entityProcessors.onEntityRemoved(entity);
}
if (this._entitiesToAdded.getCount() > 0) {
this._entitiesToAdded.toArray().forEach(function (entity) {
_this._entities.push(entity);
entity.scene = _this.scene;
_this.addToTagList(entity);
_this.scene.entityProcessors.onEntityAdded(entity);
});
this._entitiesToAdded.toArray().forEach(function (entity) {
entity.onAddedToScene();
});
this._entitiesToAdded.clear();
this._isEntityListUnsorted = true;
this._entitiesToRemove = {};
for (var i in this._entitiesToAdded) {
var entity = this._entitiesToAdded[i];
this._entities.push(entity);
entity.scene = this.scene;
this.addToTagList(entity);
this.scene.entityProcessors.onEntityAdded(entity);
}
if (this._isEntityListUnsorted) {
this._entities.sort(es.Entity.entityComparer.compare);
this._isEntityListUnsorted = false;
for (var i in this._entitiesToAdded) {
this._entitiesToAdded[i].onAddedToScene();
}
this._entitiesToAdded = {};
// this._isEntityListUnsorted = true;
// if (this._isEntityListUnsorted) {
// this._entities.sort(Entity.entityComparer.compare);
// this._isEntityListUnsorted = false;
// }
};
/**
* 返回第一个找到的名字为name的实体。如果没有找到则返回null
@@ -4345,8 +4466,13 @@ var es;
if (this._entities[i].name == name)
return this._entities[i];
}
for (var i = 0; i < this._entitiesToAdded.getCount(); i++) {
var entity = this._entitiesToAdded.toArray()[i];
// for (let i = 0; i < this._entitiesToAdded.size; i++) {
// let entity = this._entitiesToAdded.values;
// if (entity.name == name)
// return entity;
// }
for (var i in this._entitiesToAdded) {
var entity = this._entitiesToAdded[i];
if (entity.name == name)
return entity;
}
@@ -4399,25 +4525,6 @@ var es;
}
return null;
};
/**
* 返回一个T类型的所有实体的列表。
* 返回的List可以通过ListPool.free放回池中。
* @param type
*/
EntityList.prototype.entitiesOfType = function (type) {
var list = es.ListPool.obtain();
for (var i = 0; i < this._entities.length; i++) {
if (this._entities[i] instanceof type)
list.push(this._entities[i]);
}
for (var i = 0; i < this._entitiesToAdded.getCount(); i++) {
var entity = this._entitiesToAdded.toArray()[i];
if (es.TypeUtils.getType(entity) instanceof type) {
list.push(entity);
}
}
return list;
};
/**
* 返回在场景中找到的第一个T类型的组件。
* @param type
@@ -4430,8 +4537,16 @@ var es;
return comp;
}
}
for (var i = 0; i < this._entitiesToAdded.getCount(); i++) {
var entity = this._entitiesToAdded.toArray()[i];
// for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
// let entity: Entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled) {
// let comp = entity.getComponent<T>(type);
// if (comp)
// return comp;
// }
// }
for (var i in this._entitiesToAdded) {
var entity = this._entitiesToAdded[i];
if (entity.enabled) {
var comp = entity.getComponent(type);
if (comp)
@@ -4451,8 +4566,13 @@ var es;
if (this._entities[i].enabled)
this._entities[i].getComponents(type, comps);
}
for (var i = 0; i < this._entitiesToAdded.getCount(); i++) {
var entity = this._entitiesToAdded.toArray()[i];
// for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
// let entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled)
// entity.getComponents(type, comps);
// }
for (var i in this._entitiesToAdded) {
var entity = this._entitiesToAdded[i];
if (entity.enabled)
entity.getComponents(type, comps);
}
@@ -4495,8 +4615,24 @@ var es;
}
}
}
for (var i = 0; i < this._entitiesToAdded.getCount(); i++) {
var entity = this._entitiesToAdded.toArray()[i];
// for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
// let entity: Entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled) {
// let meet = true;
// for (let type of types) {
// let hasComp = entity.hasComponent(type);
// if (!hasComp) {
// meet = false;
// break;
// }
// }
// if (meet) {
// entities.push(entity);
// }
// }
// }
for (var i in this._entitiesToAdded) {
var entity = this._entitiesToAdded[i];
if (entity.enabled) {
var meet = true;
try {
@@ -8979,6 +9115,307 @@ var es;
es.Triangulator = Triangulator;
})(es || (es = {}));
var es;
(function (es) {
var hex = [
// hex identity values 0-255
"00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"0a",
"0b",
"0c",
"0d",
"0e",
"0f",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"1a",
"1b",
"1c",
"1d",
"1e",
"1f",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"2a",
"2b",
"2c",
"2d",
"2e",
"2f",
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"3a",
"3b",
"3c",
"3d",
"3e",
"3f",
"40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"4a",
"4b",
"4c",
"4d",
"4e",
"4f",
"50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"5a",
"5b",
"5c",
"5d",
"5e",
"5f",
"60",
"61",
"62",
"63",
"64",
"65",
"66",
"67",
"68",
"69",
"6a",
"6b",
"6c",
"6d",
"6e",
"6f",
"70",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"7a",
"7b",
"7c",
"7d",
"7e",
"7f",
"80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
"88",
"89",
"8a",
"8b",
"8c",
"8d",
"8e",
"8f",
"90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99",
"9a",
"9b",
"9c",
"9d",
"9e",
"9f",
"a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"a8",
"a9",
"aa",
"ab",
"ac",
"ad",
"ae",
"af",
"b0",
"b1",
"b2",
"b3",
"b4",
"b5",
"b6",
"b7",
"b8",
"b9",
"ba",
"bb",
"bc",
"bd",
"be",
"bf",
"c0",
"c1",
"c2",
"c3",
"c4",
"c5",
"c6",
"c7",
"c8",
"c9",
"ca",
"cb",
"cc",
"cd",
"ce",
"cf",
"d0",
"d1",
"d2",
"d3",
"d4",
"d5",
"d6",
"d7",
"d8",
"d9",
"da",
"db",
"dc",
"dd",
"de",
"df",
"e0",
"e1",
"e2",
"e3",
"e4",
"e5",
"e6",
"e7",
"e8",
"e9",
"ea",
"eb",
"ec",
"ed",
"ee",
"ef",
"f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"fa",
"fb",
"fc",
"fd",
"fe",
"ff",
];
var UUID = /** @class */ (function () {
function UUID() {
}
UUID.randomUUID = function () {
var d0 = (Math.random() * 0xffffffff) | 0;
var d1 = (Math.random() * 0xffffffff) | 0;
var d2 = (Math.random() * 0xffffffff) | 0;
var d3 = (Math.random() * 0xffffffff) | 0;
return (hex[d0 & 0xff] +
hex[(d0 >> 8) & 0xff] +
hex[(d0 >> 16) & 0xff] +
hex[(d0 >> 24) & 0xff] +
"-" +
hex[d1 & 0xff] +
hex[(d1 >> 8) & 0xff] +
"-" +
hex[((d1 >> 16) & 0x0f) | 0x40] +
hex[(d1 >> 24) & 0xff] +
"-" +
hex[(d2 & 0x3f) | 0x80] +
hex[(d2 >> 8) & 0xff] +
"-" +
hex[(d2 >> 16) & 0xff] +
hex[(d2 >> 24) & 0xff] +
hex[d3 & 0xff] +
hex[(d3 >> 8) & 0xff] +
hex[(d3 >> 16) & 0xff] +
hex[(d3 >> 24) & 0xff]);
};
return UUID;
}());
es.UUID = UUID;
})(es || (es = {}));
var es;
(function (es) {
function getClassName(klass) {
return klass.className || klass.name;
}
es.getClassName = getClassName;
})(es || (es = {}));
var es;
(function (es) {
/**
* 记录时间的持续时间,一些设计灵感来自物理秒表。
@@ -9163,6 +9600,139 @@ var es;
var _defaultSystemTimeGetter = Date.now;
})(es || (es = {}));
var es;
(function (es) {
var Bag = /** @class */ (function () {
function Bag(capacity) {
if (capacity === void 0) { capacity = 64; }
this.size_ = 0;
this.length = 0;
this.array = [];
this.length = capacity;
}
Bag.prototype.removeAt = function (index) {
var e = this.array[index];
this.array[index] = this.array[--this.size_];
this.array[this.size_] = null;
return e;
};
Bag.prototype.remove = function (e) {
var i;
var e2;
var size = this.size_;
for (i = 0; i < size; i++) {
e2 = this.array[i];
if (e == e2) {
this.array[i] = this.array[--this.size_];
this.array[this.size_] = null;
return true;
}
}
return false;
};
Bag.prototype.removeLast = function () {
if (this.size_ > 0) {
var e = this.array[--this.size_];
this.array[this.size_] = null;
return e;
}
return null;
};
Bag.prototype.contains = function (e) {
var i;
var size;
for (i = 0, size = this.size_; size > i; i++) {
if (e === this.array[i]) {
return true;
}
}
return false;
};
Bag.prototype.removeAll = function (bag) {
var modified = false;
var i;
var j;
var l;
var e1;
var e2;
for (i = 0, l = bag.size(); i < l; i++) {
e1 = bag[i];
for (j = 0; j < this.size_; j++) {
e2 = this.array[j];
if (e1 === e2) {
this.removeAt(j);
j--;
modified = true;
break;
}
}
}
return modified;
};
Bag.prototype.get = function (index) {
if (index >= this.length) {
throw new Error("ArrayIndexOutOfBoundsException");
}
return this.array[index];
};
Bag.prototype.safeGet = function (index) {
if (index >= this.length) {
this.grow((index * 7) / 4 + 1);
}
return this.array[index];
};
Bag.prototype.size = function () {
return this.size_;
};
Bag.prototype.getCapacity = function () {
return this.length;
};
Bag.prototype.isIndexWithinBounds = function (index) {
return index < this.getCapacity();
};
Bag.prototype.isEmpty = function () {
return this.size_ == 0;
};
Bag.prototype.add = function (e) {
if (this.size_ === this.length) {
this.grow();
}
this.array[this.size_++] = e;
};
Bag.prototype.set = function (index, e) {
if (index >= this.length) {
this.grow(index * 2);
}
this.size_ = index + 1;
this.array[index] = e;
};
Bag.prototype.grow = function (newCapacity) {
if (newCapacity === void 0) { newCapacity = ~~((this.length * 3) / 2) + 1; }
this.length = ~~newCapacity;
};
Bag.prototype.ensureCapacity = function (index) {
if (index >= this.length) {
this.grow(index * 2);
}
};
Bag.prototype.clear = function () {
var i;
var size;
for (i = 0, size = this.size_; i < size; i++) {
this.array[i] = null;
}
this.size_ = 0;
};
Bag.prototype.addAll = function (items) {
var i;
for (i = 0; items.size() > i; i++) {
this.add(items.get(i));
}
};
return Bag;
}());
es.Bag = Bag;
})(es || (es = {}));
var es;
(function (es) {
/**
* 创建这个字典的原因只有一个:

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
module es {
export class ComponentType {
public static INDEX = 0;
private index_ = 0;
private type_: Class;
constructor(type: Class, index?: number) {
if (index !== undefined) {
this.index_ = ComponentType.INDEX++;
} else {
this.index_ = index;
}
this.type_ = type;
}
public getName(): string {
return getClassName(this.type_);
}
public getIndex(): number {
return this.index_;
}
public toString(): string {
return "ComponentType[" + getClassName(ComponentType) + "] (" + this.index_ + ")";
}
}
}

View File

@@ -39,6 +39,7 @@ module es {
* 返回一个BitSet实例包含实体拥有的组件的位
*/
public componentBits: BitSet;
private systemBits_: BitSet;
constructor(name: string) {
this.components = new ComponentList(this);
@@ -46,6 +47,7 @@ module es {
this.name = name;
this.id = Entity._idGenerator++;
this.systemBits_ = new BitSet();
this.componentBits = new BitSet();
}
@@ -109,6 +111,10 @@ module es {
this.setUpdateOrder(value);
}
public getSystemBits(): BitSet {
return this.systemBits_;
}
public get parent(): Transform {
return this.transform.parent;
}

View File

@@ -1,16 +1,5 @@
///<reference path="../Math/Vector2.ts" />
module es {
export enum SceneResolutionPolicy {
/**
* 默认情况下RenderTarget与屏幕大小匹配。RenderTarget与屏幕大小相匹配
*/
none,
/**
* 该应用程序采用最适合设计分辨率的宽度和高度
*/
bestFit
}
/** 场景 */
export class Scene {
/**
@@ -209,14 +198,6 @@ module es {
return this.entities.entityWithTag(tag);
}
/**
* 返回类型为T的所有实体
* @param type
*/
public entitiesOfType<T extends Entity>(type): T[] {
return this.entities.entitiesOfType<T>(type);
}
/**
* 返回第一个启用加载的类型为T的组件
* @param type

View File

@@ -1,12 +1,29 @@
///<reference path="../../Utils/Collections/HashMap.ts"/>
module es {
export class SystemIndexManager {
public static INDEX = 0;
private static indices: HashMap<Function, number> = new HashMap<Function, number>();
public static getIndexFor(es: Class): number {
let index: number = SystemIndexManager.indices.get(es);
if (index === undefined) {
index = SystemIndexManager.INDEX++;
SystemIndexManager.indices.put(es, index);
}
return index;
}
}
/**
* 追踪实体的子集,但不实现任何排序或迭代。
*/
export abstract class EntitySystem {
private _entities: Entity[] = [];
private systemIndex_: number;
constructor(matcher?: Matcher) {
this._matcher = matcher ? matcher : Matcher.empty();
this.systemIndex_ = SystemIndexManager.getIndexFor(this.constructor);
this.initialize();
}
@@ -43,7 +60,7 @@ module es {
}
public onChanged(entity: Entity) {
let contains = new es.List(this._entities).contains(entity);
let contains = entity.getSystemBits().get(this.systemIndex_);
let interest = this._matcher.isInterestedEntity(entity);
if (interest && !contains)
@@ -54,6 +71,7 @@ module es {
public add(entity: Entity) {
this._entities.push(entity);
entity.getSystemBits().set(this.systemIndex_);
this.onAdded(entity);
}
@@ -61,6 +79,7 @@ module es {
public remove(entity: Entity) {
new es.List(this._entities).remove(entity);
entity.getSystemBits().clear(this.systemIndex_);
this.onRemoved(entity);
}

View File

@@ -145,10 +145,10 @@ module es {
this._tempBufferList.length = 0;
}
if (this._isComponentListUnsorted) {
this._updatableComponents.sort(ComponentList.compareUpdatableOrder.compare);
this._isComponentListUnsorted = false;
}
// if (this._isComponentListUnsorted) {
// this._updatableComponents.sort(ComponentList.compareUpdatableOrder.compare);
// this._isComponentListUnsorted = false;
// }
}
public handleRemove(component: Component) {

View File

@@ -8,11 +8,12 @@ module es {
/**
* 本帧添加的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/
public _entitiesToAdded: HashSet<Entity> = new HashSet<Entity>();
// public _entitiesToAdded: Entity[] = [];
public _entitiesToAdded: {[index: number]: Entity} = {};
/**
* 本帧被标记为删除的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/
public _entitiesToRemove: HashSet<Entity> = new HashSet<Entity>();
public _entitiesToRemove: {[index: number]: Entity} = {};
/**
* 标志,用于确定我们是否需要在这一帧中对实体进行排序
*/
@@ -48,7 +49,7 @@ module es {
* @param entity
*/
public add(entity: Entity) {
this._entitiesToAdded.add(entity);
this._entitiesToAdded[entity.id] = entity;
}
/**
@@ -56,16 +57,14 @@ module es {
* @param entity
*/
public remove(entity: Entity) {
Debug.warnIf(this._entitiesToRemove.contains(entity), `您正在尝试删除已经删除的实体(${entity.name})`);
// 防止在同一帧中添加或删除实体
if (this._entitiesToAdded.contains(entity)) {
this._entitiesToAdded.remove(entity);
if (this._entitiesToAdded[entity.id]) {
delete this._entitiesToAdded[entity.id];
return;
}
if (!this._entitiesToRemove.contains(entity))
this._entitiesToRemove.add(entity);
if (!this._entitiesToRemove[entity.id])
this._entitiesToRemove[entity.id] = entity;
}
/**
@@ -73,7 +72,7 @@ module es {
*/
public removeAllEntities() {
this._unsortedTags.clear();
this._entitiesToAdded.clear();
this._entitiesToAdded = {};
this._isEntityListUnsorted = false;
// 为什么我们要在这里更新列表?主要是为了处理在场景切换前被分离的实体。
@@ -95,7 +94,7 @@ module es {
* @param entity
*/
public contains(entity: Entity): boolean {
return new es.List(this._entities).contains(entity) || this._entitiesToAdded.contains(entity);
return !!this._entitiesToAdded[entity.id];
}
public getTagList(tag: number) {
@@ -127,43 +126,40 @@ module es {
}
public updateLists() {
if (this._entitiesToRemove.getCount() > 0) {
this._entitiesToRemove.toArray().forEach(entity => {
// 处理标签列表
this.removeFromTagList(entity);
for (let i in this._entitiesToRemove) {
let entity = this._entitiesToRemove[i];
this.removeFromTagList(entity);
// 处理常规实体列表
new es.List(this._entities).remove(entity);
entity.onRemovedFromScene();
entity.scene = null;
// 处理常规实体列表
new es.List(this._entities).remove(entity);
entity.onRemovedFromScene();
entity.scene = null;
this.scene.entityProcessors.onEntityRemoved(entity);
});
this._entitiesToRemove.clear();
this.scene.entityProcessors.onEntityRemoved(entity);
}
this._entitiesToRemove = {};
for (let i in this._entitiesToAdded) {
let entity = this._entitiesToAdded[i];
this._entities.push(entity);
entity.scene = this.scene;
this.addToTagList(entity);
this.scene.entityProcessors.onEntityAdded(entity);
}
if (this._entitiesToAdded.getCount() > 0) {
this._entitiesToAdded.toArray().forEach(entity => {
this._entities.push(entity);
entity.scene = this.scene;
this.addToTagList(entity);
this.scene.entityProcessors.onEntityAdded(entity);
});
this._entitiesToAdded.toArray().forEach(entity => {
entity.onAddedToScene();
})
this._entitiesToAdded.clear();
this._isEntityListUnsorted = true;
for (let i in this._entitiesToAdded) {
this._entitiesToAdded[i].onAddedToScene();
}
if (this._isEntityListUnsorted) {
this._entities.sort(Entity.entityComparer.compare);
this._isEntityListUnsorted = false;
}
this._entitiesToAdded = {};
// this._isEntityListUnsorted = true;
// if (this._isEntityListUnsorted) {
// this._entities.sort(Entity.entityComparer.compare);
// this._isEntityListUnsorted = false;
// }
}
/**
@@ -176,8 +172,13 @@ module es {
return this._entities[i];
}
for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
let entity = this._entitiesToAdded.toArray()[i];
// for (let i = 0; i < this._entitiesToAdded.size; i++) {
// let entity = this._entitiesToAdded.values;
// if (entity.name == name)
// return entity;
// }
for (let i in this._entitiesToAdded) {
let entity = this._entitiesToAdded[i];
if (entity.name == name)
return entity;
}
@@ -216,28 +217,6 @@ module es {
return null;
}
/**
* 返回一个T类型的所有实体的列表。
* 返回的List可以通过ListPool.free放回池中。
* @param type
*/
public entitiesOfType<T extends Entity>(type): T[] {
let list = ListPool.obtain<T>();
for (let i = 0; i < this._entities.length; i++) {
if (this._entities[i] instanceof type)
list.push(this._entities[i] as T);
}
for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
let entity = this._entitiesToAdded.toArray()[i];
if (TypeUtils.getType(entity) instanceof type) {
list.push(entity as T);
}
}
return list;
}
/**
* 返回在场景中找到的第一个T类型的组件。
* @param type
@@ -251,8 +230,17 @@ module es {
}
}
for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
let entity: Entity = this._entitiesToAdded.toArray()[i];
// for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
// let entity: Entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled) {
// let comp = entity.getComponent<T>(type);
// if (comp)
// return comp;
// }
// }
for (let i in this._entitiesToAdded) {
let entity = this._entitiesToAdded[i];
if (entity.enabled) {
let comp = entity.getComponent<T>(type);
if (comp)
@@ -275,8 +263,14 @@ module es {
this._entities[i].getComponents(type, comps);
}
for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
let entity = this._entitiesToAdded.toArray()[i];
// for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
// let entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled)
// entity.getComponents(type, comps);
// }
for (let i in this._entitiesToAdded) {
let entity = this._entitiesToAdded[i];
if (entity.enabled)
entity.getComponents(type, comps);
}
@@ -308,8 +302,26 @@ module es {
}
}
for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
let entity: Entity = this._entitiesToAdded.toArray()[i];
// for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
// let entity: Entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled) {
// let meet = true;
// for (let type of types) {
// let hasComp = entity.hasComponent(type);
// if (!hasComp) {
// meet = false;
// break;
// }
// }
// if (meet) {
// entities.push(entity);
// }
// }
// }
for (let i in this._entitiesToAdded) {
let entity = this._entitiesToAdded[i];
if (entity.enabled) {
let meet = true;
for (let type of types) {

View File

@@ -0,0 +1,158 @@
module es {
export class Bag<E> implements ImmutableBag<E> {
public size_ = 0;
public length = 0;
private array: Array<E> = [];
constructor(capacity = 64) {
this.length = capacity;
}
removeAt(index: number): E {
const e: E = this.array[index];
this.array[index] = this.array[--this.size_];
this.array[this.size_] = null;
return e;
}
remove(e: E): boolean {
let i: number;
let e2: E;
const size = this.size_;
for (i = 0; i < size; i++) {
e2 = this.array[i];
if (e == e2) {
this.array[i] = this.array[--this.size_];
this.array[this.size_] = null;
return true;
}
}
return false;
}
removeLast(): E {
if (this.size_ > 0) {
const e: E = this.array[--this.size_];
this.array[this.size_] = null;
return e;
}
return null;
}
contains(e: E): boolean {
let i: number;
let size: number;
for (i = 0, size = this.size_; size > i; i++) {
if (e === this.array[i]) {
return true;
}
}
return false;
}
removeAll(bag: ImmutableBag<E>): boolean {
let modified = false;
let i: number;
let j: number;
let l: number;
let e1: E;
let e2: E;
for (i = 0, l = bag.size(); i < l; i++) {
e1 = bag[i];
for (j = 0; j < this.size_; j++) {
e2 = this.array[j];
if (e1 === e2) {
this.removeAt(j);
j--;
modified = true;
break;
}
}
}
return modified;
}
get(index: number): E {
if (index >= this.length) {
throw new Error("ArrayIndexOutOfBoundsException");
}
return this.array[index];
}
safeGet(index: number): E {
if (index >= this.length) {
this.grow((index * 7) / 4 + 1);
}
return this.array[index];
}
size(): number {
return this.size_;
}
getCapacity(): number {
return this.length;
}
isIndexWithinBounds(index: number): boolean {
return index < this.getCapacity();
}
isEmpty(): boolean {
return this.size_ == 0;
}
add(e: E): void {
if (this.size_ === this.length) {
this.grow();
}
this.array[this.size_++] = e;
}
set(index: number, e: E): void {
if (index >= this.length) {
this.grow(index * 2);
}
this.size_ = index + 1;
this.array[index] = e;
}
grow(newCapacity: number = ~~((this.length * 3) / 2) + 1): void {
this.length = ~~newCapacity;
}
ensureCapacity(index: number): void {
if (index >= this.length) {
this.grow(index * 2);
}
}
clear(): void {
let i: number;
let size: number;
for (i = 0, size = this.size_; i < size; i++) {
this.array[i] = null;
}
this.size_ = 0;
}
addAll(items: ImmutableBag<E>): void {
let i: number;
for (i = 0; items.size() > i; i++) {
this.add(items.get(i));
}
}
}
}

View File

@@ -0,0 +1,119 @@
module es {
interface Map<K, V> {
clear(): void;
containsKey(key): boolean;
containsValue(value): boolean;
get(key): V;
isEmpty(): boolean;
put(key, value): void;
remove(key): V;
size(): number;
values(): V[];
}
function decode(key): string {
switch (typeof key) {
case "boolean":
return "" + key;
case "number":
return "" + key;
case "string":
return "" + key;
case "function":
return getClassName(key);
default:
key.uuid = key.uuid ? key.uuid : UUID.randomUUID();
return key.uuid;
}
}
export class HashMap<K, V> implements Map<K, V> {
private map_;
private keys_;
constructor() {
this.clear();
}
clear(): void {
this.map_ = {};
this.keys_ = {};
}
values(): V[] {
const result = [];
const map = this.map_;
for (const key in map) {
result.push(map[key]);
}
return result;
}
contains(value): boolean {
const map = this.map_;
for (const key in map) {
if (value === map[key]) {
return true;
}
}
return false;
}
containsKey(key): boolean {
return decode(key) in this.map_;
}
containsValue(value): boolean {
const map = this.map_;
for (const key in map) {
if (value === map[key]) {
return true;
}
}
return false;
}
get(key: K): V {
return this.map_[decode(key)];
}
isEmpty(): boolean {
return Object.keys(this.map_).length === 0;
}
keys(): K[] {
const keys = this.map_;
const result = [];
for (const key in keys) {
result.push(keys[key]);
}
return result;
}
/**
* if key is a string, use as is, else use key.id_ or key.name
*/
put(key, value): void {
const k = decode(key);
this.map_[k] = value;
this.keys_[k] = key;
}
remove(key): V {
const map = this.map_;
const k = decode(key);
const value = map[k];
delete map[k];
delete this.keys_[k];
return value;
}
size(): number {
return Object.keys(this.map_).length;
}
}
}

View File

@@ -0,0 +1,11 @@
module es {
export interface ImmutableBag<E> {
get(index: number): E;
size(): number;
isEmpty(): boolean;
contains(e: E): boolean;
}
}

293
source/src/Utils/UUID.ts Normal file
View File

@@ -0,0 +1,293 @@
module es {
const hex = [
// hex identity values 0-255
"00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"0a",
"0b",
"0c",
"0d",
"0e",
"0f",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"1a",
"1b",
"1c",
"1d",
"1e",
"1f",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"2a",
"2b",
"2c",
"2d",
"2e",
"2f",
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"3a",
"3b",
"3c",
"3d",
"3e",
"3f",
"40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"4a",
"4b",
"4c",
"4d",
"4e",
"4f",
"50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"5a",
"5b",
"5c",
"5d",
"5e",
"5f",
"60",
"61",
"62",
"63",
"64",
"65",
"66",
"67",
"68",
"69",
"6a",
"6b",
"6c",
"6d",
"6e",
"6f",
"70",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"7a",
"7b",
"7c",
"7d",
"7e",
"7f",
"80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
"88",
"89",
"8a",
"8b",
"8c",
"8d",
"8e",
"8f",
"90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99",
"9a",
"9b",
"9c",
"9d",
"9e",
"9f",
"a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"a8",
"a9",
"aa",
"ab",
"ac",
"ad",
"ae",
"af",
"b0",
"b1",
"b2",
"b3",
"b4",
"b5",
"b6",
"b7",
"b8",
"b9",
"ba",
"bb",
"bc",
"bd",
"be",
"bf",
"c0",
"c1",
"c2",
"c3",
"c4",
"c5",
"c6",
"c7",
"c8",
"c9",
"ca",
"cb",
"cc",
"cd",
"ce",
"cf",
"d0",
"d1",
"d2",
"d3",
"d4",
"d5",
"d6",
"d7",
"d8",
"d9",
"da",
"db",
"dc",
"dd",
"de",
"df",
"e0",
"e1",
"e2",
"e3",
"e4",
"e5",
"e6",
"e7",
"e8",
"e9",
"ea",
"eb",
"ec",
"ed",
"ee",
"ef",
"f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"fa",
"fb",
"fc",
"fd",
"fe",
"ff",
];
export class UUID {
static randomUUID(): string {
const d0 = (Math.random() * 0xffffffff) | 0;
const d1 = (Math.random() * 0xffffffff) | 0;
const d2 = (Math.random() * 0xffffffff) | 0;
const d3 = (Math.random() * 0xffffffff) | 0;
return (
hex[d0 & 0xff] +
hex[(d0 >> 8) & 0xff] +
hex[(d0 >> 16) & 0xff] +
hex[(d0 >> 24) & 0xff] +
"-" +
hex[d1 & 0xff] +
hex[(d1 >> 8) & 0xff] +
"-" +
hex[((d1 >> 16) & 0x0f) | 0x40] +
hex[(d1 >> 24) & 0xff] +
"-" +
hex[(d2 & 0x3f) | 0x80] +
hex[(d2 >> 8) & 0xff] +
"-" +
hex[(d2 >> 16) & 0xff] +
hex[(d2 >> 24) & 0xff] +
hex[d3 & 0xff] +
hex[(d3 >> 8) & 0xff] +
hex[(d3 >> 16) & 0xff] +
hex[(d3 >> 24) & 0xff]
);
}
}
}

View File

@@ -0,0 +1,7 @@
module es {
export interface Class extends Function {}
export function getClassName(klass): string {
return klass.className || klass.name;
}
}