2020-08-22 12:21:40 +08:00
|
|
|
|
///<reference path="./RaycastHit.ts" />
|
2020-07-23 11:00:46 +08:00
|
|
|
|
module es {
|
|
|
|
|
|
export class Physics {
|
2020-11-26 17:26:49 +08:00
|
|
|
|
public static _spatialHash: SpatialHash;
|
2020-12-07 11:48:42 +08:00
|
|
|
|
/** 用于在全局范围内存储重力值的方便字段 */
|
2021-05-27 18:32:38 +08:00
|
|
|
|
public static gravity = new Vector2(0, -300);
|
2020-07-23 11:00:46 +08:00
|
|
|
|
/** 调用reset并创建一个新的SpatialHash时使用的单元格大小 */
|
|
|
|
|
|
public static spatialHashCellSize = 100;
|
|
|
|
|
|
/** 接受layerMask的所有方法的默认值 */
|
|
|
|
|
|
public static readonly allLayers: number = -1;
|
2020-07-31 19:33:04 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* raycast是否检测配置为触发器的碰撞器
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static raycastsHitTriggers: boolean = false;
|
2020-08-03 14:45:57 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 在碰撞器中开始的射线/直线是否强制转换检测到那些碰撞器
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static raycastsStartInColliders = false;
|
2020-08-22 12:21:40 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 我们保留它以避免在每次raycast发生时分配它
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static _hitArray: RaycastHit[] = [
|
|
|
|
|
|
new RaycastHit()
|
|
|
|
|
|
];
|
2020-12-15 11:46:33 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 避免重叠检查和形状投射的分配
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static _colliderArray: Collider[] = [
|
|
|
|
|
|
null
|
|
|
|
|
|
];
|
2020-06-12 20:24:51 +08:00
|
|
|
|
|
2020-07-28 16:25:20 +08:00
|
|
|
|
public static reset() {
|
2020-07-23 11:00:46 +08:00
|
|
|
|
this._spatialHash = new SpatialHash(this.spatialHashCellSize);
|
2020-11-26 10:39:32 +08:00
|
|
|
|
this._hitArray[0].reset();
|
2020-12-15 11:46:33 +08:00
|
|
|
|
this._colliderArray[0] = null;
|
2020-07-23 11:00:46 +08:00
|
|
|
|
}
|
2020-06-16 11:59:40 +08:00
|
|
|
|
|
2020-07-23 11:00:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 从SpatialHash中移除所有碰撞器
|
|
|
|
|
|
*/
|
2020-07-28 16:25:20 +08:00
|
|
|
|
public static clear() {
|
2020-07-23 11:00:46 +08:00
|
|
|
|
this._spatialHash.clear();
|
|
|
|
|
|
}
|
2020-06-21 10:27:15 +08:00
|
|
|
|
|
2021-05-27 18:32:38 +08:00
|
|
|
|
public static debugDraw(secondsToDisplay) {
|
|
|
|
|
|
this._spatialHash.debugDraw(secondsToDisplay);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-07-27 16:10:36 +08:00
|
|
|
|
/**
|
2020-12-15 11:46:33 +08:00
|
|
|
|
* 检查是否有对撞机落在一个圆形区域内。返回遇到的第一个对撞机
|
|
|
|
|
|
* @param center
|
|
|
|
|
|
* @param radius
|
|
|
|
|
|
* @param layerMask
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static overlapCircle(center: Vector2, radius: number, layerMask: number = Physics.allLayers) {
|
|
|
|
|
|
this._colliderArray[0] = null;
|
|
|
|
|
|
this._spatialHash.overlapCircle(center, radius, this._colliderArray, layerMask);
|
|
|
|
|
|
return this._colliderArray[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取所有落在指定圆圈内的碰撞器
|
2020-07-27 16:10:36 +08:00
|
|
|
|
* @param center
|
|
|
|
|
|
* @param randius
|
|
|
|
|
|
* @param results
|
|
|
|
|
|
* @param layerMask
|
|
|
|
|
|
*/
|
2020-07-28 16:25:20 +08:00
|
|
|
|
public static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask = -1) {
|
|
|
|
|
|
if (results.length == 0) {
|
2020-12-15 11:46:33 +08:00
|
|
|
|
console.warn("传入了一个空的结果数组。不会返回任何结果");
|
2020-07-27 16:10:36 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-07-23 11:00:46 +08:00
|
|
|
|
return this._spatialHash.overlapCircle(center, randius, results, layerMask);
|
|
|
|
|
|
}
|
2020-06-15 08:46:38 +08:00
|
|
|
|
|
2020-07-27 16:10:36 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 返回所有碰撞器与边界相交的碰撞器。bounds。请注意,这是一个broadphase检查,所以它只检查边界,不做单个碰撞到碰撞器的检查!
|
|
|
|
|
|
* @param rect
|
|
|
|
|
|
* @param layerMask
|
|
|
|
|
|
*/
|
2020-07-28 16:25:20 +08:00
|
|
|
|
public static boxcastBroadphase(rect: Rectangle, layerMask: number = this.allLayers) {
|
2020-07-27 16:10:36 +08:00
|
|
|
|
return this._spatialHash.aabbBroadphase(rect, null, layerMask);
|
2020-07-23 11:00:46 +08:00
|
|
|
|
}
|
2020-06-15 10:42:06 +08:00
|
|
|
|
|
2020-07-27 16:10:36 +08:00
|
|
|
|
/**
|
2020-12-15 11:46:33 +08:00
|
|
|
|
* 返回所有被边界交错的碰撞器,但不包括传入的碰撞器(self)。
|
|
|
|
|
|
* 如果你想为其他查询自己创建扫描边界,这个方法很有用
|
2020-07-27 16:10:36 +08:00
|
|
|
|
* @param collider
|
|
|
|
|
|
* @param rect
|
|
|
|
|
|
* @param layerMask
|
|
|
|
|
|
*/
|
2020-07-28 16:25:20 +08:00
|
|
|
|
public static boxcastBroadphaseExcludingSelf(collider: Collider, rect: Rectangle, layerMask = this.allLayers) {
|
2020-07-23 11:00:46 +08:00
|
|
|
|
return this._spatialHash.aabbBroadphase(rect, collider, layerMask);
|
|
|
|
|
|
}
|
2020-06-16 11:22:37 +08:00
|
|
|
|
|
2020-12-07 11:48:42 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 返回所有边界与 collider.bounds 相交的碰撞器,但不包括传入的碰撞器(self)
|
|
|
|
|
|
* @param collider
|
|
|
|
|
|
* @param layerMask
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static boxcastBroadphaseExcludingSelfNonRect(collider: Collider, layerMask = this.allLayers) {
|
2021-05-28 08:41:38 +08:00
|
|
|
|
let bounds = collider.bounds;
|
2020-12-07 11:48:42 +08:00
|
|
|
|
return this._spatialHash.aabbBroadphase(bounds, collider, layerMask);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-12-15 11:46:33 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 返回所有被 collider.bounds 扩展为包含 deltaX/deltaY 的碰撞器,但不包括传入的碰撞器(self)
|
|
|
|
|
|
* @param collider
|
|
|
|
|
|
* @param deltaX
|
|
|
|
|
|
* @param deltaY
|
|
|
|
|
|
* @param layerMask
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static boxcastBroadphaseExcludingSelfDelta(collider: Collider, deltaX: number, deltaY: number, layerMask: number = Physics.allLayers) {
|
2021-05-28 08:41:38 +08:00
|
|
|
|
let colliderBounds = collider.bounds;
|
2020-12-15 11:46:33 +08:00
|
|
|
|
let sweptBounds = colliderBounds.getSweptBroadphaseBounds(deltaX, deltaY);
|
|
|
|
|
|
return this._spatialHash.aabbBroadphase(sweptBounds, collider, layerMask);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-07-23 11:00:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将对撞机添加到物理系统中
|
|
|
|
|
|
* @param collider
|
|
|
|
|
|
*/
|
2020-07-28 16:25:20 +08:00
|
|
|
|
public static addCollider(collider: Collider) {
|
2020-07-23 11:00:46 +08:00
|
|
|
|
Physics._spatialHash.register(collider);
|
|
|
|
|
|
}
|
2020-06-15 20:08:21 +08:00
|
|
|
|
|
2020-07-23 11:00:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 从物理系统中移除对撞机
|
|
|
|
|
|
* @param collider
|
|
|
|
|
|
*/
|
2020-07-28 16:25:20 +08:00
|
|
|
|
public static removeCollider(collider: Collider) {
|
2020-07-23 11:00:46 +08:00
|
|
|
|
Physics._spatialHash.remove(collider);
|
|
|
|
|
|
}
|
2020-06-15 20:08:21 +08:00
|
|
|
|
|
2020-07-23 11:00:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 更新物理系统中对撞机的位置。这实际上只是移除然后重新添加带有新边界的碰撞器
|
|
|
|
|
|
* @param collider
|
|
|
|
|
|
*/
|
2020-07-28 16:25:20 +08:00
|
|
|
|
public static updateCollider(collider: Collider) {
|
2020-07-23 11:00:46 +08:00
|
|
|
|
this._spatialHash.remove(collider);
|
|
|
|
|
|
this._spatialHash.register(collider);
|
|
|
|
|
|
}
|
2020-07-09 16:16:04 +08:00
|
|
|
|
|
2020-08-22 12:21:40 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 返回与layerMask匹配的碰撞器的第一次命中
|
|
|
|
|
|
* @param start
|
|
|
|
|
|
* @param end
|
|
|
|
|
|
* @param layerMask
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static linecast(start: Vector2, end: Vector2, layerMask: number = Physics.allLayers): RaycastHit{
|
|
|
|
|
|
this._hitArray[0].reset();
|
|
|
|
|
|
this.linecastAll(start, end, this._hitArray, layerMask);
|
|
|
|
|
|
return this._hitArray[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 通过空间散列强制执行一行,并用该行命中的任何碰撞器填充hits数组
|
|
|
|
|
|
* @param start
|
|
|
|
|
|
* @param end
|
|
|
|
|
|
* @param hits
|
|
|
|
|
|
* @param layerMask
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static linecastAll(start: Vector2, end: Vector2, hits: RaycastHit[], layerMask: number = Physics.allLayers){
|
|
|
|
|
|
if (hits.length == 0){
|
|
|
|
|
|
console.warn("传入了一个空的hits数组。没有点击会被返回");
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return this._spatialHash.linecast(start, end, hits, layerMask);
|
|
|
|
|
|
}
|
2020-12-15 11:46:33 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查是否有对撞机落在一个矩形区域中
|
|
|
|
|
|
* @param rect
|
|
|
|
|
|
* @param layerMask
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static overlapRectangle(rect: Rectangle, layerMask: number = Physics.allLayers) {
|
|
|
|
|
|
this._colliderArray[0] = null;
|
|
|
|
|
|
this._spatialHash.overlapRectangle(rect, this._colliderArray, layerMask);
|
|
|
|
|
|
return this._colliderArray[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取所有在指定矩形范围内的碰撞器
|
|
|
|
|
|
* @param rect
|
|
|
|
|
|
* @param results
|
|
|
|
|
|
* @param layerMask
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static overlapRectangleAll(rect: Rectangle, results: Collider[], layerMask: number = Physics.allLayers) {
|
|
|
|
|
|
if (results.length == 0){
|
|
|
|
|
|
console.warn("传入了一个空的结果数组。不会返回任何结果");
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
return this._spatialHash.overlapRectangle(rect, results, layerMask);
|
|
|
|
|
|
}
|
2020-07-09 16:16:04 +08:00
|
|
|
|
}
|
2020-07-23 11:00:46 +08:00
|
|
|
|
}
|