移除Bitset更改为Bits
This commit is contained in:
@@ -35,20 +35,14 @@ module es {
|
||||
* 指定应该调用这个entity update方法的频率。1表示每一帧,2表示每一帧,以此类推
|
||||
*/
|
||||
public updateInterval: number = 1;
|
||||
/**
|
||||
* 返回一个BitSet实例,包含实体拥有的组件的位
|
||||
*/
|
||||
public componentBits: BitSet;
|
||||
private systemBits_: BitSet;
|
||||
public componentBits: Bits;
|
||||
|
||||
constructor(name: string) {
|
||||
this.components = new ComponentList(this);
|
||||
this.transform = new Transform(this);
|
||||
this.componentBits = new Bits();
|
||||
this.name = name;
|
||||
this.id = Entity._idGenerator++;
|
||||
|
||||
this.systemBits_ = new BitSet();
|
||||
this.componentBits = new BitSet();
|
||||
}
|
||||
|
||||
public _isDestroyed: boolean;
|
||||
@@ -111,10 +105,6 @@ module es {
|
||||
this.setUpdateOrder(value);
|
||||
}
|
||||
|
||||
public getSystemBits(): BitSet {
|
||||
return this.systemBits_;
|
||||
}
|
||||
|
||||
public get parent(): Transform {
|
||||
return this.transform.parent;
|
||||
}
|
||||
|
||||
@@ -1,29 +1,13 @@
|
||||
///<reference path="../../Utils/Collections/HashMap.ts"/>
|
||||
module es {
|
||||
export class SystemIndexManager {
|
||||
public static INDEX = 0;
|
||||
private static indices: Map<Function, number> = new Map<Function, number>();
|
||||
|
||||
public static getIndexFor(es: Class): number {
|
||||
let index: number = SystemIndexManager.indices.get(es);
|
||||
if (!index) {
|
||||
index = SystemIndexManager.INDEX++;
|
||||
SystemIndexManager.indices.set(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();
|
||||
}
|
||||
|
||||
@@ -60,7 +44,7 @@ module es {
|
||||
}
|
||||
|
||||
public onChanged(entity: Entity) {
|
||||
let contains = entity.getSystemBits().get(this.systemIndex_);
|
||||
let contains = !!this._entities.find(e => e.id == entity.id);
|
||||
let interest = this._matcher.isInterestedEntity(entity);
|
||||
|
||||
if (interest && !contains)
|
||||
@@ -70,8 +54,8 @@ module es {
|
||||
}
|
||||
|
||||
public add(entity: Entity) {
|
||||
this._entities.push(entity);
|
||||
entity.getSystemBits().set(this.systemIndex_);
|
||||
if (!this._entities.find(e => e.id == entity.id))
|
||||
this._entities.push(entity);
|
||||
this.onAdded(entity);
|
||||
}
|
||||
|
||||
@@ -79,7 +63,6 @@ module es {
|
||||
|
||||
public remove(entity: Entity) {
|
||||
new es.List(this._entities).remove(entity);
|
||||
entity.getSystemBits().clear(this.systemIndex_);
|
||||
this.onRemoved(entity);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
module es {
|
||||
/**
|
||||
* 这个类可以从两方面来考虑。你可以把它看成一个位向量或者一组非负整数。这个名字有点误导人。
|
||||
*
|
||||
* 它是由一个位向量实现的,但同样可以把它看成是一个非负整数的集合;集合中的每个整数由对应索引处的集合位表示。该结构的大小由集合中的最大整数决定。
|
||||
*/
|
||||
export class BitSet {
|
||||
private static ADDRESS_BITS_PER_WORD = 5;
|
||||
private static BITS_PER_WORD = 1 << BitSet.ADDRESS_BITS_PER_WORD; // 32
|
||||
private static WORD_MASK : number = 0xffffffff;
|
||||
private words_: number[];
|
||||
|
||||
constructor(nbits: number = 0) {
|
||||
this.words_ = [];
|
||||
}
|
||||
|
||||
public clear(bitIndex?: number) {
|
||||
if (bitIndex === null) {
|
||||
const words = this.words_;
|
||||
let wordsInUse = words.length;
|
||||
while (wordsInUse > 0) {
|
||||
words[--wordsInUse] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const wordIndex = bitIndex >> BitSet.ADDRESS_BITS_PER_WORD;
|
||||
this.words_[wordIndex] &= ~(1 << bitIndex);
|
||||
}
|
||||
|
||||
public get(bitIndex: number): boolean {
|
||||
const wordIndex = bitIndex >> BitSet.ADDRESS_BITS_PER_WORD;
|
||||
const words = this.words_;
|
||||
const wordsInUse = words.length;
|
||||
|
||||
return wordIndex < wordsInUse && (words[wordIndex] & (1 << bitIndex)) != 0;
|
||||
}
|
||||
|
||||
public intersects(set: BitSet) {
|
||||
const words = this.words_;
|
||||
const wordsInUse = words.length;
|
||||
|
||||
for (let i = Math.min(wordsInUse, set.words_.length) - 1; i >= 0; i--)
|
||||
if ((words[i] & set.words_[i]) != 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public isEmpty(): boolean {
|
||||
return this.words_.length === 0;
|
||||
}
|
||||
|
||||
public nextSetBit(fromIndex: number) {
|
||||
let u = fromIndex >> BitSet.ADDRESS_BITS_PER_WORD;
|
||||
const words = this.words_;
|
||||
const wordsInUse = words.length;
|
||||
|
||||
let word = words[u] & (BitSet.WORD_MASK << fromIndex);
|
||||
while (true) {
|
||||
if (word !== 0) return u * BitSet.BITS_PER_WORD + this.numberOfTrailingZeros(word);
|
||||
if (++u === wordsInUse) return -1;
|
||||
word = words[u];
|
||||
}
|
||||
}
|
||||
|
||||
private numberOfTrailingZeros(i: number): number {
|
||||
if (i == 0) return 64;
|
||||
let x: number = i;
|
||||
let y: number;
|
||||
let n = 63;
|
||||
y = x << 32;
|
||||
if (y != 0) {
|
||||
n -= 32;
|
||||
x = y;
|
||||
}
|
||||
y = x << 16;
|
||||
if (y != 0) {
|
||||
n -= 16;
|
||||
x = y;
|
||||
}
|
||||
y = x << 8;
|
||||
if (y != 0) {
|
||||
n -= 8;
|
||||
x = y;
|
||||
}
|
||||
y = x << 4;
|
||||
if (y != 0) {
|
||||
n -= 4;
|
||||
x = y;
|
||||
}
|
||||
y = x << 2;
|
||||
if (y != 0) {
|
||||
n -= 2;
|
||||
x = y;
|
||||
}
|
||||
return n - ((x << 1) >>> 63);
|
||||
}
|
||||
|
||||
public set(bitIndex: number, value: boolean = true) {
|
||||
const wordIndex = bitIndex >> BitSet.ADDRESS_BITS_PER_WORD;
|
||||
const words = this.words_;
|
||||
const wordsInUse = words.length;
|
||||
const wordsRequired = wordIndex + 1;
|
||||
|
||||
if (wordsInUse < wordsRequired) {
|
||||
words.length = Math.max(2 * wordsInUse, wordsRequired);
|
||||
for (let i = wordsInUse, l = words.length; i < l; i++) {
|
||||
words[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (value) {
|
||||
return (words[wordIndex] |= 1 << bitIndex);
|
||||
} else {
|
||||
return (words[wordIndex] &= ~(1 << bitIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,353 +0,0 @@
|
||||
module es {
|
||||
/**
|
||||
* 性能优化的位组实现。某些操作是以不安全为前缀的, 这些方法不执行验证,主要是在内部利用来优化实体ID位集的访问
|
||||
*/
|
||||
export class BitVector {
|
||||
private words: number[] = [0];
|
||||
|
||||
/**
|
||||
* 创建一个初始大小足够大的bitset,以明确表示0到nbits-1范围内指数的bit
|
||||
* @param nbits nbits 位集的初始大小
|
||||
*/
|
||||
constructor(nbits?: number | BitVector) {
|
||||
if (nbits) {
|
||||
if (typeof nbits == 'number')
|
||||
this.checkCapacity(nbits >>> 6);
|
||||
else {
|
||||
// 基于另一个位向量创建一个位集
|
||||
this.words = nbits.words.slice(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param index 位的索引
|
||||
* @returns 该位是否被设置
|
||||
*/
|
||||
public get(index: number): boolean {
|
||||
const word = index >>> 6;
|
||||
return word < this.words.length &&
|
||||
(this.words[word] & (1 << index)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param index 位的索引
|
||||
*/
|
||||
public set(index: number, value: boolean = true) {
|
||||
if (value) {
|
||||
const word = index >>> 6;
|
||||
this.checkCapacity(word);
|
||||
this.words[word] |= 1 << index;
|
||||
} else {
|
||||
this.clear(index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param index 位的索引
|
||||
* @returns 该位是否被设置
|
||||
*/
|
||||
public unsafeGet(index: number): boolean {
|
||||
return (this.words[index >>> 6] & (1 << index)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param index 要设置的位的索引
|
||||
*/
|
||||
public unsafeSet(index: number) {
|
||||
this.words[index >>> 6] |= 1 << index;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param index 要翻转的位的索引
|
||||
*/
|
||||
public flip(index: number) {
|
||||
const word = index >>> 6;
|
||||
this.checkCapacity(word);
|
||||
this.words[word] ^= 1 << index;
|
||||
}
|
||||
|
||||
/**
|
||||
* 要清除的位的索引
|
||||
* @param index
|
||||
*/
|
||||
public clear(index?: number) {
|
||||
if (index != null) {
|
||||
const word = index >>> 6;
|
||||
if (word >= this.words.length) return;
|
||||
this.words[word] &= ~(1 << index);
|
||||
} else {
|
||||
this.words.fill(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回该位组的 "逻辑大小":位组中最高设置位的索引加1。如果比特集不包含集合位,则返回0
|
||||
*/
|
||||
public length(): number {
|
||||
let bits = this.words.slice(0);
|
||||
for (let word = bits.length - 1; word >= 0; --word) {
|
||||
let bitsAtWord = bits[word];
|
||||
if (bitsAtWord != 0)
|
||||
return (word << 6) + 64 - this.numberOfLeadingZeros(bitsAtWord);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns 如果这个位组中没有设置为true的位,则为true
|
||||
*/
|
||||
public isEmpty(): boolean {
|
||||
let bits = this.words.slice(0);
|
||||
let length = bits.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (bits[i] != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回在指定的起始索引上或之后出现的第一个被设置为真的位的索引。
|
||||
* 如果不存在这样的位,则返回-1
|
||||
* @param fromIndex
|
||||
*/
|
||||
public nextSetBit(fromIndex: number): number {
|
||||
let word = fromIndex >>> 6;
|
||||
if (word >= this.words.length)
|
||||
return -1;
|
||||
|
||||
let bitmap = this.words[word] >>> fromIndex;
|
||||
if (bitmap != 0)
|
||||
return fromIndex + this.numberOfTrailingZeros(bitmap);
|
||||
|
||||
for (let i = 1 + word; i < this.words.length; i++) {
|
||||
bitmap = this.words[i];
|
||||
if (bitmap != 0) {
|
||||
return i * 64 + this.numberOfTrailingZeros(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回在指定的起始索引上或之后发生的第一个被设置为false的位的索引
|
||||
* @param fromIndex
|
||||
*/
|
||||
public nextClearBit(fromIndex: number): number {
|
||||
let word = fromIndex >>> 6;
|
||||
if (word >= this.words.length)
|
||||
return Math.min(fromIndex, this.words.length << 6);
|
||||
|
||||
let bitmap = ~(this.words[word] >>> fromIndex);
|
||||
if (bitmap != 0)
|
||||
return fromIndex + this.numberOfTrailingZeros(bitmap);
|
||||
|
||||
for (let i = 1 + word; i < this.words.length; i++) {
|
||||
bitmap = ~this.words[i];
|
||||
if (bitmap != 0) {
|
||||
return i * 64 + this.numberOfTrailingZeros(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
return Math.min(fromIndex, this.words.length << 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对这个目标位集和参数位集进行逻辑AND。
|
||||
* 这个位集被修改,使它的每一个位都有值为真,如果且仅当它最初的值为真,并且位集参数中的相应位也有值为真
|
||||
* @param other
|
||||
*/
|
||||
public and(other: BitVector) {
|
||||
let commonWords = Math.min(this.words.length, other.words.length);
|
||||
for (let i = 0; commonWords > i; i++) {
|
||||
this.words[i] &= other.words[i];
|
||||
}
|
||||
|
||||
if (this.words.length > commonWords) {
|
||||
for (let i = commonWords, s = this.words.length; s > i; i++) {
|
||||
this.words[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除该位集的所有位,其对应的位被设置在指定的位集中
|
||||
* @param other
|
||||
*/
|
||||
public andNot(other: BitVector) {
|
||||
let commonWords = Math.min(this.words.length, other.words.length);
|
||||
for (let i = 0; commonWords > i; i++)
|
||||
this.words[i] &= ~other.words[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* 用位集参数执行这个位集的逻辑OR。
|
||||
* 如果且仅当位集参数中的位已经有值为真或位集参数中的对应位有值为真时,该位集才会被修改,从而使位集中的位有值为真
|
||||
* @param other
|
||||
*/
|
||||
public or(other: BitVector) {
|
||||
let commonWords = Math.min(this.words.length, other.words.length);
|
||||
for (let i = 0; commonWords > i; i++)
|
||||
this.words[i] |= other.words[i];
|
||||
|
||||
if (commonWords < other.words.length) {
|
||||
this.checkCapacity(other.words.length);
|
||||
for (let i = commonWords, s = other.words.length; s > i; i++) {
|
||||
this.words[i] = other.words[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用位集参数对这个位集进行逻辑XOR。
|
||||
* 这个位集被修改了,所以如果且仅当以下语句之一成立时,位集中的一个位的值为真
|
||||
* @param other
|
||||
*/
|
||||
public xor(other: BitVector) {
|
||||
let commonWords = Math.min(this.words.length, other.words.length);
|
||||
|
||||
for (let i = 0; commonWords > i; i++)
|
||||
this.words[i] ^= other.words[i];
|
||||
|
||||
if (commonWords < other.words.length) {
|
||||
this.checkCapacity(other.words.length);
|
||||
for (let i = commonWords, s = other.words.length; s > i; i++) {
|
||||
this.words[i] = other.words[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果指定的BitVector有任何位被设置为true,并且在这个BitVector中也被设置为true,则返回true
|
||||
* @param other
|
||||
*/
|
||||
public intersects(other: BitVector): boolean {
|
||||
let bits = this.words.slice(0);
|
||||
let otherBits = other.words;
|
||||
for (let i = 0, s = Math.min(bits.length, otherBits.length); s > i; i++) {
|
||||
if ((bits[i] & otherBits[i]) != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果这个位集是指定位集的超级集,即它的所有位都被设置为真,那么返回true
|
||||
* @param other
|
||||
*/
|
||||
public containsAll(other: BitVector): boolean {
|
||||
let bits = this.words.slice(0);
|
||||
let otherBits = other.words;
|
||||
let otherBitsLength = otherBits.length;
|
||||
let bitsLength = bits.length;
|
||||
|
||||
|
||||
for (let i = bitsLength; i < otherBitsLength; i++) {
|
||||
if (otherBits[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0, s = Math.min(bitsLength, otherBitsLength); s > i; i++) {
|
||||
if ((bits[i] & otherBits[i]) != otherBits[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public cardinality() {
|
||||
let count = 0;
|
||||
for (let i = 0; i < this.words.length; i++)
|
||||
count += this.bitCount(this.words[i]);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public hashCode() {
|
||||
const word = this.length() >>> 6;
|
||||
let hash = 0;
|
||||
for (let i = 0; word >= i; i++)
|
||||
hash = 127 * hash + (this.words[i] ^ (this.words[i] >>> 32));
|
||||
return hash;
|
||||
}
|
||||
|
||||
private bitCount(i: number) {
|
||||
i = i - ((i >>> 1) & 0x55555555);
|
||||
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
|
||||
i = (i + (i >>> 4)) & 0x0f0f0f0f;
|
||||
i = i + (i >>> 8);
|
||||
i = i + (i >>> 16);
|
||||
return i & 0x3f;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回二进制补码二进制表示形式中最高位(“最左端”)一位之前的零位数量
|
||||
* @param i
|
||||
*/
|
||||
private numberOfLeadingZeros(i: number) {
|
||||
if (i == 0) return 64;
|
||||
let n = 1;
|
||||
let x = i >>> 32;
|
||||
if (x == 0) { n += 32; x = i; }
|
||||
if (x >>> 16 == 0) { n += 16; x <<= 16; }
|
||||
if (x >>> 24 == 0) { n += 8; x <<= 8; }
|
||||
if (x >>> 28 == 0) { n += 4; x <<= 4; }
|
||||
if (x >>> 30 == 0) { n += 2; x <<= 2; }
|
||||
n -= x >>> 31;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回指定二进制数的补码二进制表示形式中最低序(“最右”)一位之后的零位数量
|
||||
* @param i
|
||||
*/
|
||||
public numberOfTrailingZeros(i: number) {
|
||||
let x: number = 0, y: number = 0;
|
||||
if (i == 0) return 64;
|
||||
let n = 63;
|
||||
y = i; if (y != 0) { n = n - 32; x = y; } else x = (i >>> 32);
|
||||
y = x << 16; if (y != 0) { n = n - 16; x = y; }
|
||||
y = x << 8; if (y != 0) { n = n - 8; x = y; }
|
||||
y = x << 4; if (y != 0) { n = n - 4; x = y; }
|
||||
y = x << 2; if (y != 0) { n = n - 2; x = y; }
|
||||
return n - ((x << 1) >>> 31);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param index 要清除的位的索引
|
||||
*/
|
||||
public unsafeClear(index: number) {
|
||||
this.words[index >>> 6] &= ~(1 << index);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增长支持数组,使其能够容纳所请求的位
|
||||
* @param bits 位数
|
||||
*/
|
||||
public ensureCapacity(bits: number) {
|
||||
this.checkCapacity(bits >>> 6);
|
||||
}
|
||||
|
||||
private checkCapacity(len: number) {
|
||||
if (len >= this.words.length) {
|
||||
let newBits: number[] = new Array(len + 1);
|
||||
for (let i = 0; i < this.words.length; i++) {
|
||||
newBits[i] = this.words[i];
|
||||
}
|
||||
this.words = newBits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
source/src/ECS/Utils/Bits.ts
Normal file
14
source/src/ECS/Utils/Bits.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
module es {
|
||||
export class Bits {
|
||||
private _bit: {[index: number]: number} = {};
|
||||
|
||||
public set(index: number, value: number) {
|
||||
this._bit[index] = value;
|
||||
}
|
||||
|
||||
public get(index: number): number {
|
||||
let v = this._bit[index];
|
||||
return v == null ? 0 : v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,6 @@ module es {
|
||||
* 添加到实体的组件列表
|
||||
*/
|
||||
public _components: Component[] = [];
|
||||
/** 记录component的快速读取列表 */
|
||||
public fastComponentsMap = new Map<new (...args: any[]) => Component, es.Component[]>();
|
||||
public fastComponentsToAddMap = new Map<new (...args: any[]) => Component, es.Component[]>();
|
||||
/**
|
||||
* 所有需要更新的组件列表
|
||||
*/
|
||||
@@ -21,16 +18,18 @@ module es {
|
||||
/**
|
||||
* 添加到此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工
|
||||
*/
|
||||
public _componentsToAdd: {[index: number]: Component} = {};
|
||||
public _componentsToAdd: { [index: number]: Component } = {};
|
||||
/**
|
||||
* 标记要删除此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工
|
||||
*/
|
||||
public _componentsToRemove: {[index: number]: Component} = {};
|
||||
public _componentsToRemove: { [index: number]: Component } = {};
|
||||
public _tempBufferList: Component[] = [];
|
||||
/**
|
||||
* 用于确定是否需要对该框架中的组件进行排序的标志
|
||||
*/
|
||||
public _isComponentListUnsorted: boolean;
|
||||
private componentsByType = new Map<new (...args: any[]) => Component, es.Component[]>();
|
||||
private componentsToAddByType = new Map<new (...args: any[]) => Component, es.Component[]>();
|
||||
|
||||
constructor(entity: Entity) {
|
||||
this._entity = entity;
|
||||
@@ -50,16 +49,13 @@ module es {
|
||||
|
||||
public add(component: Component) {
|
||||
this._componentsToAdd[component.id] = component;
|
||||
this.addFastComponentToAdd(component);
|
||||
this.addComponentsToAddByType(component);
|
||||
}
|
||||
|
||||
public remove(component: Component) {
|
||||
Debug.warnIf(!!this._componentsToRemove[component.id], `您正在尝试删除一个您已经删除的组件(${component})`);
|
||||
//
|
||||
// 这可能不是一个活动的组件,所以我们必须注意它是否还没有被处理,它可能正在同一帧中被删除
|
||||
if (this._componentsToAdd[component.id]) {
|
||||
delete this._componentsToAdd[component.id];
|
||||
this.removeFastComponentToAdd(component);
|
||||
this.removeComponentsToAddByType(component);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,12 +70,12 @@ module es {
|
||||
this.handleRemove(this._components[i]);
|
||||
}
|
||||
|
||||
this.fastComponentsMap.clear();
|
||||
this.fastComponentsToAddMap.clear();
|
||||
this.componentsByType.clear();
|
||||
this.componentsToAddByType.clear();
|
||||
this._components.length = 0;
|
||||
this._updatableComponents.length = 0;
|
||||
this._componentsToAdd = {};
|
||||
this._componentsToRemove = {};
|
||||
this._componentsToRemove = {};
|
||||
}
|
||||
|
||||
public deregisterAllComponents() {
|
||||
@@ -90,7 +86,7 @@ module es {
|
||||
if (isIUpdatable(component))
|
||||
new es.List(this._updatableComponents).remove(component);
|
||||
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)), false);
|
||||
this.decreaseBits(component);
|
||||
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
||||
}
|
||||
}
|
||||
@@ -100,11 +96,23 @@ module es {
|
||||
if (isIUpdatable(component))
|
||||
this._updatableComponents.push(component);
|
||||
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)));
|
||||
this.addBits(component);
|
||||
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
||||
}
|
||||
}
|
||||
|
||||
private decreaseBits(component: Component) {
|
||||
let bits = this._entity.componentBits;
|
||||
let typeIndex = ComponentTypeManager.getIndexFor(TypeUtils.getType(component));
|
||||
bits.set(typeIndex, bits.get(typeIndex) - 1);
|
||||
}
|
||||
|
||||
private addBits(component: Component) {
|
||||
let bits = this._entity.componentBits;
|
||||
let typeIndex = ComponentTypeManager.getIndexFor(TypeUtils.getType(component));
|
||||
bits.set(typeIndex, bits.get(typeIndex) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理任何需要删除或添加的组件
|
||||
*/
|
||||
@@ -112,14 +120,14 @@ module es {
|
||||
for (let i in this._componentsToRemove) {
|
||||
let component = this._componentsToRemove[i];
|
||||
this.handleRemove(component);
|
||||
for (let index = 0; index < this._components.length; index ++) {
|
||||
for (let index = 0; index < this._components.length; index++) {
|
||||
let searchComponent = this._components[index];
|
||||
if (searchComponent.id == component.id) {
|
||||
this._components.splice(index, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.removeFastComponent(component);
|
||||
this.removeComponentsByType(component);
|
||||
}
|
||||
|
||||
this._componentsToRemove = {};
|
||||
@@ -130,72 +138,72 @@ module es {
|
||||
if (isIUpdatable(component))
|
||||
this._updatableComponents.push(component);
|
||||
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)));
|
||||
this.addBits(component);
|
||||
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
||||
this.addFastComponent(component);
|
||||
|
||||
this.addComponentsByType(component);
|
||||
this._components.push(component);
|
||||
this._tempBufferList.push(component);
|
||||
}
|
||||
|
||||
// 在调用onAddedToEntity之前清除,以防添加更多组件
|
||||
this._componentsToAdd = {};
|
||||
this.fastComponentsToAddMap.clear();
|
||||
this._isComponentListUnsorted = true;
|
||||
// 在调用onAddedToEntity之前清除,以防添加更多组件
|
||||
this._componentsToAdd = {};
|
||||
this.componentsToAddByType.clear();
|
||||
this._isComponentListUnsorted = true;
|
||||
|
||||
// 现在所有的组件都添加到了场景中,我们再次循环并调用onAddedToEntity/onEnabled
|
||||
for (let i = 0; i < this._tempBufferList.length; i++) {
|
||||
let component = this._tempBufferList[i];
|
||||
component.onAddedToEntity();
|
||||
// 现在所有的组件都添加到了场景中,我们再次循环并调用onAddedToEntity/onEnabled
|
||||
for (let i = 0; i < this._tempBufferList.length; i++) {
|
||||
let component = this._tempBufferList[i];
|
||||
component.onAddedToEntity();
|
||||
|
||||
// enabled检查实体和组件
|
||||
if (component.enabled) {
|
||||
component.onEnabled();
|
||||
}
|
||||
}
|
||||
// enabled检查实体和组件
|
||||
if (component.enabled) {
|
||||
component.onEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
this._tempBufferList.length = 0;
|
||||
this._tempBufferList.length = 0;
|
||||
}
|
||||
|
||||
public handleRemove(component: Component) {
|
||||
if (isIUpdatable(component))
|
||||
new es.List(this._updatableComponents).remove(component);
|
||||
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)), false);
|
||||
this.decreaseBits(component);
|
||||
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
||||
|
||||
component.onRemovedFromEntity();
|
||||
component.entity = null;
|
||||
}
|
||||
|
||||
private removeFastComponent(component: Component) {
|
||||
let fastList = this.fastComponentsMap.get(TypeUtils.getType(component));
|
||||
private removeComponentsByType(component: Component) {
|
||||
let fastList = this.componentsByType.get(TypeUtils.getType(component));
|
||||
let fastIndex = fastList.findIndex(c => c.id == component.id);
|
||||
if (fastIndex != -1)
|
||||
if (fastIndex != -1) {
|
||||
fastList.splice(fastIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private addFastComponent(component: Component) {
|
||||
let fastList = this.fastComponentsMap.get(TypeUtils.getType(component));
|
||||
if (!fastList)
|
||||
fastList = [];
|
||||
private addComponentsByType(component: Component) {
|
||||
let fastList = this.componentsByType.get(TypeUtils.getType(component));
|
||||
if (!fastList) fastList = [];
|
||||
fastList.push(component);
|
||||
this.fastComponentsMap.set(TypeUtils.getType(component), fastList);
|
||||
this.componentsByType.set(TypeUtils.getType(component), fastList);
|
||||
}
|
||||
|
||||
private removeFastComponentToAdd(component: Component) {
|
||||
let fastList = this.fastComponentsToAddMap.get(TypeUtils.getType(component));
|
||||
private removeComponentsToAddByType(component: Component) {
|
||||
let fastList = this.componentsToAddByType.get(TypeUtils.getType(component));
|
||||
let fastIndex = fastList.findIndex(c => c.id == component.id);
|
||||
if (fastIndex != -1)
|
||||
if (fastIndex != -1) {
|
||||
fastList.splice(fastIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private addFastComponentToAdd(component: Component) {
|
||||
let fastList = this.fastComponentsToAddMap.get(TypeUtils.getType(component));
|
||||
if (!fastList)
|
||||
fastList = [];
|
||||
private addComponentsToAddByType(component: Component) {
|
||||
let fastList = this.componentsToAddByType.get(TypeUtils.getType(component));
|
||||
if (!fastList) fastList = [];
|
||||
fastList.push(component);
|
||||
this.fastComponentsToAddMap.set(TypeUtils.getType(component), fastList);
|
||||
this.componentsToAddByType.set(TypeUtils.getType(component), fastList);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,13 +214,13 @@ module es {
|
||||
* @param onlyReturnInitializedComponents
|
||||
*/
|
||||
public getComponent<T extends Component>(type, onlyReturnInitializedComponents: boolean): T {
|
||||
let fastList = this.fastComponentsMap.get(type);
|
||||
let fastList = this.componentsByType.get(type);
|
||||
if (fastList && fastList.length > 0)
|
||||
return fastList[0] as T;
|
||||
|
||||
// 我们可以选择检查挂起的组件,以防addComponent和getComponent在同一个框架中被调用
|
||||
if (!onlyReturnInitializedComponents) {
|
||||
let fastToAddList = this.fastComponentsToAddMap.get(type);
|
||||
let fastToAddList = this.componentsToAddByType.get(type);
|
||||
if (fastToAddList && fastToAddList.length > 0)
|
||||
return fastToAddList[0] as T;
|
||||
}
|
||||
@@ -229,13 +237,13 @@ module es {
|
||||
if (!components)
|
||||
components = [];
|
||||
|
||||
let fastList = this.fastComponentsMap.get(typeName);
|
||||
let fastList = this.componentsByType.get(typeName);
|
||||
if (fastList)
|
||||
components = components.concat(fastList);
|
||||
|
||||
let fastToAddList = this.fastComponentsToAddMap.get(typeName);
|
||||
let fastToAddList = this.componentsToAddByType.get(typeName);
|
||||
if (fastToAddList)
|
||||
components =components.concat(fastToAddList);
|
||||
components = components.concat(fastToAddList);
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
module es {
|
||||
export class Matcher {
|
||||
protected allSet = new BitSet();
|
||||
protected exclusionSet = new BitSet();
|
||||
protected oneSet = new BitSet();
|
||||
protected allSet: (new (...args: any[]) => Component)[] = [];
|
||||
protected exclusionSet: (new (...args: any[]) => Component)[] = [];
|
||||
protected oneSet: (new (...args: any[]) => Component)[] = [];
|
||||
|
||||
public static empty() {
|
||||
return new Matcher();
|
||||
@@ -24,46 +24,53 @@ module es {
|
||||
return this.isInterested(e.componentBits);
|
||||
}
|
||||
|
||||
public isInterested(componentBits: BitSet) {
|
||||
// 检查实体是否拥有该方面中定义的所有组件
|
||||
if (!this.allSet.isEmpty()) {
|
||||
for (let i = this.allSet.nextSetBit(0); i >= 0; i = this.allSet.nextSetBit(i + 1)) {
|
||||
if (!componentBits.get(i))
|
||||
public isInterested(components: Bits) {
|
||||
if (this.allSet.length != 0) {
|
||||
for (let s of this.allSet) {
|
||||
if (!components.get(ComponentTypeManager.getIndexFor(s)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果我们仍然感兴趣,检查该实体是否拥有任何一个排除组件,如果有,那么系统就不感兴趣
|
||||
if (!this.exclusionSet.isEmpty() && this.exclusionSet.intersects(componentBits))
|
||||
return false;
|
||||
if (this.exclusionSet.length != 0) {
|
||||
for (let s of this.exclusionSet) {
|
||||
if (components.get(ComponentTypeManager.getIndexFor(s)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果我们仍然感兴趣,检查该实体是否拥有oneSet中的任何一个组件。如果是,系统就会感兴趣
|
||||
if (!this.oneSet.isEmpty() && !this.oneSet.intersects(componentBits))
|
||||
return false;
|
||||
if (this.oneSet.length != 0) {
|
||||
for (let s of this.oneSet) {
|
||||
if (components.get(ComponentTypeManager.getIndexFor(s)))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public all(...types: any[]): Matcher {
|
||||
types.forEach(type => {
|
||||
this.allSet.set(ComponentTypeManager.getIndexFor(type));
|
||||
});
|
||||
let t;
|
||||
for (t of types) {
|
||||
this.allSet.push(t);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public exclude(...types: any[]) {
|
||||
types.forEach(type => {
|
||||
this.exclusionSet.set(ComponentTypeManager.getIndexFor(type));
|
||||
});
|
||||
let t;
|
||||
for (t of types) {
|
||||
this.exclusionSet.push(t);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public one(...types: any[]) {
|
||||
types.forEach(type => {
|
||||
this.oneSet.set(ComponentTypeManager.getIndexFor(type));
|
||||
});
|
||||
for (const t of types) {
|
||||
this.oneSet.push(t);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user