修复ITriggerListener失效问题
This commit is contained in:
@@ -562,10 +562,6 @@ module es {
|
||||
return this.compareTo(other) == 0;
|
||||
}
|
||||
|
||||
public getHashCode(): number {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return `[Entity: name: ${this.name}, tag: ${this.tag}, enabled: ${this.enabled}, depth: ${this.updateOrder}]`;
|
||||
}
|
||||
|
||||
@@ -60,5 +60,17 @@ module es {
|
||||
public static invertFlags(self: Ref<number>) {
|
||||
self.value = ~self.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印 number 的二进制表示。 方便调试 number 标志
|
||||
*/
|
||||
public static binaryStringRepresentation(self: number,
|
||||
leftPadWidth: number = 10) {
|
||||
let str = self.toString(2);
|
||||
while (str.length < (leftPadWidth || 2)) {
|
||||
str = '0' + str;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ module es {
|
||||
export class ColliderTriggerHelper {
|
||||
private _entity: Entity;
|
||||
/** 存储当前帧中发生的所有活动交点对 */
|
||||
private _activeTriggerIntersections: HashSet<Pair<Collider>> = new HashSet<Pair<Collider>>();
|
||||
private _activeTriggerIntersections: PairSet<Collider> = new PairSet<Collider>();
|
||||
/** 存储前一帧的交点对,这样我们就可以在移动这一帧后检测到退出 */
|
||||
private _previousTriggerIntersections: HashSet<Pair<Collider>> = new HashSet<Pair<Collider>>();
|
||||
private _previousTriggerIntersections: PairSet<Collider> = new PairSet<Collider>();
|
||||
private _tempTriggerList: ITriggerListener[] = [];
|
||||
|
||||
constructor(entity: Entity) {
|
||||
@@ -22,11 +22,11 @@ module es {
|
||||
const lateColliders = [];
|
||||
// 对所有实体.colliders进行重叠检查,这些实体.colliders是触发器,与所有宽相碰撞器,无论是否触发器。
|
||||
// 任何重叠都会导致触发事件
|
||||
let colliders = this._entity.getComponents(Collider);
|
||||
let colliders: Collider[] = this.getColliders();
|
||||
for (let i = 0; i < colliders.length; i++) {
|
||||
let collider = colliders[i];
|
||||
|
||||
let neighbors = Physics.boxcastBroadphaseExcludingSelf(collider.bounds, collider.collidesWithLayers);
|
||||
let neighbors = Physics.boxcastBroadphaseExcludingSelf(collider, collider.bounds, collider.collidesWithLayers.value);
|
||||
for (let j = 0; j < neighbors.length; j++) {
|
||||
let neighbor = neighbors[j];
|
||||
// 我们至少需要一个碰撞器作为触发器
|
||||
@@ -37,8 +37,8 @@ module es {
|
||||
const pair = new Pair<Collider>(collider, neighbor);
|
||||
|
||||
// 如果我们的某一个集合中已经有了这个对子(前一个或当前的触发交叉点),就不要调用输入事件了
|
||||
const shouldReportTriggerEvent = !this._activeTriggerIntersections.contains(pair) &&
|
||||
!this._previousTriggerIntersections.contains(pair);
|
||||
const shouldReportTriggerEvent = !this._activeTriggerIntersections.has(pair) &&
|
||||
!this._previousTriggerIntersections.has(pair);
|
||||
|
||||
if (shouldReportTriggerEvent) {
|
||||
if (neighbor.castSortOrder >= Collider.lateSortOrder) {
|
||||
@@ -60,18 +60,30 @@ module es {
|
||||
this.checkForExitedColliders();
|
||||
}
|
||||
|
||||
private getColliders() {
|
||||
const colliders: Collider[] = [];
|
||||
for (let i = 0; i < this._entity.components.buffer.length; i ++) {
|
||||
const component = this._entity.components.buffer[i];
|
||||
if (component instanceof Collider) {
|
||||
colliders.push(component);
|
||||
}
|
||||
}
|
||||
|
||||
return colliders;
|
||||
}
|
||||
|
||||
private checkForExitedColliders() {
|
||||
// 删除所有与此帧交互的触发器,留下我们退出的触发器
|
||||
this._previousTriggerIntersections.exceptWith(this._activeTriggerIntersections.toArray());
|
||||
|
||||
for (let i = 0; i < this._previousTriggerIntersections.getCount(); i++) {
|
||||
this.notifyTriggerListeners(this._previousTriggerIntersections[i], false)
|
||||
}
|
||||
this._previousTriggerIntersections.except(this._activeTriggerIntersections);
|
||||
const all = this._previousTriggerIntersections.all;
|
||||
all.forEach(pair => {
|
||||
this.notifyTriggerListeners(pair, false);
|
||||
});
|
||||
|
||||
this._previousTriggerIntersections.clear();
|
||||
|
||||
// 添加所有当前激活的触发器
|
||||
this._previousTriggerIntersections.unionWith(this._activeTriggerIntersections.toArray());
|
||||
this._previousTriggerIntersections.union(this._activeTriggerIntersections);
|
||||
|
||||
// 清空活动集,为下一帧做准备
|
||||
this._activeTriggerIntersections.clear();
|
||||
|
||||
@@ -2,7 +2,7 @@ module es {
|
||||
/**
|
||||
* 用于管理一对对象的简单DTO
|
||||
*/
|
||||
export class Pair<T> implements IEqualityComparable {
|
||||
export class Pair<T> {
|
||||
public first: T;
|
||||
public second: T;
|
||||
|
||||
@@ -17,12 +17,7 @@ module es {
|
||||
|
||||
public equals(other: Pair<T>): boolean {
|
||||
// 这两种方法在功能上应该是等价的
|
||||
return this.first == other.first && this.second == other.second;
|
||||
}
|
||||
|
||||
public getHashCode(): number {
|
||||
return EqualityComparer.default<T>().getHashCode(this.first) * 37 +
|
||||
EqualityComparer.default<T>().getHashCode(this.second);
|
||||
return this.first === other.first && this.second === other.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
source/src/Utils/Collections/PairSet.ts
Normal file
48
source/src/Utils/Collections/PairSet.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
module es {
|
||||
export class PairSet<T> {
|
||||
public get all(): Array<Pair<T>> {
|
||||
return this._all;
|
||||
}
|
||||
|
||||
public has(pair: Pair<T>) {
|
||||
const index = this._all.findIndex(p => p.equals(pair));
|
||||
return index > -1;
|
||||
}
|
||||
|
||||
public add(pair: Pair<T>) {
|
||||
if (!this.has(pair)) {
|
||||
this._all.push(pair);
|
||||
}
|
||||
}
|
||||
|
||||
public remove(pair: Pair<T>) {
|
||||
const index = this._all.findIndex(p => p.equals(pair));
|
||||
if (index > -1) {
|
||||
const temp = this._all[index];
|
||||
this._all[index] = this._all[this._all.length - 1];
|
||||
this._all[this._all.length - 1] = temp;
|
||||
this._all = this._all.slice(0, this._all.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public clear() {
|
||||
this._all = [];
|
||||
}
|
||||
|
||||
public union(other: PairSet<T>) {
|
||||
const otherAll = other.all;
|
||||
for (const elem of otherAll) {
|
||||
this.add(elem);
|
||||
}
|
||||
}
|
||||
|
||||
public except(other: PairSet<T>) {
|
||||
const otherAll = other.all;
|
||||
for (const elem of otherAll) {
|
||||
this.remove(elem);
|
||||
}
|
||||
}
|
||||
|
||||
private _all: Array<Pair<T>> = new Array<Pair<T>>();
|
||||
}
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
module es {
|
||||
export interface ISet<T> {
|
||||
add(item: T): boolean
|
||||
remove(item: T): boolean
|
||||
contains(item: T): boolean
|
||||
getCount(): number
|
||||
clear(): void
|
||||
toArray(): Array<T>
|
||||
/**
|
||||
* 从当前集合中删除指定集合中的所有元素
|
||||
* @param other
|
||||
*/
|
||||
exceptWith(other: Array<T>): void
|
||||
/**
|
||||
* 修改当前Set对象,使其只包含该对象和指定数组中的元素
|
||||
* @param other
|
||||
*/
|
||||
intersectWith(other: Array<T>): void
|
||||
/**
|
||||
* 修改当前的集合对象,使其包含所有存在于自身、指定集合中的元素,或者两者都包含
|
||||
* @param other
|
||||
*/
|
||||
unionWith(other: Array<T>): void
|
||||
isSubsetOf(other: Array<T>): boolean
|
||||
isSupersetOf(other: Array<T>): boolean
|
||||
overlaps(other: Array<T>): boolean
|
||||
setEquals(other: Array<T>): boolean
|
||||
}
|
||||
|
||||
interface IBucketsWithCount<T> {
|
||||
Buckets: Array<Array<T>>
|
||||
Count: number
|
||||
}
|
||||
|
||||
abstract class Set<T> implements ISet<T> {
|
||||
protected buckets: T[][];
|
||||
protected count: number;
|
||||
constructor(source?: Array<T>) {
|
||||
this.clear();
|
||||
if (source)
|
||||
source.forEach(value => {
|
||||
this.add(value);
|
||||
});
|
||||
}
|
||||
abstract getHashCode(item: T): number;
|
||||
abstract areEqual(value1: T, value2: T): boolean;
|
||||
|
||||
add(item: T) {
|
||||
let hashCode = this.getHashCode(item);
|
||||
let bucket = this.buckets[hashCode];
|
||||
if (bucket === undefined) {
|
||||
let newBucket = new Array<T>();
|
||||
newBucket.push(item);
|
||||
this.buckets[hashCode] = newBucket;
|
||||
this.count = this.count + 1;
|
||||
return true;
|
||||
}
|
||||
if (bucket.some((value) => this.areEqual(value,item)))
|
||||
return false;
|
||||
bucket.push(item);
|
||||
this.count = this.count + 1;
|
||||
return true;
|
||||
};
|
||||
|
||||
remove(item: T) {
|
||||
let hashCode = this.getHashCode(item);
|
||||
let bucket = this.buckets[hashCode];
|
||||
if (bucket === undefined) {
|
||||
return false;
|
||||
}
|
||||
let result = false;
|
||||
let newBucket = new Array<T>();
|
||||
bucket.forEach((value) => {
|
||||
if (!this.areEqual(value, item))
|
||||
newBucket.push(item);
|
||||
else
|
||||
result = true;
|
||||
});
|
||||
this.buckets[hashCode] = newBucket;
|
||||
if (result)
|
||||
this.count = this.count - 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
contains(item: T) {
|
||||
return this.bucketsContains(this.buckets, item)
|
||||
};
|
||||
|
||||
getCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.buckets = new Array<Array<T>>();
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
toArray() {
|
||||
let result = new Array<T>()
|
||||
this.buckets.forEach(value => {
|
||||
value.forEach(inner => {
|
||||
result.push(inner);
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从当前集合中删除指定集合中的所有元素
|
||||
* @param other
|
||||
*/
|
||||
exceptWith(other: Array<T>) {
|
||||
if (other) {
|
||||
other.forEach(value => {
|
||||
this.remove(value);
|
||||
})
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 修改当前Set对象,使其只包含该对象和指定数组中的元素
|
||||
* @param other
|
||||
*/
|
||||
intersectWith(other: Array<T>) {
|
||||
if (other) {
|
||||
let otherBuckets = this.buildInternalBuckets(other);
|
||||
this.toArray().forEach(value => {
|
||||
if (!this.bucketsContains(otherBuckets.Buckets, value))
|
||||
this.remove(value);
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
unionWith(other: Array<T>) {
|
||||
other.forEach(value => {
|
||||
this.add(value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定当前集合是否为指定集合或数组的子集
|
||||
* @param other
|
||||
*/
|
||||
isSubsetOf(other: Array<T>) {
|
||||
|
||||
let otherBuckets = this.buildInternalBuckets(other);
|
||||
return this.toArray().every(value => this.bucketsContains(otherBuckets.Buckets, value));
|
||||
|
||||
}
|
||||
/**
|
||||
* 确定当前不可变排序集是否为指定集合的超集
|
||||
* @param other
|
||||
*/
|
||||
isSupersetOf(other: Array<T>) {
|
||||
return other.every(value => this.contains(value));
|
||||
}
|
||||
|
||||
overlaps(other: Array<T>) {
|
||||
return other.some(value => this.contains(value));
|
||||
}
|
||||
|
||||
setEquals(other: Array<T>) {
|
||||
let otherBuckets = this.buildInternalBuckets(other);
|
||||
if (otherBuckets.Count !== this.count)
|
||||
return false
|
||||
return other.every(value => this.contains(value));
|
||||
}
|
||||
|
||||
private buildInternalBuckets(source: Array<T>): IBucketsWithCount<T> {
|
||||
let internalBuckets = new Array<Array<T>>();
|
||||
let internalCount = 0;
|
||||
source.forEach(item=> {
|
||||
let hashCode = this.getHashCode(item);
|
||||
let bucket = internalBuckets[hashCode];
|
||||
if (bucket === undefined) {
|
||||
let newBucket = new Array<T>();
|
||||
newBucket.push(item);
|
||||
internalBuckets[hashCode] = newBucket;
|
||||
internalCount = internalCount + 1;
|
||||
}
|
||||
else if (!bucket.some((value) => this.areEqual(value, item))) {
|
||||
bucket.push(item);
|
||||
internalCount = internalCount + 1;
|
||||
}
|
||||
});
|
||||
return { Buckets: internalBuckets, Count: internalCount };
|
||||
}
|
||||
|
||||
private bucketsContains(internalBuckets: Array<Array<T>>, item: T) {
|
||||
let hashCode = this.getHashCode(item);
|
||||
let bucket = internalBuckets[hashCode];
|
||||
if (bucket === undefined) {
|
||||
return false;
|
||||
}
|
||||
return bucket.some((value) => this.areEqual(value, item));
|
||||
}
|
||||
}
|
||||
|
||||
export class HashSet<T extends IEqualityComparable> extends Set<T> {
|
||||
constructor(source?: Array<T>) {
|
||||
super(source)
|
||||
}
|
||||
getHashCode(item: T) {
|
||||
return item.getHashCode();
|
||||
}
|
||||
areEqual(value1: T, value2: T) {
|
||||
return value1.equals(value2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,5 @@ module es {
|
||||
* @param other
|
||||
*/
|
||||
equals(other: any): boolean;
|
||||
|
||||
/**
|
||||
* 生成对象的哈希码
|
||||
*/
|
||||
getHashCode(): number;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user