完善 colliderTriggerHelper 用于更新碰撞信息
This commit is contained in:
@@ -1,21 +1,89 @@
|
||||
class ColliderTriggerHelper {
|
||||
private _entity: Entity;
|
||||
/** 存储当前帧中发生的所有活动交集对 */
|
||||
private _activeTriggerIntersections: Pair<Collider>[] = [];
|
||||
/** 存储前一帧的交叉对,以便我们可以在移动该帧后检测出口 */
|
||||
private _previousTriggerIntersections: Pair<Collider>[] = [];
|
||||
private _tempTriggerList: ITriggerListener[] = [];
|
||||
|
||||
constructor(entity: Entity) {
|
||||
this._entity = entity;
|
||||
}
|
||||
|
||||
public update(){
|
||||
let colliders = this._entity.getComponents<Collider>(Collider);
|
||||
for (let i = 0; i < colliders.length; i ++){
|
||||
/**
|
||||
* 实体被移动后,应该调用更新。它会处理碰撞器重叠的任何itriggerlistener。
|
||||
*/
|
||||
public update() {
|
||||
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 i = 0; i < neighbors.length; i ++){
|
||||
for (let i = 0; i < neighbors.length; i++) {
|
||||
let neighbor = neighbors[i];
|
||||
if (!collider.isTrigger && !neighbor.isTrigger)
|
||||
continue;
|
||||
|
||||
if (collider.overlaps(neighbor)){
|
||||
|
||||
if (collider.overlaps(neighbor)) {
|
||||
let pair = new Pair<Collider>(collider, neighbor);
|
||||
let shouldReportTriggerEvent = !this._activeTriggerIntersections.contains(pair) &&
|
||||
!this._previousTriggerIntersections.contains(pair);
|
||||
|
||||
if (shouldReportTriggerEvent)
|
||||
this.notifyTriggerListeners(pair, true);
|
||||
|
||||
this._activeTriggerIntersections.push(pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListPool.free(colliders);
|
||||
|
||||
this.checkForExitedColliders();
|
||||
}
|
||||
|
||||
private checkForExitedColliders(){
|
||||
let tempIntersections = [];
|
||||
this._previousTriggerIntersections = this._previousTriggerIntersections.filter(value => {
|
||||
for (let i = 0; i < this._activeTriggerIntersections.length; i ++){
|
||||
if (value == this._activeTriggerIntersections[i]){
|
||||
tempIntersections.push(value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
this._previousTriggerIntersections.forEach(pair => this.notifyTriggerListeners(pair, false));
|
||||
this._previousTriggerIntersections.length = 0;
|
||||
tempIntersections.forEach(value => this._previousTriggerIntersections.push(value));
|
||||
this._activeTriggerIntersections.length = 0;
|
||||
}
|
||||
|
||||
private notifyTriggerListeners(collisionPair: Pair<Collider>, isEntering: boolean) {
|
||||
collisionPair.first.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
for (let i = 0; i < this._tempTriggerList.length; i ++){
|
||||
if (isEntering){
|
||||
this._tempTriggerList[i].onTriggerEnter(collisionPair.second, collisionPair.first);
|
||||
} else {
|
||||
this._tempTriggerList[i].onTriggerExit(collisionPair.second, collisionPair.first);
|
||||
}
|
||||
|
||||
this._tempTriggerList.length = 0;
|
||||
|
||||
if (collisionPair.second.entity){
|
||||
collisionPair.second.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
for (let i = 0; i < this._tempTriggerList.length; i ++){
|
||||
if (isEntering){
|
||||
this._tempTriggerList[i].onTriggerEnter(collisionPair.first, collisionPair.second);
|
||||
} else {
|
||||
this._tempTriggerList[i].onTriggerExit(collisionPair.first, collisionPair.second);
|
||||
}
|
||||
}
|
||||
|
||||
this._tempTriggerList.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
class ShapeCollisions {
|
||||
/**
|
||||
* 检查两个多边形之间的碰撞
|
||||
* @param first
|
||||
* @param second
|
||||
*/
|
||||
public static polygonToPolygon(first: Polygon, second: Polygon) {
|
||||
let result = new CollisionResult();
|
||||
let isIntersecting = true;
|
||||
@@ -56,6 +61,13 @@ class ShapeCollisions {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算[minA, maxA]和[minB, maxB]之间的距离。如果间隔重叠,距离是负的
|
||||
* @param minA
|
||||
* @param maxA
|
||||
* @param minB
|
||||
* @param maxB
|
||||
*/
|
||||
public static intervalDistance(minA: number, maxA: number, minB: number, maxB) {
|
||||
if (minA < minB)
|
||||
return minB - maxA;
|
||||
@@ -63,6 +75,13 @@ class ShapeCollisions {
|
||||
return minA - minB;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算一个多边形在一个轴上的投影,并返回一个[min,max]区间
|
||||
* @param axis
|
||||
* @param polygon
|
||||
* @param min
|
||||
* @param max
|
||||
*/
|
||||
public static getInterval(axis: Vector2, polygon: Polygon, min: number, max: number) {
|
||||
let dot = Vector2.dot(polygon.points[0], axis);
|
||||
min = max = dot;
|
||||
@@ -79,6 +98,11 @@ class ShapeCollisions {
|
||||
return { min: min, max: max };
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param circle
|
||||
* @param polygon
|
||||
*/
|
||||
public static circleToPolygon(circle: Circle, polygon: Polygon) {
|
||||
let result = new CollisionResult();
|
||||
|
||||
@@ -111,6 +135,11 @@ class ShapeCollisions {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 适用于圆心在方框内以及只与方框外圆心重叠的圆。
|
||||
* @param circle
|
||||
* @param box
|
||||
*/
|
||||
public static circleToBox(circle: Circle, box: Box): CollisionResult {
|
||||
let result = new CollisionResult();
|
||||
let closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position).res;
|
||||
@@ -139,6 +168,11 @@ class ShapeCollisions {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param point
|
||||
* @param circle
|
||||
*/
|
||||
public static pointToCircle(point: Vector2, circle: Circle) {
|
||||
let result = new CollisionResult();
|
||||
|
||||
@@ -157,6 +191,12 @@ class ShapeCollisions {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param lineA
|
||||
* @param lineB
|
||||
* @param closestTo
|
||||
*/
|
||||
public static closestPointOnLine(lineA: Vector2, lineB: Vector2, closestTo: Vector2) {
|
||||
let v = Vector2.subtract(lineB, lineA);
|
||||
let w = Vector2.subtract(closestTo, lineA);
|
||||
@@ -166,6 +206,11 @@ class ShapeCollisions {
|
||||
return Vector2.add(lineA, Vector2.multiply(v, new Vector2(t, t)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param point
|
||||
* @param poly
|
||||
*/
|
||||
public static pointToPoly(point: Vector2, poly: Polygon) {
|
||||
let result = new CollisionResult();
|
||||
|
||||
@@ -185,6 +230,11 @@ class ShapeCollisions {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param first
|
||||
* @param second
|
||||
*/
|
||||
public static circleToCircle(first: Circle, second: Circle){
|
||||
let result = new CollisionResult();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user