优化triggerListener与ArrayUtils
This commit is contained in:
112
source/bin/framework.d.ts
vendored
112
source/bin/framework.d.ts
vendored
@@ -246,7 +246,7 @@ declare module es {
|
||||
*/
|
||||
protected onGraphicsDeviceReset(): void;
|
||||
protected initialize(): void;
|
||||
protected update(): Promise<void>;
|
||||
protected update(currentTime?: number): Promise<void>;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
@@ -858,6 +858,10 @@ declare module es {
|
||||
*/
|
||||
onTriggerExit(other: Collider, local: Collider): any;
|
||||
}
|
||||
class TriggerListenerHelper {
|
||||
static getITriggerListener(entity: Entity, components: ITriggerListener[]): ITriggerListener[];
|
||||
}
|
||||
var isITriggerListener: (props: any) => props is ITriggerListener;
|
||||
}
|
||||
declare module es {
|
||||
/**
|
||||
@@ -2474,17 +2478,20 @@ declare module es {
|
||||
*/
|
||||
class ColliderTriggerHelper {
|
||||
private _entity;
|
||||
/** 存储当前帧中发生的所有活动交集对 */
|
||||
/** 存储当前帧中发生的所有活动交点对 */
|
||||
private _activeTriggerIntersections;
|
||||
/** 存储前一帧的交叉对,以便我们可以在移动该帧后检测出口 */
|
||||
/** 存储前一帧的交点对,这样我们就可以在移动这一帧后检测到退出 */
|
||||
private _previousTriggerIntersections;
|
||||
private _tempTriggerList;
|
||||
constructor(entity: Entity);
|
||||
/**
|
||||
* 实体被移动后,应该调用更新。它会处理碰撞器重叠的任何itriggerlistener。
|
||||
* update应该在实体被移动后被调用,它将处理任何与Colllider重叠的ITriggerListeners。
|
||||
* 它将处理任何与Collider重叠的ITriggerListeners。
|
||||
*/
|
||||
update(): void;
|
||||
private checkForExitedColliders;
|
||||
private excepthWith;
|
||||
private unionWith;
|
||||
private notifyTriggerListeners;
|
||||
}
|
||||
}
|
||||
@@ -2561,11 +2568,11 @@ declare module es {
|
||||
}
|
||||
declare module es {
|
||||
class Physics {
|
||||
static _spatialHash: SpatialHash;
|
||||
/** 调用reset并创建一个新的SpatialHash时使用的单元格大小 */
|
||||
static spatialHashCellSize: number;
|
||||
/** 接受layerMask的所有方法的默认值 */
|
||||
static readonly allLayers: number;
|
||||
private static _spatialHash;
|
||||
/**
|
||||
* raycast是否检测配置为触发器的碰撞器
|
||||
*/
|
||||
@@ -2596,14 +2603,14 @@ declare module es {
|
||||
* @param rect
|
||||
* @param layerMask
|
||||
*/
|
||||
static boxcastBroadphase(rect: Rectangle, layerMask?: number): Collider[];
|
||||
static boxcastBroadphase(rect: Rectangle, layerMask?: number): Set<Collider>;
|
||||
/**
|
||||
* 返回所有与边界相交的碰撞器,不包括传入的碰撞器(self)。如果您希望为其他查询自行创建扫过的边界,则此方法非常有用
|
||||
* @param collider
|
||||
* @param rect
|
||||
* @param layerMask
|
||||
*/
|
||||
static boxcastBroadphaseExcludingSelf(collider: Collider, rect: Rectangle, layerMask?: number): Collider[];
|
||||
static boxcastBroadphaseExcludingSelf(collider: Collider, rect: Rectangle, layerMask?: number): Set<Collider>;
|
||||
/**
|
||||
* 将对撞机添加到物理系统中
|
||||
* @param collider
|
||||
@@ -2634,11 +2641,6 @@ declare module es {
|
||||
* @param layerMask
|
||||
*/
|
||||
static linecastAll(start: Vector2, end: Vector2, hits: RaycastHit[], layerMask?: number): number;
|
||||
/**
|
||||
* debug绘制空间散列的内容
|
||||
* @param secondsToDisplay
|
||||
*/
|
||||
static debugDraw(secondsToDisplay: any): void;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
@@ -2675,7 +2677,7 @@ declare module es {
|
||||
/**
|
||||
* 用于返回冲突信息的共享HashSet
|
||||
*/
|
||||
_tempHashSet: Collider[];
|
||||
_tempHashSet: Set<Collider>;
|
||||
constructor(cellSize?: number);
|
||||
/**
|
||||
* 将对象添加到SpatialHash
|
||||
@@ -2693,19 +2695,13 @@ declare module es {
|
||||
*/
|
||||
removeWithBruteForce(obj: Collider): void;
|
||||
clear(): void;
|
||||
/**
|
||||
* debug绘制空间散列的内容
|
||||
* @param secondsToDisplay
|
||||
* @param textScale
|
||||
*/
|
||||
debugDraw(secondsToDisplay: number, textScale?: number): void;
|
||||
/**
|
||||
* 返回边框与单元格相交的所有对象
|
||||
* @param bounds
|
||||
* @param excludeCollider
|
||||
* @param layerMask
|
||||
*/
|
||||
aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number): Collider[];
|
||||
aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number): Set<Collider>;
|
||||
/**
|
||||
* 通过空间散列强制执行一行,并用该行命中的任何碰撞器填充hits数组。
|
||||
* @param start
|
||||
@@ -2727,7 +2723,7 @@ declare module es {
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
private cellCoords;
|
||||
cellCoords(x: number, y: number): Vector2;
|
||||
/**
|
||||
* 获取世界空间x,y值的单元格。
|
||||
* 如果单元格为空且createCellIfEmpty为true,则会创建一个新的单元格
|
||||
@@ -2735,8 +2731,7 @@ declare module es {
|
||||
* @param y
|
||||
* @param createCellIfEmpty
|
||||
*/
|
||||
private cellAtPosition;
|
||||
private debugDrawCellDetails;
|
||||
cellAtPosition(x: number, y: number, createCellIfEmpty?: boolean): Collider[];
|
||||
}
|
||||
/**
|
||||
* 包装一个Unit32,列表碰撞器字典
|
||||
@@ -3083,39 +3078,38 @@ declare class ArrayUtils {
|
||||
static bubbleSort(ary: number[]): void;
|
||||
/**
|
||||
* 执行插入排序
|
||||
* @param ary
|
||||
* @param ary
|
||||
*/
|
||||
static insertionSort(ary: number[]): void;
|
||||
/**
|
||||
* 执行二分搜索
|
||||
* @param ary 搜索的数组(必须排序过)
|
||||
* @param value 需要搜索的值
|
||||
* @return 返回匹配结果的数组索引
|
||||
* @param ary 搜索的数组(必须排序过)
|
||||
* @param value 需要搜索的值
|
||||
* @returns 返回匹配结果的数组索引
|
||||
*/
|
||||
static binarySearch(ary: number[], value: number): number;
|
||||
/**
|
||||
* 返回匹配项的索引
|
||||
* @param ary
|
||||
* @param num
|
||||
* @return 返回匹配项的索引
|
||||
* @param ary
|
||||
* @param num
|
||||
*/
|
||||
static findElementIndex(ary: any[], num: any): any;
|
||||
/**
|
||||
* 返回数组中最大值的索引
|
||||
* @param ary
|
||||
* @return 返回数组中最大值的索引
|
||||
* @param ary
|
||||
*/
|
||||
static getMaxElementIndex(ary: number[]): number;
|
||||
/**
|
||||
* 返回数组中最小值的索引
|
||||
* @param ary
|
||||
* @return 返回数组中最小值的索引
|
||||
* @param ary
|
||||
*/
|
||||
static getMinElementIndex(ary: number[]): number;
|
||||
/**
|
||||
* 返回一个"唯一性"数组
|
||||
* @param ary 需要唯一性的数组
|
||||
* @return 唯一性的数组
|
||||
* @param ary 需要唯一性的数组
|
||||
* @returns 唯一性的数组
|
||||
*
|
||||
* @tutorial
|
||||
* 比如: [1, 2, 2, 3, 4]
|
||||
* 返回: [1, 2, 3, 4]
|
||||
*/
|
||||
@@ -3139,7 +3133,7 @@ declare class ArrayUtils {
|
||||
static swap(array: any[], index1: number, index2: number): void;
|
||||
/**
|
||||
* 清除列表
|
||||
* @param ary 列表
|
||||
* @param ary
|
||||
*/
|
||||
static clearList(ary: any[]): void;
|
||||
/**
|
||||
@@ -3150,18 +3144,45 @@ declare class ArrayUtils {
|
||||
static cloneList(ary: any[]): any[];
|
||||
/**
|
||||
* 判断2个数组是否相同
|
||||
* @param ary1 数组1
|
||||
* @param ary2 数组2
|
||||
* @return 是否相同
|
||||
* @param ary1 数组1
|
||||
* @param ary2 数组2
|
||||
*/
|
||||
static equals(ary1: number[], ary2: number[]): Boolean;
|
||||
/**
|
||||
* 根据索引插入元素,索引和索引后的元素都向后移动一位
|
||||
* @param index 插入索引
|
||||
* @param value 插入的元素
|
||||
* @return 插入的元素 未插入则返回空
|
||||
* @param ary
|
||||
* @param index 插入索引
|
||||
* @param value 插入的元素
|
||||
* @returns 插入的元素 未插入则返回空
|
||||
*/
|
||||
static insert(ary: any[], index: number, value: any): any;
|
||||
/**
|
||||
* 打乱数组 Fisher–Yates shuffle
|
||||
* @param list
|
||||
*/
|
||||
static shuffle<T>(list: T[]): void;
|
||||
/**
|
||||
* 如果项目已经在列表中,返回false,如果成功添加,返回true
|
||||
* @param list
|
||||
* @param item
|
||||
*/
|
||||
static addIfNotPresent<T>(list: T[], item: T): boolean;
|
||||
/**
|
||||
* 返回列表中的最后一项。列表中至少应该有一个项目
|
||||
* @param list
|
||||
*/
|
||||
static lastItem<T>(list: T[]): T;
|
||||
/**
|
||||
* 从列表中随机获取一个项目。不清空检查列表!
|
||||
* @param list
|
||||
*/
|
||||
static randomItem<T>(list: T[]): T;
|
||||
/**
|
||||
* 从列表中随机获取物品。不清空检查列表,也不验证列表数是否大于项目数。返回的List可以通过ListPool.free放回池中
|
||||
* @param list
|
||||
* @param itemCount 从列表中返回的随机项目的数量
|
||||
*/
|
||||
static randomItems<T>(list: T[], itemCount: number): T[];
|
||||
}
|
||||
declare module es {
|
||||
class Base64Utils {
|
||||
@@ -3577,6 +3598,11 @@ declare module es {
|
||||
private initialize;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
class TypeUtils {
|
||||
static getType(obj: any): any;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
class Vector2Ext {
|
||||
/**
|
||||
|
||||
@@ -568,12 +568,14 @@ var es;
|
||||
};
|
||||
Core.prototype.initialize = function () {
|
||||
};
|
||||
Core.prototype.update = function () {
|
||||
Core.prototype.update = function (currentTime) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var i;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (currentTime != null)
|
||||
es.Time.update(currentTime);
|
||||
if (this._scene != null) {
|
||||
for (i = this._globalManagers.length - 1; i >= 0; i--) {
|
||||
if (this._globalManagers[i].enabled)
|
||||
@@ -964,7 +966,7 @@ var es;
|
||||
* @param type
|
||||
*/
|
||||
Entity.prototype.getOrCreateComponent = function (type) {
|
||||
var comp = this.components.getComponent(type, true);
|
||||
var comp = this.components.getComponent(es.TypeUtils.getType(type), true);
|
||||
if (!comp) {
|
||||
comp = this.addComponent(type);
|
||||
}
|
||||
@@ -1878,6 +1880,31 @@ var es;
|
||||
es.SceneComponent = SceneComponent;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var TriggerListenerHelper = /** @class */ (function () {
|
||||
function TriggerListenerHelper() {
|
||||
}
|
||||
TriggerListenerHelper.getITriggerListener = function (entity, components) {
|
||||
for (var i = 0; i < entity.components._components.length; i++) {
|
||||
var component = entity.components._components.buffer[i];
|
||||
if (es.isITriggerListener(component)) {
|
||||
components.push(component);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < entity.components._componentsToAdd.length; i++) {
|
||||
var component = entity.components._componentsToAdd[i];
|
||||
if (es.isITriggerListener(component)) {
|
||||
components.push(component);
|
||||
}
|
||||
}
|
||||
return components;
|
||||
};
|
||||
return TriggerListenerHelper;
|
||||
}());
|
||||
es.TriggerListenerHelper = TriggerListenerHelper;
|
||||
es.isITriggerListener = function (props) { return typeof props['onTriggerEnter'] !== 'undefined'; };
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
/**
|
||||
* 辅助类说明了一种处理移动的方法,它考虑了包括触发器在内的所有冲突。
|
||||
@@ -1915,7 +1942,7 @@ var es;
|
||||
bounds.x += motion.x;
|
||||
bounds.y += motion.y;
|
||||
var neighbors = es.Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers.value);
|
||||
for (var j = 0; j < neighbors.length; j++) {
|
||||
for (var j = 0; j < neighbors.size; j++) {
|
||||
var neighbor = neighbors[j];
|
||||
// 不检测触发器
|
||||
if (neighbor.isTrigger)
|
||||
@@ -1989,8 +2016,8 @@ var es;
|
||||
this.entity.position.add(motion);
|
||||
// 获取任何可能在新位置发生碰撞的东西
|
||||
var neighbors = es.Physics.boxcastBroadphase(this._collider.bounds, this._collider.collidesWithLayers.value);
|
||||
for (var _i = 0, neighbors_1 = neighbors; _i < neighbors_1.length; _i++) {
|
||||
var neighbor = neighbors_1[_i];
|
||||
for (var i = 0; i < neighbors.size; i++) {
|
||||
var neighbor = neighbors[i];
|
||||
if (this._collider.overlaps(neighbor) && neighbor.enabled) {
|
||||
didCollide = true;
|
||||
this.notifyTriggerListeners(this._collider, neighbor);
|
||||
@@ -2000,13 +2027,13 @@ var es;
|
||||
};
|
||||
ProjectileMover.prototype.notifyTriggerListeners = function (self, other) {
|
||||
// 通知我们重叠的碰撞器实体上的任何侦听器
|
||||
other.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
es.TriggerListenerHelper.getITriggerListener(other.entity, this._tempTriggerList);
|
||||
for (var i = 0; i < this._tempTriggerList.length; i++) {
|
||||
this._tempTriggerList[i].onTriggerEnter(self, other);
|
||||
}
|
||||
this._tempTriggerList.length = 0;
|
||||
// 通知此实体上的任何侦听器
|
||||
this.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
es.TriggerListenerHelper.getITriggerListener(this.entity, this._tempTriggerList);
|
||||
for (var i = 0; i < this._tempTriggerList.length; i++) {
|
||||
this._tempTriggerList[i].onTriggerEnter(other, self);
|
||||
}
|
||||
@@ -2685,7 +2712,7 @@ var es;
|
||||
if (es.isIUpdatable(component))
|
||||
this._updatableComponents.remove(component);
|
||||
if (es.Core.entitySystemsEnabled) {
|
||||
this._entity.componentBits.set(es.ComponentTypeManager.getIndexFor(component["__proto__"]["constructor"]), false);
|
||||
this._entity.componentBits.set(es.ComponentTypeManager.getIndexFor(es.TypeUtils.getType(component)), false);
|
||||
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
||||
}
|
||||
}
|
||||
@@ -2696,7 +2723,7 @@ var es;
|
||||
if (es.isIUpdatable(component))
|
||||
this._updatableComponents.add(component);
|
||||
if (es.Core.entitySystemsEnabled) {
|
||||
this._entity.componentBits.set(es.ComponentTypeManager.getIndexFor(component["__proto__"]["constructor"]));
|
||||
this._entity.componentBits.set(es.ComponentTypeManager.getIndexFor(es.TypeUtils.getType(component)));
|
||||
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
||||
}
|
||||
}
|
||||
@@ -2718,7 +2745,7 @@ var es;
|
||||
if (es.isIUpdatable(component))
|
||||
this._updatableComponents.add(component);
|
||||
if (es.Core.entitySystemsEnabled) {
|
||||
this._entity.componentBits.set(es.ComponentTypeManager.getIndexFor(component["__proto__"]["constructor"]));
|
||||
this._entity.componentBits.set(es.ComponentTypeManager.getIndexFor(es.TypeUtils.getType(component)));
|
||||
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
||||
}
|
||||
this._components.add(component);
|
||||
@@ -2749,7 +2776,7 @@ var es;
|
||||
if (es.isIUpdatable(component))
|
||||
this._updatableComponents.remove(component);
|
||||
if (es.Core.entitySystemsEnabled) {
|
||||
this._entity.componentBits.set(es.ComponentTypeManager.getIndexFor(component["__proto__"]["constructor"]), false);
|
||||
this._entity.componentBits.set(es.ComponentTypeManager.getIndexFor(es.TypeUtils.getType(component)), false);
|
||||
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
||||
}
|
||||
component.onRemovedFromEntity();
|
||||
@@ -5979,74 +6006,73 @@ var es;
|
||||
*/
|
||||
var ColliderTriggerHelper = /** @class */ (function () {
|
||||
function ColliderTriggerHelper(entity) {
|
||||
/** 存储当前帧中发生的所有活动交集对 */
|
||||
this._activeTriggerIntersections = [];
|
||||
/** 存储前一帧的交叉对,以便我们可以在移动该帧后检测出口 */
|
||||
this._previousTriggerIntersections = [];
|
||||
/** 存储当前帧中发生的所有活动交点对 */
|
||||
this._activeTriggerIntersections = new Set();
|
||||
/** 存储前一帧的交点对,这样我们就可以在移动这一帧后检测到退出 */
|
||||
this._previousTriggerIntersections = new Set();
|
||||
this._tempTriggerList = [];
|
||||
this._entity = entity;
|
||||
}
|
||||
/**
|
||||
* 实体被移动后,应该调用更新。它会处理碰撞器重叠的任何itriggerlistener。
|
||||
* update应该在实体被移动后被调用,它将处理任何与Colllider重叠的ITriggerListeners。
|
||||
* 它将处理任何与Collider重叠的ITriggerListeners。
|
||||
*/
|
||||
ColliderTriggerHelper.prototype.update = function () {
|
||||
// 对所有实体.colliders进行重叠检查,这些实体.colliders是触发器,与所有宽相碰撞器,无论是否触发器。
|
||||
// 任何重叠都会导致触发事件
|
||||
var colliders = this._entity.getComponents(es.Collider);
|
||||
for (var i = 0; i < colliders.length; i++) {
|
||||
var collider = colliders[i];
|
||||
var neighbors = es.Physics.boxcastBroadphase(collider.bounds, collider.collidesWithLayers);
|
||||
var _loop_2 = function (j) {
|
||||
for (var j = 0; j < neighbors.size; j++) {
|
||||
var neighbor = neighbors[j];
|
||||
// 我们至少需要一个碰撞器作为触发器
|
||||
if (!collider.isTrigger && !neighbor.isTrigger)
|
||||
return "continue";
|
||||
continue;
|
||||
if (collider.overlaps(neighbor)) {
|
||||
var pair_1 = new es.Pair(collider, neighbor);
|
||||
var shouldReportTriggerEvent = this_1._activeTriggerIntersections.findIndex(function (value) {
|
||||
return value.first == pair_1.first && value.second == pair_1.second;
|
||||
}) == -1 && this_1._previousTriggerIntersections.findIndex(function (value) {
|
||||
return value.first == pair_1.first && value.second == pair_1.second;
|
||||
}) == -1;
|
||||
var pair = new es.Pair(collider, neighbor);
|
||||
// 如果我们的某一个集合中已经有了这个对子(前一个或当前的触发交叉点),就不要调用输入事件了
|
||||
var shouldReportTriggerEvent = !this._activeTriggerIntersections.has(pair) &&
|
||||
!this._previousTriggerIntersections.has(pair);
|
||||
if (shouldReportTriggerEvent)
|
||||
this_1.notifyTriggerListeners(pair_1, true);
|
||||
if (!this_1._activeTriggerIntersections.contains(pair_1))
|
||||
this_1._activeTriggerIntersections.push(pair_1);
|
||||
this.notifyTriggerListeners(pair, true);
|
||||
this._activeTriggerIntersections.add(pair);
|
||||
}
|
||||
};
|
||||
var this_1 = this;
|
||||
for (var j = 0; j < neighbors.length; j++) {
|
||||
_loop_2(j);
|
||||
}
|
||||
}
|
||||
es.ListPool.free(colliders);
|
||||
this.checkForExitedColliders();
|
||||
};
|
||||
ColliderTriggerHelper.prototype.checkForExitedColliders = function () {
|
||||
var _this = this;
|
||||
var _loop_3 = function (i) {
|
||||
var index = this_2._previousTriggerIntersections.findIndex(function (value) {
|
||||
if (value.first == _this._activeTriggerIntersections[i].first && value.second == _this._activeTriggerIntersections[i].second)
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
if (index != -1)
|
||||
this_2._previousTriggerIntersections.removeAt(index);
|
||||
};
|
||||
var this_2 = this;
|
||||
for (var i = 0; i < this._activeTriggerIntersections.length; i++) {
|
||||
_loop_3(i);
|
||||
}
|
||||
for (var i = 0; i < this._previousTriggerIntersections.length; i++) {
|
||||
// 删除所有与此帧交互的触发器,留下我们退出的触发器
|
||||
this.excepthWith(this._previousTriggerIntersections, this._activeTriggerIntersections);
|
||||
for (var i = 0; i < this._previousTriggerIntersections.size; i++) {
|
||||
this.notifyTriggerListeners(this._previousTriggerIntersections[i], false);
|
||||
}
|
||||
this._previousTriggerIntersections.length = 0;
|
||||
for (var i = 0; i < this._activeTriggerIntersections.length; i++) {
|
||||
if (!this._previousTriggerIntersections.contains(this._activeTriggerIntersections[i])) {
|
||||
this._previousTriggerIntersections.push(this._activeTriggerIntersections[i]);
|
||||
this._previousTriggerIntersections.clear();
|
||||
// 添加所有当前激活的触发器
|
||||
this.unionWith(this._previousTriggerIntersections, this._activeTriggerIntersections);
|
||||
// 清空活动集,为下一帧做准备
|
||||
this._activeTriggerIntersections.clear();
|
||||
};
|
||||
ColliderTriggerHelper.prototype.excepthWith = function (previous, active) {
|
||||
for (var i = 0; i < previous.size; i++) {
|
||||
var previousDATA = previous[i];
|
||||
for (var j = 0; j < active.size; j++) {
|
||||
var activeDATA = active[j];
|
||||
if (activeDATA.equals(previousDATA))
|
||||
previous.delete(previousDATA);
|
||||
}
|
||||
}
|
||||
this._activeTriggerIntersections.length = 0;
|
||||
};
|
||||
ColliderTriggerHelper.prototype.unionWith = function (previous, active) {
|
||||
for (var i = 0; i < this._activeTriggerIntersections.size; i++) {
|
||||
if (!this._previousTriggerIntersections.has(this._activeTriggerIntersections[i]))
|
||||
this._previousTriggerIntersections.add(this._activeTriggerIntersections[i]);
|
||||
}
|
||||
};
|
||||
ColliderTriggerHelper.prototype.notifyTriggerListeners = function (collisionPair, isEntering) {
|
||||
collisionPair.first.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
es.TriggerListenerHelper.getITriggerListener(collisionPair.first.entity, this._tempTriggerList);
|
||||
for (var i = 0; i < this._tempTriggerList.length; i++) {
|
||||
if (isEntering) {
|
||||
this._tempTriggerList[i].onTriggerEnter(collisionPair.second, collisionPair.first);
|
||||
@@ -6056,7 +6082,7 @@ var es;
|
||||
}
|
||||
this._tempTriggerList.length = 0;
|
||||
if (collisionPair.second.entity) {
|
||||
collisionPair.second.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
es.TriggerListenerHelper.getITriggerListener(collisionPair.second.entity, this._tempTriggerList);
|
||||
for (var i_2 = 0; i_2 < this._tempTriggerList.length; i_2++) {
|
||||
if (isEntering) {
|
||||
this._tempTriggerList[i_2].onTriggerEnter(collisionPair.first, collisionPair.second);
|
||||
@@ -6388,13 +6414,6 @@ var es;
|
||||
}
|
||||
return this._spatialHash.linecast(start, end, hits, layerMask);
|
||||
};
|
||||
/**
|
||||
* debug绘制空间散列的内容
|
||||
* @param secondsToDisplay
|
||||
*/
|
||||
Physics.debugDraw = function (secondsToDisplay) {
|
||||
this._spatialHash.debugDraw(secondsToDisplay, 2);
|
||||
};
|
||||
/** 调用reset并创建一个新的SpatialHash时使用的单元格大小 */
|
||||
Physics.spatialHashCellSize = 100;
|
||||
/** 接受layerMask的所有方法的默认值 */
|
||||
@@ -6449,7 +6468,7 @@ var es;
|
||||
/**
|
||||
* 用于返回冲突信息的共享HashSet
|
||||
*/
|
||||
this._tempHashSet = [];
|
||||
this._tempHashSet = new Set();
|
||||
this._cellSize = cellSize;
|
||||
this._inverseCellSize = 1 / this._cellSize;
|
||||
this._raycastParser = new RaycastResultParser();
|
||||
@@ -6474,8 +6493,7 @@ var es;
|
||||
for (var y = p1.y; y <= p2.y; y++) {
|
||||
// 如果没有单元格,我们需要创建它
|
||||
var c = this.cellAtPosition(x, y, true);
|
||||
if (!c.firstOrDefault(function (c) { return c == collider; }))
|
||||
c.push(collider);
|
||||
c.push(collider);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -6508,21 +6526,6 @@ var es;
|
||||
SpatialHash.prototype.clear = function () {
|
||||
this._cellDict.clear();
|
||||
};
|
||||
/**
|
||||
* debug绘制空间散列的内容
|
||||
* @param secondsToDisplay
|
||||
* @param textScale
|
||||
*/
|
||||
SpatialHash.prototype.debugDraw = function (secondsToDisplay, textScale) {
|
||||
if (textScale === void 0) { textScale = 1; }
|
||||
for (var x = this.gridBounds.x; x <= this.gridBounds.right; x++) {
|
||||
for (var y = this.gridBounds.y; y <= this.gridBounds.bottom; y++) {
|
||||
var cell = this.cellAtPosition(x, y);
|
||||
if (cell && cell.length > 0)
|
||||
this.debugDrawCellDetails(x, y, cell.length, secondsToDisplay, textScale);
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 返回边框与单元格相交的所有对象
|
||||
* @param bounds
|
||||
@@ -6530,7 +6533,7 @@ var es;
|
||||
* @param layerMask
|
||||
*/
|
||||
SpatialHash.prototype.aabbBroadphase = function (bounds, excludeCollider, layerMask) {
|
||||
this._tempHashSet.length = 0;
|
||||
this._tempHashSet.clear();
|
||||
var p1 = this.cellCoords(bounds.x, bounds.y);
|
||||
var p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||
for (var x = p1.x; x <= p2.x; x++) {
|
||||
@@ -6538,20 +6541,15 @@ var es;
|
||||
var cell = this.cellAtPosition(x, y);
|
||||
if (!cell)
|
||||
continue;
|
||||
var _loop_4 = function (i) {
|
||||
// 当cell不为空。循环并取回所有碰撞器
|
||||
for (var i = 0; i < cell.length; i++) {
|
||||
var collider = cell[i];
|
||||
// 如果它是自身或者如果它不匹配我们的层掩码 跳过这个碰撞器
|
||||
if (collider == excludeCollider || !es.Flags.isFlagSet(layerMask, collider.physicsLayer.value))
|
||||
return "continue";
|
||||
continue;
|
||||
if (bounds.intersects(collider.bounds)) {
|
||||
if (!this_3._tempHashSet.firstOrDefault(function (c) { return c == collider; }))
|
||||
this_3._tempHashSet.push(collider);
|
||||
this._tempHashSet.add(collider);
|
||||
}
|
||||
};
|
||||
var this_3 = this;
|
||||
// 当cell不为空。循环并取回所有碰撞器
|
||||
for (var i = 0; i < cell.length; i++) {
|
||||
_loop_4(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6626,7 +6624,7 @@ var es;
|
||||
this._overlapTestCircle.position = circleCenter;
|
||||
var resultCounter = 0;
|
||||
var potentials = this.aabbBroadphase(bounds, null, layerMask);
|
||||
for (var i = 0; i < potentials.length; i++) {
|
||||
for (var i = 0; i < potentials.size; i++) {
|
||||
var collider = potentials[i];
|
||||
if (collider instanceof es.BoxCollider) {
|
||||
results[resultCounter] = collider;
|
||||
@@ -6679,10 +6677,6 @@ var es;
|
||||
}
|
||||
return cell;
|
||||
};
|
||||
SpatialHash.prototype.debugDrawCellDetails = function (x, y, cellCount, secondsToDisplay, textScale) {
|
||||
if (secondsToDisplay === void 0) { secondsToDisplay = 0.5; }
|
||||
if (textScale === void 0) { textScale = 1; }
|
||||
};
|
||||
return SpatialHash;
|
||||
}());
|
||||
es.SpatialHash = SpatialHash;
|
||||
@@ -7719,7 +7713,7 @@ var ArrayUtils = /** @class */ (function () {
|
||||
};
|
||||
/**
|
||||
* 执行插入排序
|
||||
* @param ary
|
||||
* @param ary
|
||||
*/
|
||||
ArrayUtils.insertionSort = function (ary) {
|
||||
var len = ary.length;
|
||||
@@ -7733,9 +7727,9 @@ var ArrayUtils = /** @class */ (function () {
|
||||
};
|
||||
/**
|
||||
* 执行二分搜索
|
||||
* @param ary 搜索的数组(必须排序过)
|
||||
* @param value 需要搜索的值
|
||||
* @return 返回匹配结果的数组索引
|
||||
* @param ary 搜索的数组(必须排序过)
|
||||
* @param value 需要搜索的值
|
||||
* @returns 返回匹配结果的数组索引
|
||||
*/
|
||||
ArrayUtils.binarySearch = function (ary, value) {
|
||||
var startIndex = 0;
|
||||
@@ -7754,9 +7748,8 @@ var ArrayUtils = /** @class */ (function () {
|
||||
};
|
||||
/**
|
||||
* 返回匹配项的索引
|
||||
* @param ary
|
||||
* @param num
|
||||
* @return 返回匹配项的索引
|
||||
* @param ary
|
||||
* @param num
|
||||
*/
|
||||
ArrayUtils.findElementIndex = function (ary, num) {
|
||||
var len = ary.length;
|
||||
@@ -7768,8 +7761,7 @@ var ArrayUtils = /** @class */ (function () {
|
||||
};
|
||||
/**
|
||||
* 返回数组中最大值的索引
|
||||
* @param ary
|
||||
* @return 返回数组中最大值的索引
|
||||
* @param ary
|
||||
*/
|
||||
ArrayUtils.getMaxElementIndex = function (ary) {
|
||||
var matchIndex = 0;
|
||||
@@ -7782,8 +7774,7 @@ var ArrayUtils = /** @class */ (function () {
|
||||
};
|
||||
/**
|
||||
* 返回数组中最小值的索引
|
||||
* @param ary
|
||||
* @return 返回数组中最小值的索引
|
||||
* @param ary
|
||||
*/
|
||||
ArrayUtils.getMinElementIndex = function (ary) {
|
||||
var matchIndex = 0;
|
||||
@@ -7796,8 +7787,10 @@ var ArrayUtils = /** @class */ (function () {
|
||||
};
|
||||
/**
|
||||
* 返回一个"唯一性"数组
|
||||
* @param ary 需要唯一性的数组
|
||||
* @return 唯一性的数组
|
||||
* @param ary 需要唯一性的数组
|
||||
* @returns 唯一性的数组
|
||||
*
|
||||
* @tutorial
|
||||
* 比如: [1, 2, 2, 3, 4]
|
||||
* 返回: [1, 2, 3, 4]
|
||||
*/
|
||||
@@ -7865,7 +7858,7 @@ var ArrayUtils = /** @class */ (function () {
|
||||
};
|
||||
/**
|
||||
* 清除列表
|
||||
* @param ary 列表
|
||||
* @param ary
|
||||
*/
|
||||
ArrayUtils.clearList = function (ary) {
|
||||
if (!ary)
|
||||
@@ -7887,9 +7880,8 @@ var ArrayUtils = /** @class */ (function () {
|
||||
};
|
||||
/**
|
||||
* 判断2个数组是否相同
|
||||
* @param ary1 数组1
|
||||
* @param ary2 数组2
|
||||
* @return 是否相同
|
||||
* @param ary1 数组1
|
||||
* @param ary2 数组2
|
||||
*/
|
||||
ArrayUtils.equals = function (ary1, ary2) {
|
||||
if (ary1 == ary2)
|
||||
@@ -7905,9 +7897,10 @@ var ArrayUtils = /** @class */ (function () {
|
||||
};
|
||||
/**
|
||||
* 根据索引插入元素,索引和索引后的元素都向后移动一位
|
||||
* @param index 插入索引
|
||||
* @param value 插入的元素
|
||||
* @return 插入的元素 未插入则返回空
|
||||
* @param ary
|
||||
* @param index 插入索引
|
||||
* @param value 插入的元素
|
||||
* @returns 插入的元素 未插入则返回空
|
||||
*/
|
||||
ArrayUtils.insert = function (ary, index, value) {
|
||||
if (!ary)
|
||||
@@ -7929,6 +7922,61 @@ var ArrayUtils = /** @class */ (function () {
|
||||
}
|
||||
return value;
|
||||
};
|
||||
/**
|
||||
* 打乱数组 Fisher–Yates shuffle
|
||||
* @param list
|
||||
*/
|
||||
ArrayUtils.shuffle = function (list) {
|
||||
var n = list.length;
|
||||
while (n > 1) {
|
||||
n--;
|
||||
var k = RandomUtils.randint(0, n + 1);
|
||||
var value = list[k];
|
||||
list[k] = list[n];
|
||||
list[n] = value;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 如果项目已经在列表中,返回false,如果成功添加,返回true
|
||||
* @param list
|
||||
* @param item
|
||||
*/
|
||||
ArrayUtils.addIfNotPresent = function (list, item) {
|
||||
if (list.contains(item))
|
||||
return false;
|
||||
list.push(item);
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
* 返回列表中的最后一项。列表中至少应该有一个项目
|
||||
* @param list
|
||||
*/
|
||||
ArrayUtils.lastItem = function (list) {
|
||||
return list[list.length - 1];
|
||||
};
|
||||
/**
|
||||
* 从列表中随机获取一个项目。不清空检查列表!
|
||||
* @param list
|
||||
*/
|
||||
ArrayUtils.randomItem = function (list) {
|
||||
return list[RandomUtils.randint(0, list.length)];
|
||||
};
|
||||
/**
|
||||
* 从列表中随机获取物品。不清空检查列表,也不验证列表数是否大于项目数。返回的List可以通过ListPool.free放回池中
|
||||
* @param list
|
||||
* @param itemCount 从列表中返回的随机项目的数量
|
||||
*/
|
||||
ArrayUtils.randomItems = function (list, itemCount) {
|
||||
var set = new Set();
|
||||
while (set.size != itemCount) {
|
||||
var item = this.randomItem(list);
|
||||
if (!set.has(item))
|
||||
set.add(item);
|
||||
}
|
||||
var items = es.ListPool.obtain();
|
||||
set.forEach(function (value) { return items.push(value); });
|
||||
return items;
|
||||
};
|
||||
return ArrayUtils;
|
||||
}());
|
||||
var es;
|
||||
@@ -8640,7 +8688,6 @@ var es;
|
||||
*/
|
||||
RectangleExt.union = function (first, point) {
|
||||
var rect = new es.Rectangle(point.x, point.y, 0, 0);
|
||||
// let rectResult = first.union(rect);
|
||||
var result = new es.Rectangle();
|
||||
result.x = Math.min(first.x, rect.x);
|
||||
result.y = Math.min(first.y, rect.y);
|
||||
@@ -8850,6 +8897,18 @@ var es;
|
||||
es.Triangulator = Triangulator;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var TypeUtils = /** @class */ (function () {
|
||||
function TypeUtils() {
|
||||
}
|
||||
TypeUtils.getType = function (obj) {
|
||||
return obj["__proto__"]["constructor"];
|
||||
};
|
||||
return TypeUtils;
|
||||
}());
|
||||
es.TypeUtils = TypeUtils;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var Vector2Ext = /** @class */ (function () {
|
||||
function Vector2Ext() {
|
||||
|
||||
2
source/bin/framework.min.js
vendored
2
source/bin/framework.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -20,4 +20,26 @@ module es {
|
||||
*/
|
||||
onTriggerExit(other: Collider, local: Collider);
|
||||
}
|
||||
|
||||
export class TriggerListenerHelper {
|
||||
public static getITriggerListener(entity: Entity, components: ITriggerListener[]){
|
||||
for (let i = 0; i < entity.components._components.length; i++) {
|
||||
let component = entity.components._components.buffer[i];
|
||||
if (isITriggerListener(component)) {
|
||||
components.push(component);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < entity.components._componentsToAdd.length; i++) {
|
||||
let component = entity.components._componentsToAdd[i];
|
||||
if (isITriggerListener(component)) {
|
||||
components.push(component);
|
||||
}
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
}
|
||||
|
||||
export var isITriggerListener = (props: any): props is ITriggerListener => typeof (props as ITriggerListener)['onTriggerEnter'] !== 'undefined';
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ module es {
|
||||
bounds.y += motion.y;
|
||||
let neighbors = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers.value);
|
||||
|
||||
for (let j = 0; j < neighbors.length; j++) {
|
||||
for (let j = 0; j < neighbors.size; j++) {
|
||||
let neighbor = neighbors[j];
|
||||
// 不检测触发器
|
||||
if (neighbor.isTrigger)
|
||||
|
||||
@@ -28,7 +28,8 @@ module es {
|
||||
|
||||
// 获取任何可能在新位置发生碰撞的东西
|
||||
let neighbors = Physics.boxcastBroadphase(this._collider.bounds, this._collider.collidesWithLayers.value);
|
||||
for (let neighbor of neighbors){
|
||||
for (let i = 0; i < neighbors.size; i ++){
|
||||
let neighbor = neighbors[i];
|
||||
if (this._collider.overlaps(neighbor) && neighbor.enabled){
|
||||
didCollide = true;
|
||||
this.notifyTriggerListeners(this._collider, neighbor);
|
||||
@@ -40,14 +41,14 @@ module es {
|
||||
|
||||
private notifyTriggerListeners(self: Collider, other: Collider) {
|
||||
// 通知我们重叠的碰撞器实体上的任何侦听器
|
||||
other.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
TriggerListenerHelper.getITriggerListener(other.entity, this._tempTriggerList);
|
||||
for (let i = 0; i < this._tempTriggerList.length; i++) {
|
||||
this._tempTriggerList[i].onTriggerEnter(self, other);
|
||||
}
|
||||
this._tempTriggerList.length = 0;
|
||||
|
||||
// 通知此实体上的任何侦听器
|
||||
this.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
TriggerListenerHelper.getITriggerListener(this.entity, this._tempTriggerList);
|
||||
for (let i = 0; i < this._tempTriggerList.length; i++) {
|
||||
this._tempTriggerList[i].onTriggerEnter(other, self);
|
||||
}
|
||||
|
||||
@@ -204,7 +204,8 @@ module es {
|
||||
|
||||
}
|
||||
|
||||
protected async update() {
|
||||
protected async update(currentTime?: number) {
|
||||
if (currentTime != null) Time.update(currentTime);
|
||||
if (this._scene != null) {
|
||||
for (let i = this._globalManagers.length - 1; i >= 0; i--) {
|
||||
if (this._globalManagers[i].enabled)
|
||||
|
||||
@@ -335,7 +335,7 @@ module es {
|
||||
* @param type
|
||||
*/
|
||||
public getOrCreateComponent<T extends Component>(type: T) {
|
||||
let comp = this.components.getComponent<T>(type, true);
|
||||
let comp = this.components.getComponent<T>(TypeUtils.getType(type), true);
|
||||
if (!comp) {
|
||||
comp = this.addComponent<T>(type);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ module es {
|
||||
this._updatableComponents.remove(component);
|
||||
|
||||
if (Core.entitySystemsEnabled) {
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component["__proto__"]["constructor"]), false);
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)), false);
|
||||
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ module es {
|
||||
this._updatableComponents.add(component);
|
||||
|
||||
if (Core.entitySystemsEnabled) {
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component["__proto__"]["constructor"]));
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)));
|
||||
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
||||
}
|
||||
}
|
||||
@@ -128,7 +128,7 @@ module es {
|
||||
this._updatableComponents.add(component);
|
||||
|
||||
if (Core.entitySystemsEnabled) {
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component["__proto__"]["constructor"]));
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)));
|
||||
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ module es {
|
||||
this._updatableComponents.remove(component);
|
||||
|
||||
if (Core.entitySystemsEnabled) {
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component["__proto__"]["constructor"]), false);
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)), false);
|
||||
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ module es {
|
||||
*/
|
||||
export class ColliderTriggerHelper {
|
||||
private _entity: Entity;
|
||||
/** 存储当前帧中发生的所有活动交集对 */
|
||||
private _activeTriggerIntersections: Pair<Collider>[] = [];
|
||||
/** 存储前一帧的交叉对,以便我们可以在移动该帧后检测出口 */
|
||||
private _previousTriggerIntersections: Pair<Collider>[] = [];
|
||||
/** 存储当前帧中发生的所有活动交点对 */
|
||||
private _activeTriggerIntersections: Set<Pair<Collider>> = new Set();
|
||||
/** 存储前一帧的交点对,这样我们就可以在移动这一帧后检测到退出 */
|
||||
private _previousTriggerIntersections: Set<Pair<Collider>> = new Set();
|
||||
private _tempTriggerList: ITriggerListener[] = [];
|
||||
|
||||
constructor(entity: Entity) {
|
||||
@@ -15,32 +15,34 @@ module es {
|
||||
}
|
||||
|
||||
/**
|
||||
* 实体被移动后,应该调用更新。它会处理碰撞器重叠的任何itriggerlistener。
|
||||
* update应该在实体被移动后被调用,它将处理任何与Colllider重叠的ITriggerListeners。
|
||||
* 它将处理任何与Collider重叠的ITriggerListeners。
|
||||
*/
|
||||
public update() {
|
||||
// 对所有实体.colliders进行重叠检查,这些实体.colliders是触发器,与所有宽相碰撞器,无论是否触发器。
|
||||
// 任何重叠都会导致触发事件
|
||||
let colliders = this._entity.getComponents(Collider);
|
||||
for (let i = 0; i < colliders.length; i++) {
|
||||
let collider = colliders[i];
|
||||
|
||||
let neighbors = Physics.boxcastBroadphase(collider.bounds, collider.collidesWithLayers);
|
||||
for (let j = 0; j < neighbors.length; j++) {
|
||||
for (let j = 0; j < neighbors.size; j++) {
|
||||
let neighbor = neighbors[j];
|
||||
// 我们至少需要一个碰撞器作为触发器
|
||||
if (!collider.isTrigger && !neighbor.isTrigger)
|
||||
continue;
|
||||
|
||||
if (collider.overlaps(neighbor)) {
|
||||
let pair = new Pair<Collider>(collider, neighbor);
|
||||
let shouldReportTriggerEvent = this._activeTriggerIntersections.findIndex(value => {
|
||||
return value.first == pair.first && value.second == pair.second;
|
||||
}) == -1 && this._previousTriggerIntersections.findIndex(value => {
|
||||
return value.first == pair.first && value.second == pair.second;
|
||||
}) == -1;
|
||||
|
||||
// 如果我们的某一个集合中已经有了这个对子(前一个或当前的触发交叉点),就不要调用输入事件了
|
||||
let shouldReportTriggerEvent = !this._activeTriggerIntersections.has(pair) &&
|
||||
!this._previousTriggerIntersections.has(pair);
|
||||
|
||||
if (shouldReportTriggerEvent)
|
||||
this.notifyTriggerListeners(pair, true);
|
||||
|
||||
if (!this._activeTriggerIntersections.contains(pair))
|
||||
this._activeTriggerIntersections.push(pair);
|
||||
this._activeTriggerIntersections.add(pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,31 +53,42 @@ module es {
|
||||
}
|
||||
|
||||
private checkForExitedColliders() {
|
||||
for (let i = 0; i < this._activeTriggerIntersections.length; i++) {
|
||||
let index = this._previousTriggerIntersections.findIndex(value => {
|
||||
if (value.first == this._activeTriggerIntersections[i].first && value.second == this._activeTriggerIntersections[i].second)
|
||||
return true;
|
||||
// 删除所有与此帧交互的触发器,留下我们退出的触发器
|
||||
this.excepthWith(this._previousTriggerIntersections, this._activeTriggerIntersections);
|
||||
|
||||
return false;
|
||||
});
|
||||
if (index != -1)
|
||||
this._previousTriggerIntersections.removeAt(index);
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._previousTriggerIntersections.length; i++) {
|
||||
for (let i = 0; i < this._previousTriggerIntersections.size; i++) {
|
||||
this.notifyTriggerListeners(this._previousTriggerIntersections[i], false)
|
||||
}
|
||||
this._previousTriggerIntersections.length = 0;
|
||||
for (let i = 0; i < this._activeTriggerIntersections.length; i++) {
|
||||
if (!this._previousTriggerIntersections.contains(this._activeTriggerIntersections[i])) {
|
||||
this._previousTriggerIntersections.push(this._activeTriggerIntersections[i]);
|
||||
|
||||
this._previousTriggerIntersections.clear();
|
||||
|
||||
// 添加所有当前激活的触发器
|
||||
this.unionWith(this._previousTriggerIntersections, this._activeTriggerIntersections);
|
||||
|
||||
// 清空活动集,为下一帧做准备
|
||||
this._activeTriggerIntersections.clear();
|
||||
}
|
||||
|
||||
private excepthWith(previous: Set<Pair<Collider>>, active: Set<Pair<Collider>>){
|
||||
for (let i = 0; i < previous.size; i ++){
|
||||
let previousDATA: Pair<Collider> = previous[i];
|
||||
for (let j = 0; j < active.size; j ++){
|
||||
let activeDATA: Pair<Collider> = active[j];
|
||||
if (activeDATA.equals(previousDATA))
|
||||
previous.delete(previousDATA);
|
||||
}
|
||||
}
|
||||
this._activeTriggerIntersections.length = 0;
|
||||
}
|
||||
|
||||
private unionWith(previous: Set<Pair<Collider>>, active: Set<Pair<Collider>>) {
|
||||
for (let i = 0; i < this._activeTriggerIntersections.size; i ++) {
|
||||
if (!this._previousTriggerIntersections.has(this._activeTriggerIntersections[i]))
|
||||
this._previousTriggerIntersections.add(this._activeTriggerIntersections[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private notifyTriggerListeners(collisionPair: Pair<Collider>, isEntering: boolean) {
|
||||
collisionPair.first.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
TriggerListenerHelper.getITriggerListener(collisionPair.first.entity, this._tempTriggerList);
|
||||
for (let i = 0; i < this._tempTriggerList.length; i++) {
|
||||
if (isEntering) {
|
||||
this._tempTriggerList[i].onTriggerEnter(collisionPair.second, collisionPair.first);
|
||||
@@ -86,7 +99,7 @@ module es {
|
||||
this._tempTriggerList.length = 0;
|
||||
|
||||
if (collisionPair.second.entity) {
|
||||
collisionPair.second.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
TriggerListenerHelper.getITriggerListener(collisionPair.second.entity, this._tempTriggerList);
|
||||
for (let i = 0; i < this._tempTriggerList.length; i++) {
|
||||
if (isEntering) {
|
||||
this._tempTriggerList[i].onTriggerEnter(collisionPair.first, collisionPair.second);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
///<reference path="./RaycastHit.ts" />
|
||||
module es {
|
||||
export class Physics {
|
||||
public static _spatialHash: SpatialHash;
|
||||
/** 调用reset并创建一个新的SpatialHash时使用的单元格大小 */
|
||||
public static spatialHashCellSize = 100;
|
||||
/** 接受layerMask的所有方法的默认值 */
|
||||
public static readonly allLayers: number = -1;
|
||||
private static _spatialHash: SpatialHash;
|
||||
/**
|
||||
* raycast是否检测配置为触发器的碰撞器
|
||||
*/
|
||||
@@ -120,13 +120,5 @@ module es {
|
||||
|
||||
return this._spatialHash.linecast(start, end, hits, layerMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* debug绘制空间散列的内容
|
||||
* @param secondsToDisplay
|
||||
*/
|
||||
public static debugDraw(secondsToDisplay) {
|
||||
this._spatialHash.debugDraw(secondsToDisplay, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ module es {
|
||||
/**
|
||||
* 用于返回冲突信息的共享HashSet
|
||||
*/
|
||||
public _tempHashSet: Collider[] = [];
|
||||
public _tempHashSet: Set<Collider> = new Set<Collider>();
|
||||
|
||||
constructor(cellSize: number = 100) {
|
||||
this._cellSize = cellSize;
|
||||
@@ -53,8 +53,7 @@ module es {
|
||||
for (let y = p1.y; y <= p2.y; y++) {
|
||||
// 如果没有单元格,我们需要创建它
|
||||
let c: Collider[] = this.cellAtPosition(x, y, true);
|
||||
if (!c.firstOrDefault(c => c == collider))
|
||||
c.push(collider);
|
||||
c.push(collider);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,29 +91,14 @@ module es {
|
||||
this._cellDict.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* debug绘制空间散列的内容
|
||||
* @param secondsToDisplay
|
||||
* @param textScale
|
||||
*/
|
||||
public debugDraw(secondsToDisplay: number, textScale: number = 1) {
|
||||
for (let x = this.gridBounds.x; x <= this.gridBounds.right; x++) {
|
||||
for (let y = this.gridBounds.y; y <= this.gridBounds.bottom; y++) {
|
||||
let cell = this.cellAtPosition(x, y);
|
||||
if (cell && cell.length > 0)
|
||||
this.debugDrawCellDetails(x, y, cell.length, secondsToDisplay, textScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回边框与单元格相交的所有对象
|
||||
* @param bounds
|
||||
* @param excludeCollider
|
||||
* @param layerMask
|
||||
*/
|
||||
public aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number): Collider[] {
|
||||
this._tempHashSet.length = 0;
|
||||
public aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number): Set<Collider> {
|
||||
this._tempHashSet.clear();
|
||||
|
||||
let p1 = this.cellCoords(bounds.x, bounds.y);
|
||||
let p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||
@@ -134,8 +118,7 @@ module es {
|
||||
continue;
|
||||
|
||||
if (bounds.intersects(collider.bounds)) {
|
||||
if (!this._tempHashSet.firstOrDefault(c => c == collider))
|
||||
this._tempHashSet.push(collider);
|
||||
this._tempHashSet.add(collider);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,7 +209,7 @@ module es {
|
||||
|
||||
let resultCounter = 0;
|
||||
let potentials = this.aabbBroadphase(bounds, null, layerMask);
|
||||
for (let i = 0; i < potentials.length; i++) {
|
||||
for (let i = 0; i < potentials.size; i++) {
|
||||
let collider = potentials[i];
|
||||
if (collider instanceof BoxCollider) {
|
||||
results[resultCounter] = collider;
|
||||
@@ -258,7 +241,7 @@ module es {
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
private cellCoords(x: number, y: number): Vector2 {
|
||||
public cellCoords(x: number, y: number): Vector2 {
|
||||
return new Vector2(Math.floor(x * this._inverseCellSize), Math.floor(y * this._inverseCellSize));
|
||||
}
|
||||
|
||||
@@ -269,7 +252,7 @@ module es {
|
||||
* @param y
|
||||
* @param createCellIfEmpty
|
||||
*/
|
||||
private cellAtPosition(x: number, y: number, createCellIfEmpty: boolean = false): Collider[] {
|
||||
public cellAtPosition(x: number, y: number, createCellIfEmpty: boolean = false): Collider[] {
|
||||
let cell: Collider[] = this._cellDict.tryGetValue(x, y);
|
||||
if (!cell) {
|
||||
if (createCellIfEmpty) {
|
||||
@@ -279,10 +262,6 @@ module es {
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
private debugDrawCellDetails(x: number, y: number, cellCount: number, secondsToDisplay = 0.5, textScale = 1) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,10 +21,9 @@ class ArrayUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 执行插入排序
|
||||
* @param ary
|
||||
* @param ary
|
||||
*/
|
||||
public static insertionSort(ary: number[]): void {
|
||||
let len: number = ary.length;
|
||||
@@ -39,9 +38,9 @@ class ArrayUtils {
|
||||
|
||||
/**
|
||||
* 执行二分搜索
|
||||
* @param ary 搜索的数组(必须排序过)
|
||||
* @param value 需要搜索的值
|
||||
* @return 返回匹配结果的数组索引
|
||||
* @param ary 搜索的数组(必须排序过)
|
||||
* @param value 需要搜索的值
|
||||
* @returns 返回匹配结果的数组索引
|
||||
*/
|
||||
public static binarySearch(ary: number[], value: number): number {
|
||||
let startIndex: number = 0;
|
||||
@@ -59,9 +58,8 @@ class ArrayUtils {
|
||||
|
||||
/**
|
||||
* 返回匹配项的索引
|
||||
* @param ary
|
||||
* @param num
|
||||
* @return 返回匹配项的索引
|
||||
* @param ary
|
||||
* @param num
|
||||
*/
|
||||
public static findElementIndex(ary: any[], num: any): any {
|
||||
let len: number = ary.length;
|
||||
@@ -74,8 +72,7 @@ class ArrayUtils {
|
||||
|
||||
/**
|
||||
* 返回数组中最大值的索引
|
||||
* @param ary
|
||||
* @return 返回数组中最大值的索引
|
||||
* @param ary
|
||||
*/
|
||||
public static getMaxElementIndex(ary: number[]): number {
|
||||
let matchIndex: number = 0;
|
||||
@@ -89,8 +86,7 @@ class ArrayUtils {
|
||||
|
||||
/**
|
||||
* 返回数组中最小值的索引
|
||||
* @param ary
|
||||
* @return 返回数组中最小值的索引
|
||||
* @param ary
|
||||
*/
|
||||
public static getMinElementIndex(ary: number[]): number {
|
||||
let matchIndex: number = 0;
|
||||
@@ -104,8 +100,10 @@ class ArrayUtils {
|
||||
|
||||
/**
|
||||
* 返回一个"唯一性"数组
|
||||
* @param ary 需要唯一性的数组
|
||||
* @return 唯一性的数组
|
||||
* @param ary 需要唯一性的数组
|
||||
* @returns 唯一性的数组
|
||||
*
|
||||
* @tutorial
|
||||
* 比如: [1, 2, 2, 3, 4]
|
||||
* 返回: [1, 2, 3, 4]
|
||||
*/
|
||||
@@ -177,7 +175,7 @@ class ArrayUtils {
|
||||
|
||||
/**
|
||||
* 清除列表
|
||||
* @param ary 列表
|
||||
* @param ary
|
||||
*/
|
||||
public static clearList(ary: any[]): void {
|
||||
if (!ary) return;
|
||||
@@ -197,12 +195,10 @@ class ArrayUtils {
|
||||
return ary.slice(0, ary.length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断2个数组是否相同
|
||||
* @param ary1 数组1
|
||||
* @param ary2 数组2
|
||||
* @return 是否相同
|
||||
* @param ary1 数组1
|
||||
* @param ary2 数组2
|
||||
*/
|
||||
public static equals(ary1: number[], ary2: number[]): Boolean {
|
||||
if (ary1 == ary2) return true;
|
||||
@@ -215,12 +211,12 @@ class ArrayUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据索引插入元素,索引和索引后的元素都向后移动一位
|
||||
* @param index 插入索引
|
||||
* @param value 插入的元素
|
||||
* @return 插入的元素 未插入则返回空
|
||||
* @param ary
|
||||
* @param index 插入索引
|
||||
* @param value 插入的元素
|
||||
* @returns 插入的元素 未插入则返回空
|
||||
*/
|
||||
public static insert(ary: any[], index: number, value: any): any {
|
||||
if (!ary) return null;
|
||||
@@ -237,4 +233,66 @@ class ArrayUtils {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打乱数组 Fisher–Yates shuffle
|
||||
* @param list
|
||||
*/
|
||||
public static shuffle<T>(list: T[]) {
|
||||
let n = list.length;
|
||||
while (n > 1) {
|
||||
n--;
|
||||
let k = RandomUtils.randint(0, n + 1);
|
||||
let value: T = list[k];
|
||||
list[k] = list[n];
|
||||
list[n] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果项目已经在列表中,返回false,如果成功添加,返回true
|
||||
* @param list
|
||||
* @param item
|
||||
*/
|
||||
public static addIfNotPresent<T>(list: T[], item: T) {
|
||||
if (list.contains(item))
|
||||
return false;
|
||||
|
||||
list.push(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回列表中的最后一项。列表中至少应该有一个项目
|
||||
* @param list
|
||||
*/
|
||||
public static lastItem<T>(list: T[]) {
|
||||
return list[list.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* 从列表中随机获取一个项目。不清空检查列表!
|
||||
* @param list
|
||||
*/
|
||||
public static randomItem<T>(list: T[]) {
|
||||
return list[RandomUtils.randint(0, list.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* 从列表中随机获取物品。不清空检查列表,也不验证列表数是否大于项目数。返回的List可以通过ListPool.free放回池中
|
||||
* @param list
|
||||
* @param itemCount 从列表中返回的随机项目的数量
|
||||
*/
|
||||
public static randomItems<T>(list: T[], itemCount: number){
|
||||
let set = new Set<T>();
|
||||
while (set.size != itemCount) {
|
||||
let item = this.randomItem(list);
|
||||
if (!set.has(item))
|
||||
set.add(item);
|
||||
}
|
||||
|
||||
let items = es.ListPool.obtain<T>();
|
||||
set.forEach(value => items.push(value));
|
||||
return items;
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ module es {
|
||||
*/
|
||||
public static union(first: Rectangle, point: Vector2) {
|
||||
let rect = new Rectangle(point.x, point.y, 0, 0);
|
||||
// let rectResult = first.union(rect);
|
||||
let result = new Rectangle();
|
||||
result.x = Math.min(first.x, rect.x);
|
||||
result.y = Math.min(first.y, rect.y);
|
||||
|
||||
7
source/src/Utils/TypeUtils.ts
Normal file
7
source/src/Utils/TypeUtils.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
module es {
|
||||
export class TypeUtils {
|
||||
public static getType(obj: any){
|
||||
return obj["__proto__"]["constructor"];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user