新增Out类
This commit is contained in:
Vendored
+35
-29
@@ -1282,7 +1282,7 @@ declare module es {
|
|||||||
* @param motion
|
* @param motion
|
||||||
* @param collisionResult
|
* @param collisionResult
|
||||||
*/
|
*/
|
||||||
calculateMovement(motion: Vector2, collisionResult: CollisionResult): boolean;
|
calculateMovement(motion: Vector2, collisionResult: Out<CollisionResult>): boolean;
|
||||||
/**
|
/**
|
||||||
* 将calculatemomovement应用到实体并更新triggerHelper
|
* 将calculatemomovement应用到实体并更新triggerHelper
|
||||||
* @param motion
|
* @param motion
|
||||||
@@ -1293,7 +1293,7 @@ declare module es {
|
|||||||
* @param motion
|
* @param motion
|
||||||
* @param collisionResult
|
* @param collisionResult
|
||||||
*/
|
*/
|
||||||
move(motion: Vector2, collisionResult: CollisionResult): boolean;
|
move(motion: Vector2, collisionResult: Out<CollisionResult>): boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
@@ -1409,25 +1409,25 @@ declare module es {
|
|||||||
* @param motion
|
* @param motion
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
collidesWith(collider: Collider, motion: Vector2, result?: CollisionResult): boolean;
|
collidesWith(collider: Collider, motion: Vector2, result: Out<CollisionResult>): boolean;
|
||||||
/**
|
/**
|
||||||
* 检查这个对撞机是否与对撞机发生碰撞。如果碰撞,则返回true,结果将被填充
|
* 检查这个对撞机是否与对撞机发生碰撞。如果碰撞,则返回true,结果将被填充
|
||||||
* @param collider
|
* @param collider
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
collidesWithNonMotion(collider: Collider, result?: CollisionResult): boolean;
|
collidesWithNonMotion(collider: Collider, result: Out<CollisionResult>): boolean;
|
||||||
/**
|
/**
|
||||||
* 检查此碰撞器是否已应用运动(增量运动矢量)与任何碰撞器发生碰撞。
|
* 检查此碰撞器是否已应用运动(增量运动矢量)与任何碰撞器发生碰撞。
|
||||||
* 如果是这样,则将返回true,并且将使用碰撞数据填充结果。 运动将设置为碰撞器在碰撞之前可以行进的最大距离。
|
* 如果是这样,则将返回true,并且将使用碰撞数据填充结果。 运动将设置为碰撞器在碰撞之前可以行进的最大距离。
|
||||||
* @param motion
|
* @param motion
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
collidesWithAny(motion: Vector2, result: CollisionResult): boolean;
|
collidesWithAny(motion: Vector2, result: Out<CollisionResult>): boolean;
|
||||||
/**
|
/**
|
||||||
* 检查此碰撞器是否与场景中的其他碰撞器碰撞。它相交的第一个碰撞器将在碰撞结果中返回碰撞数据。
|
* 检查此碰撞器是否与场景中的其他碰撞器碰撞。它相交的第一个碰撞器将在碰撞结果中返回碰撞数据。
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
collidesWithAnyNonMotion(result?: CollisionResult): boolean;
|
collidesWithAnyNonMotion(result: Out<CollisionResult>): boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
@@ -3053,7 +3053,7 @@ declare module es {
|
|||||||
* @param edgeNormal
|
* @param edgeNormal
|
||||||
* @returns 矩形边框上离点最近的点
|
* @returns 矩形边框上离点最近的点
|
||||||
*/
|
*/
|
||||||
getClosestPointOnRectangleBorderToPoint(point: Vector2, edgeNormal: Vector2): Vector2;
|
getClosestPointOnRectangleBorderToPoint(point: Vector2, edgeNormal: Out<Vector2>): Vector2;
|
||||||
/**
|
/**
|
||||||
* 创建一个新的RectangleF,该RectangleF包含两个其他矩形的重叠区域
|
* 创建一个新的RectangleF,该RectangleF包含两个其他矩形的重叠区域
|
||||||
* @param value1
|
* @param value1
|
||||||
@@ -3526,10 +3526,10 @@ declare module es {
|
|||||||
bounds: Rectangle;
|
bounds: Rectangle;
|
||||||
abstract recalculateBounds(collider: Collider): any;
|
abstract recalculateBounds(collider: Collider): any;
|
||||||
abstract overlaps(other: Shape): boolean;
|
abstract overlaps(other: Shape): boolean;
|
||||||
abstract collidesWithShape(other: Shape, collisionResult: CollisionResult): boolean;
|
abstract collidesWithShape(other: Shape, collisionResult: Out<CollisionResult>): boolean;
|
||||||
abstract collidesWithLine(start: Vector2, end: Vector2, hit: RaycastHit): boolean;
|
abstract collidesWithLine(start: Vector2, end: Vector2, hit: Out<RaycastHit>): boolean;
|
||||||
abstract containsPoint(point: Vector2): any;
|
abstract containsPoint(point: Vector2): any;
|
||||||
abstract pointCollidesWithShape(point: Vector2, result: CollisionResult): boolean;
|
abstract pointCollidesWithShape(point: Vector2, result: Out<CollisionResult>): boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
@@ -3627,15 +3627,15 @@ declare module es {
|
|||||||
static rotatePolygonVerts(radians: number, originalPoints: Vector2[], rotatedPoints: Vector2[]): void;
|
static rotatePolygonVerts(radians: number, originalPoints: Vector2[], rotatedPoints: Vector2[]): void;
|
||||||
recalculateBounds(collider: Collider): void;
|
recalculateBounds(collider: Collider): void;
|
||||||
overlaps(other: Shape): any;
|
overlaps(other: Shape): any;
|
||||||
collidesWithShape(other: Shape, result: CollisionResult): boolean;
|
collidesWithShape(other: Shape, result: Out<CollisionResult>): boolean;
|
||||||
collidesWithLine(start: es.Vector2, end: es.Vector2, hit: es.RaycastHit): boolean;
|
collidesWithLine(start: Vector2, end: Vector2, hit: Out<RaycastHit>): boolean;
|
||||||
/**
|
/**
|
||||||
* 本质上,这个算法所做的就是从一个点发射一条射线。
|
* 本质上,这个算法所做的就是从一个点发射一条射线。
|
||||||
* 如果它与奇数条多边形边相交,我们就知道它在多边形内部。
|
* 如果它与奇数条多边形边相交,我们就知道它在多边形内部。
|
||||||
* @param point
|
* @param point
|
||||||
*/
|
*/
|
||||||
containsPoint(point: Vector2): boolean;
|
containsPoint(point: Vector2): boolean;
|
||||||
pointCollidesWithShape(point: Vector2, result: CollisionResult): boolean;
|
pointCollidesWithShape(point: Vector2, result: Out<CollisionResult>): boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
@@ -3659,9 +3659,9 @@ declare module es {
|
|||||||
*/
|
*/
|
||||||
updateBox(width: number, height: number): void;
|
updateBox(width: number, height: number): void;
|
||||||
overlaps(other: Shape): any;
|
overlaps(other: Shape): any;
|
||||||
collidesWithShape(other: Shape, result: CollisionResult): boolean;
|
collidesWithShape(other: Shape, result: Out<CollisionResult>): boolean;
|
||||||
containsPoint(point: Vector2): boolean;
|
containsPoint(point: Vector2): boolean;
|
||||||
pointCollidesWithShape(point: es.Vector2, result: es.CollisionResult): boolean;
|
pointCollidesWithShape(point: Vector2, result: Out<CollisionResult>): boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
@@ -3671,15 +3671,15 @@ declare module es {
|
|||||||
constructor(radius: number);
|
constructor(radius: number);
|
||||||
recalculateBounds(collider: Collider): void;
|
recalculateBounds(collider: Collider): void;
|
||||||
overlaps(other: Shape): any;
|
overlaps(other: Shape): any;
|
||||||
collidesWithShape(other: Shape, result: CollisionResult): boolean;
|
collidesWithShape(other: Shape, result: Out<CollisionResult>): boolean;
|
||||||
collidesWithLine(start: Vector2, end: Vector2, hit: RaycastHit): boolean;
|
collidesWithLine(start: Vector2, end: Vector2, hit: Out<RaycastHit>): boolean;
|
||||||
getPointAlongEdge(angle: number): Vector2;
|
getPointAlongEdge(angle: number): Vector2;
|
||||||
/**
|
/**
|
||||||
* 获取所提供的点是否在此范围内
|
* 获取所提供的点是否在此范围内
|
||||||
* @param point
|
* @param point
|
||||||
*/
|
*/
|
||||||
containsPoint(point: Vector2): boolean;
|
containsPoint(point: Vector2): boolean;
|
||||||
pointCollidesWithShape(point: Vector2, result: CollisionResult): boolean;
|
pointCollidesWithShape(point: Vector2, result: Out<CollisionResult>): boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
@@ -3731,7 +3731,7 @@ declare module es {
|
|||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
class ShapeCollisionsBox {
|
class ShapeCollisionsBox {
|
||||||
static boxToBox(first: Box, second: Box, result: CollisionResult): boolean;
|
static boxToBox(first: Box, second: Box, result: Out<CollisionResult>): boolean;
|
||||||
/**
|
/**
|
||||||
* 用second检查被deltaMovement移动的框的结果
|
* 用second检查被deltaMovement移动的框的结果
|
||||||
* @param first
|
* @param first
|
||||||
@@ -3745,31 +3745,31 @@ declare module es {
|
|||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
class ShapeCollisionsCircle {
|
class ShapeCollisionsCircle {
|
||||||
static circleToCircleCast(first: Circle, second: Circle, deltaMovement: Vector2, hit: RaycastHit): boolean;
|
static circleToCircleCast(first: Circle, second: Circle, deltaMovement: Vector2, hit: Out<RaycastHit>): boolean;
|
||||||
static circleToCircle(first: Circle, second: Circle, result?: CollisionResult): boolean;
|
static circleToCircle(first: Circle, second: Circle, result: Out<CollisionResult>): boolean;
|
||||||
/**
|
/**
|
||||||
* 适用于中心在框内的圆,也适用于与框外中心重合的圆。
|
* 适用于中心在框内的圆,也适用于与框外中心重合的圆。
|
||||||
* @param circle
|
* @param circle
|
||||||
* @param box
|
* @param box
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
static circleToBox(circle: Circle, box: Box, result?: CollisionResult): boolean;
|
static circleToBox(circle: Circle, box: Box, result: Out<CollisionResult>): boolean;
|
||||||
static circleToPolygon(circle: Circle, polygon: Polygon, result?: CollisionResult): boolean;
|
static circleToPolygon(circle: Circle, polygon: Polygon, result: Out<CollisionResult>): boolean;
|
||||||
static closestPointOnLine(lineA: Vector2, lineB: Vector2, closestTo: Vector2): Vector2;
|
static closestPointOnLine(lineA: Vector2, lineB: Vector2, closestTo: Vector2): Vector2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
class ShapeCollisionsLine {
|
class ShapeCollisionsLine {
|
||||||
static lineToPoly(start: Vector2, end: Vector2, polygon: Polygon, hit?: RaycastHit): boolean;
|
static lineToPoly(start: Vector2, end: Vector2, polygon: Polygon, hit: Out<RaycastHit>): boolean;
|
||||||
static lineToLine(a1: Vector2, a2: Vector2, b1: Vector2, b2: Vector2, intersection: Vector2): boolean;
|
static lineToLine(a1: Vector2, a2: Vector2, b1: Vector2, b2: Vector2, intersection: Vector2): boolean;
|
||||||
static lineToCircle(start: Vector2, end: Vector2, s: Circle, hit: RaycastHit): boolean;
|
static lineToCircle(start: Vector2, end: Vector2, s: Circle, hit: Out<RaycastHit>): boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
class ShapeCollisionsPoint {
|
class ShapeCollisionsPoint {
|
||||||
static pointToCircle(point: Vector2, circle: Circle, result: CollisionResult): boolean;
|
static pointToCircle(point: Vector2, circle: Circle, result: Out<CollisionResult>): boolean;
|
||||||
static pointToBox(point: Vector2, box: Box, result?: CollisionResult): boolean;
|
static pointToBox(point: Vector2, box: Box, result: Out<CollisionResult>): boolean;
|
||||||
static pointToPoly(point: Vector2, poly: Polygon, result?: CollisionResult): boolean;
|
static pointToPoly(point: Vector2, poly: Polygon, result: Out<CollisionResult>): boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
@@ -3780,7 +3780,7 @@ declare module es {
|
|||||||
* @param second
|
* @param second
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
static polygonToPolygon(first: Polygon, second: Polygon, result: CollisionResult): boolean;
|
static polygonToPolygon(first: Polygon, second: Polygon, result: Out<CollisionResult>): boolean;
|
||||||
/**
|
/**
|
||||||
* 计算一个多边形在一个轴上的投影,并返回一个[min,max]区间
|
* 计算一个多边形在一个轴上的投影,并返回一个[min,max]区间
|
||||||
* @param axis
|
* @param axis
|
||||||
@@ -4565,6 +4565,12 @@ declare module es {
|
|||||||
private _value;
|
private _value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
declare module es {
|
||||||
|
class Out<T> {
|
||||||
|
value: T;
|
||||||
|
constructor(value?: T);
|
||||||
|
}
|
||||||
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
class Ref<T> {
|
class Ref<T> {
|
||||||
value: T;
|
value: T;
|
||||||
|
|||||||
+135
-110
@@ -2467,7 +2467,6 @@ var es;
|
|||||||
if (this.shouldUseGravity)
|
if (this.shouldUseGravity)
|
||||||
this.velocity.addEqual(es.Physics.gravity.scale(es.Time.deltaTime));
|
this.velocity.addEqual(es.Physics.gravity.scale(es.Time.deltaTime));
|
||||||
this.entity.position = this.entity.position.add(this.velocity.scale(es.Time.deltaTime));
|
this.entity.position = this.entity.position.add(this.velocity.scale(es.Time.deltaTime));
|
||||||
var collisionResult = new es.CollisionResult();
|
|
||||||
// 捞取我们在新的位置上可能会碰撞到的任何东西
|
// 捞取我们在新的位置上可能会碰撞到的任何东西
|
||||||
var neighbors = es.Physics.boxcastBroadphaseExcludingSelf(this._collider, this._collider.bounds, this._collider.collidesWithLayers.value);
|
var neighbors = es.Physics.boxcastBroadphaseExcludingSelf(this._collider, this._collider.bounds, this._collider.collidesWithLayers.value);
|
||||||
if (neighbors.length > 0) {
|
if (neighbors.length > 0) {
|
||||||
@@ -2479,17 +2478,18 @@ var es;
|
|||||||
if (neighbor.entity.equals(this.entity)) {
|
if (neighbor.entity.equals(this.entity)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
var collisionResult = new es.Out();
|
||||||
if (this._collider.collidesWithNonMotion(neighbor, collisionResult)) {
|
if (this._collider.collidesWithNonMotion(neighbor, collisionResult)) {
|
||||||
// 如果附近有一个ArcadeRigidbody,我们就会处理完整的碰撞响应。如果没有,我们会根据附近是不可移动的来计算事情
|
// 如果附近有一个ArcadeRigidbody,我们就会处理完整的碰撞响应。如果没有,我们会根据附近是不可移动的来计算事情
|
||||||
var neighborRigidbody = neighbor.entity.getComponent(ArcadeRigidbody);
|
var neighborRigidbody = neighbor.entity.getComponent(ArcadeRigidbody);
|
||||||
if (neighborRigidbody != null) {
|
if (neighborRigidbody != null) {
|
||||||
this.processOverlap(neighborRigidbody, collisionResult.minimumTranslationVector);
|
this.processOverlap(neighborRigidbody, collisionResult.value.minimumTranslationVector);
|
||||||
this.processCollision(neighborRigidbody, collisionResult.minimumTranslationVector);
|
this.processCollision(neighborRigidbody, collisionResult.value.minimumTranslationVector);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 没有ArcadeRigidbody,所以我们假设它是不动的,只移动我们自己的
|
// 没有ArcadeRigidbody,所以我们假设它是不动的,只移动我们自己的
|
||||||
this.entity.position = this.entity.position.sub(collisionResult.minimumTranslationVector);
|
this.entity.position = this.entity.position.sub(collisionResult.value.minimumTranslationVector);
|
||||||
var relativeVelocity = this.calculateResponseVelocity(this.velocity, collisionResult.minimumTranslationVector);
|
var relativeVelocity = this.calculateResponseVelocity(this.velocity, collisionResult.value.minimumTranslationVector);
|
||||||
this.velocity.addEqual(relativeVelocity);
|
this.velocity.addEqual(relativeVelocity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3026,6 +3026,7 @@ var es;
|
|||||||
* @param collisionResult
|
* @param collisionResult
|
||||||
*/
|
*/
|
||||||
Mover.prototype.calculateMovement = function (motion, collisionResult) {
|
Mover.prototype.calculateMovement = function (motion, collisionResult) {
|
||||||
|
collisionResult.value = new es.CollisionResult();
|
||||||
var collider = null;
|
var collider = null;
|
||||||
if (this.entity.components.buffer.length > 0)
|
if (this.entity.components.buffer.length > 0)
|
||||||
for (var i = 0; i < this.entity.components.buffer.length; i++) {
|
for (var i = 0; i < this.entity.components.buffer.length; i++) {
|
||||||
@@ -3064,16 +3065,16 @@ var es;
|
|||||||
// 不检测触发器
|
// 不检测触发器
|
||||||
if (neighbor.isTrigger)
|
if (neighbor.isTrigger)
|
||||||
return;
|
return;
|
||||||
var _internalcollisionResult = new es.CollisionResult();
|
var _internalcollisionResult = new es.Out();
|
||||||
if (collider_1.collidesWith(neighbor, motion, _internalcollisionResult)) {
|
if (collider_1.collidesWith(neighbor, motion, _internalcollisionResult)) {
|
||||||
// 如果碰撞 则退回之前的移动量
|
// 如果碰撞 则退回之前的移动量
|
||||||
motion.subEqual(_internalcollisionResult.minimumTranslationVector);
|
motion.subEqual(_internalcollisionResult.value.minimumTranslationVector);
|
||||||
// 如果我们碰到多个对象,为了简单起见,只取第一个。
|
// 如果我们碰到多个对象,为了简单起见,只取第一个。
|
||||||
if (_internalcollisionResult.collider != null) {
|
if (_internalcollisionResult.value.collider != null) {
|
||||||
collisionResult.collider = _internalcollisionResult.collider;
|
collisionResult.value.collider = _internalcollisionResult.value.collider;
|
||||||
collisionResult.minimumTranslationVector = _internalcollisionResult.minimumTranslationVector;
|
collisionResult.value.minimumTranslationVector = _internalcollisionResult.value.minimumTranslationVector;
|
||||||
collisionResult.normal = _internalcollisionResult.normal;
|
collisionResult.value.normal = _internalcollisionResult.value.normal;
|
||||||
collisionResult.point = _internalcollisionResult.point;
|
collisionResult.value.point = _internalcollisionResult.value.point;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3081,7 +3082,7 @@ var es;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
es.ListPool.free(es.Collider, colliders);
|
es.ListPool.free(es.Collider, colliders);
|
||||||
return collisionResult.collider != null;
|
return collisionResult.value.collider != null;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* 将calculatemomovement应用到实体并更新triggerHelper
|
* 将calculatemomovement应用到实体并更新triggerHelper
|
||||||
@@ -3102,7 +3103,7 @@ var es;
|
|||||||
Mover.prototype.move = function (motion, collisionResult) {
|
Mover.prototype.move = function (motion, collisionResult) {
|
||||||
this.calculateMovement(motion, collisionResult);
|
this.calculateMovement(motion, collisionResult);
|
||||||
this.applyMovement(motion);
|
this.applyMovement(motion);
|
||||||
return collisionResult.collider != null;
|
return collisionResult.value.collider != null;
|
||||||
};
|
};
|
||||||
return Mover;
|
return Mover;
|
||||||
}(es.Component));
|
}(es.Component));
|
||||||
@@ -3346,13 +3347,12 @@ var es;
|
|||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
Collider.prototype.collidesWith = function (collider, motion, result) {
|
Collider.prototype.collidesWith = function (collider, motion, result) {
|
||||||
if (result === void 0) { result = new es.CollisionResult(); }
|
|
||||||
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
|
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
|
||||||
var oldPosition = this.entity.position;
|
var oldPosition = this.entity.position;
|
||||||
this.entity.position = this.entity.position.add(motion);
|
this.entity.position = this.entity.position.add(motion);
|
||||||
var didCollide = this.shape.collidesWithShape(collider.shape, result);
|
var didCollide = this.shape.collidesWithShape(collider.shape, result);
|
||||||
if (didCollide)
|
if (didCollide)
|
||||||
result.collider = collider;
|
result.value.collider = collider;
|
||||||
// 将图形位置返回到检查前的位置
|
// 将图形位置返回到检查前的位置
|
||||||
this.entity.position = oldPosition;
|
this.entity.position = oldPosition;
|
||||||
return didCollide;
|
return didCollide;
|
||||||
@@ -3363,12 +3363,11 @@ var es;
|
|||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
Collider.prototype.collidesWithNonMotion = function (collider, result) {
|
Collider.prototype.collidesWithNonMotion = function (collider, result) {
|
||||||
if (result === void 0) { result = new es.CollisionResult(); }
|
|
||||||
if (this.shape.collidesWithShape(collider.shape, result)) {
|
if (this.shape.collidesWithShape(collider.shape, result)) {
|
||||||
result.collider = collider;
|
result.value.collider = collider;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
result.collider = null;
|
result.value.collider = null;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@@ -3378,6 +3377,7 @@ var es;
|
|||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
Collider.prototype.collidesWithAny = function (motion, result) {
|
Collider.prototype.collidesWithAny = function (motion, result) {
|
||||||
|
result.value = new es.CollisionResult();
|
||||||
// 在我们的新位置上获取我们可能会碰到的任何东西
|
// 在我们的新位置上获取我们可能会碰到的任何东西
|
||||||
var colliderBounds = this.bounds.clone();
|
var colliderBounds = this.bounds.clone();
|
||||||
colliderBounds.x += motion.x;
|
colliderBounds.x += motion.x;
|
||||||
@@ -3387,18 +3387,16 @@ var es;
|
|||||||
var oldPosition = this.shape.position;
|
var oldPosition = this.shape.position;
|
||||||
this.shape.position = es.Vector2.add(this.shape.position, motion);
|
this.shape.position = es.Vector2.add(this.shape.position, motion);
|
||||||
var didCollide = false;
|
var didCollide = false;
|
||||||
if (neighbors.length > 0) {
|
|
||||||
for (var i = 0; i < neighbors.length; i++) {
|
for (var i = 0; i < neighbors.length; i++) {
|
||||||
var neighbor = neighbors[i];
|
var neighbor = neighbors[i];
|
||||||
if (neighbor.isTrigger)
|
if (neighbor.isTrigger)
|
||||||
continue;
|
continue;
|
||||||
if (this.collidesWithNonMotion(neighbor, result)) {
|
if (this.collidesWithNonMotion(neighbor, result)) {
|
||||||
motion = motion.sub(result.minimumTranslationVector);
|
motion = motion.sub(result.value.minimumTranslationVector);
|
||||||
this.shape.position = this.shape.position.sub(result.minimumTranslationVector);
|
this.shape.position = this.shape.position.sub(result.value.minimumTranslationVector);
|
||||||
didCollide = true;
|
didCollide = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// 将形状位置返回到检查之前的位置
|
// 将形状位置返回到检查之前的位置
|
||||||
this.shape.position = oldPosition;
|
this.shape.position = oldPosition;
|
||||||
return didCollide;
|
return didCollide;
|
||||||
@@ -3408,8 +3406,8 @@ var es;
|
|||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
Collider.prototype.collidesWithAnyNonMotion = function (result) {
|
Collider.prototype.collidesWithAnyNonMotion = function (result) {
|
||||||
if (result === void 0) { result = new es.CollisionResult(); }
|
|
||||||
var e_1, _a;
|
var e_1, _a;
|
||||||
|
result.value = new es.CollisionResult();
|
||||||
// 在我们的新位置上获取我们可能会碰到的任何东西
|
// 在我们的新位置上获取我们可能会碰到的任何东西
|
||||||
var neighbors = es.Physics.boxcastBroadphaseExcludingSelfNonRect(this, this.collidesWithLayers.value);
|
var neighbors = es.Physics.boxcastBroadphaseExcludingSelfNonRect(this, this.collidesWithLayers.value);
|
||||||
try {
|
try {
|
||||||
@@ -5449,7 +5447,7 @@ var es;
|
|||||||
*/
|
*/
|
||||||
Time.checkEvery = function (interval) {
|
Time.checkEvery = function (interval) {
|
||||||
// 我们减去了delta,因为timeSinceSceneLoad已经包含了这个update ticks delta
|
// 我们减去了delta,因为timeSinceSceneLoad已经包含了这个update ticks delta
|
||||||
return this.timeSinceSceneLoad / interval > (this.timeSinceSceneLoad - this.deltaTime) / interval;
|
return es.MathHelper.toInt(this.timeSinceSceneLoad / interval) > es.MathHelper.toInt((this.timeSinceSceneLoad - this.deltaTime) / interval);
|
||||||
};
|
};
|
||||||
/** 游戏运行的总时间 */
|
/** 游戏运行的总时间 */
|
||||||
Time.totalTime = 0;
|
Time.totalTime = 0;
|
||||||
@@ -7469,6 +7467,7 @@ var es;
|
|||||||
* @returns 矩形边框上离点最近的点
|
* @returns 矩形边框上离点最近的点
|
||||||
*/
|
*/
|
||||||
Rectangle.prototype.getClosestPointOnRectangleBorderToPoint = function (point, edgeNormal) {
|
Rectangle.prototype.getClosestPointOnRectangleBorderToPoint = function (point, edgeNormal) {
|
||||||
|
edgeNormal.value = es.Vector2.zero;
|
||||||
// 对于每条轴,如果点在框外,就把它限制在框内,否则就不要管它
|
// 对于每条轴,如果点在框外,就把它限制在框内,否则就不要管它
|
||||||
var res = es.Vector2.zero;
|
var res = es.Vector2.zero;
|
||||||
res.x = es.MathHelper.clamp(point.x, this.left, this.right);
|
res.x = es.MathHelper.clamp(point.x, this.left, this.right);
|
||||||
@@ -7482,30 +7481,30 @@ var es;
|
|||||||
var min = Math.min(dl, dr, dt, db);
|
var min = Math.min(dl, dr, dt, db);
|
||||||
if (min == dt) {
|
if (min == dt) {
|
||||||
res.y = this.top;
|
res.y = this.top;
|
||||||
edgeNormal.y = -1;
|
edgeNormal.value.y = -1;
|
||||||
}
|
}
|
||||||
else if (min == db) {
|
else if (min == db) {
|
||||||
res.y = this.bottom;
|
res.y = this.bottom;
|
||||||
edgeNormal.y = 1;
|
edgeNormal.value.y = 1;
|
||||||
}
|
}
|
||||||
else if (min == dl) {
|
else if (min == dl) {
|
||||||
res.x = this.left;
|
res.x = this.left;
|
||||||
edgeNormal.x = -1;
|
edgeNormal.value.x = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res.x = this.right;
|
res.x = this.right;
|
||||||
edgeNormal.x = 1;
|
edgeNormal.value.x = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (res.x == this.left)
|
if (res.x == this.left)
|
||||||
edgeNormal.x = -1;
|
edgeNormal.value.x = -1;
|
||||||
if (res.x == this.right)
|
if (res.x == this.right)
|
||||||
edgeNormal.x = 1;
|
edgeNormal.value.x = 1;
|
||||||
if (res.y == this.top)
|
if (res.y == this.top)
|
||||||
edgeNormal.y = -1;
|
edgeNormal.value.y = -1;
|
||||||
if (res.y == this.bottom)
|
if (res.y == this.bottom)
|
||||||
edgeNormal.y = 1;
|
edgeNormal.value.y = 1;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
@@ -8496,7 +8495,7 @@ var es;
|
|||||||
*/
|
*/
|
||||||
SpatialHash.prototype.overlapRectangle = function (rect, results, layerMask) {
|
SpatialHash.prototype.overlapRectangle = function (rect, results, layerMask) {
|
||||||
this._overlapTestBox.updateBox(rect.width, rect.height);
|
this._overlapTestBox.updateBox(rect.width, rect.height);
|
||||||
this._overlapTestBox.position = rect.location.clone();
|
this._overlapTestBox.position = rect.location;
|
||||||
var resultCounter = 0;
|
var resultCounter = 0;
|
||||||
var potentials = this.aabbBroadphase(rect, null, layerMask);
|
var potentials = this.aabbBroadphase(rect, null, layerMask);
|
||||||
for (var i = 0; i < potentials.length; i++) {
|
for (var i = 0; i < potentials.length; i++) {
|
||||||
@@ -8670,13 +8669,14 @@ var es;
|
|||||||
var colliderBounds = potential.bounds;
|
var colliderBounds = potential.bounds;
|
||||||
var res = colliderBounds.rayIntersects(this._ray);
|
var res = colliderBounds.rayIntersects(this._ray);
|
||||||
if (res.intersected && res.distance <= 1) {
|
if (res.intersected && res.distance <= 1) {
|
||||||
if (potential.shape.collidesWithLine(this._ray.start, this._ray.end, this._tempHit)) {
|
var tempHit = new es.Out(this._tempHit);
|
||||||
|
if (potential.shape.collidesWithLine(this._ray.start, this._ray.end, tempHit)) {
|
||||||
// 检查一下,我们应该排除这些射线,射线cast是否在碰撞器中开始
|
// 检查一下,我们应该排除这些射线,射线cast是否在碰撞器中开始
|
||||||
if (!es.Physics.raycastsStartInColliders && potential.shape.containsPoint(this._ray.start))
|
if (!es.Physics.raycastsStartInColliders && potential.shape.containsPoint(this._ray.start))
|
||||||
continue;
|
continue;
|
||||||
// TODO: 确保碰撞点在当前单元格中,如果它没有保存它以供以后计算
|
// TODO: 确保碰撞点在当前单元格中,如果它没有保存它以供以后计算
|
||||||
this._tempHit.collider = potential;
|
tempHit.value.collider = potential;
|
||||||
this._cellHits.push(this._tempHit);
|
this._cellHits.push(tempHit.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8701,7 +8701,7 @@ var es;
|
|||||||
};
|
};
|
||||||
RaycastResultParser.compareRaycastHits = function (a, b) {
|
RaycastResultParser.compareRaycastHits = function (a, b) {
|
||||||
if (a.distance !== b.distance) {
|
if (a.distance !== b.distance) {
|
||||||
return b.distance - a.distance;
|
return a.distance - b.distance;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return a.collider.castSortOrder - b.collider.castSortOrder;
|
return a.collider.castSortOrder - b.collider.castSortOrder;
|
||||||
@@ -8944,12 +8944,12 @@ var es;
|
|||||||
this.bounds.location = this.bounds.location.add(this.position);
|
this.bounds.location = this.bounds.location.add(this.position);
|
||||||
};
|
};
|
||||||
Polygon.prototype.overlaps = function (other) {
|
Polygon.prototype.overlaps = function (other) {
|
||||||
var result = new es.CollisionResult();
|
var result = new es.Out();
|
||||||
if (other instanceof Polygon)
|
if (other instanceof Polygon)
|
||||||
return es.ShapeCollisionsPolygon.polygonToPolygon(this, other, result);
|
return es.ShapeCollisionsPolygon.polygonToPolygon(this, other, result);
|
||||||
if (other instanceof es.Circle) {
|
if (other instanceof es.Circle) {
|
||||||
if (es.ShapeCollisionsCircle.circleToPolygon(other, this, result)) {
|
if (es.ShapeCollisionsCircle.circleToPolygon(other, this, result)) {
|
||||||
result.invertResult();
|
result.value.invertResult();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -8962,7 +8962,7 @@ var es;
|
|||||||
}
|
}
|
||||||
if (other instanceof es.Circle) {
|
if (other instanceof es.Circle) {
|
||||||
if (es.ShapeCollisionsCircle.circleToPolygon(other, this, result)) {
|
if (es.ShapeCollisionsCircle.circleToPolygon(other, this, result)) {
|
||||||
result.invertResult();
|
result.value.invertResult();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -9110,7 +9110,7 @@ var es;
|
|||||||
this.bounds = new es.Rectangle(this.position.x - this.radius, this.position.y - this.radius, this.radius * 2, this.radius * 2);
|
this.bounds = new es.Rectangle(this.position.x - this.radius, this.position.y - this.radius, this.radius * 2, this.radius * 2);
|
||||||
};
|
};
|
||||||
Circle.prototype.overlaps = function (other) {
|
Circle.prototype.overlaps = function (other) {
|
||||||
var result = new es.CollisionResult();
|
var result = new es.Out();
|
||||||
if (other instanceof es.Box && other.isUnrotated)
|
if (other instanceof es.Box && other.isUnrotated)
|
||||||
return es.Collisions.rectToCircle(other.bounds, this.position, this.radius);
|
return es.Collisions.rectToCircle(other.bounds, this.position, this.radius);
|
||||||
if (other instanceof Circle)
|
if (other instanceof Circle)
|
||||||
@@ -9289,14 +9289,15 @@ var es;
|
|||||||
function ShapeCollisionsBox() {
|
function ShapeCollisionsBox() {
|
||||||
}
|
}
|
||||||
ShapeCollisionsBox.boxToBox = function (first, second, result) {
|
ShapeCollisionsBox.boxToBox = function (first, second, result) {
|
||||||
|
result.value = new es.CollisionResult();
|
||||||
var minkowskiDiff = this.minkowskiDifference(first, second);
|
var minkowskiDiff = this.minkowskiDifference(first, second);
|
||||||
if (minkowskiDiff.contains(0, 0)) {
|
if (minkowskiDiff.contains(0, 0)) {
|
||||||
// 计算MTV。如果它是零,我们就可以称它为非碰撞
|
// 计算MTV。如果它是零,我们就可以称它为非碰撞
|
||||||
result.minimumTranslationVector = minkowskiDiff.getClosestPointOnBoundsToOrigin();
|
result.value.minimumTranslationVector = minkowskiDiff.getClosestPointOnBoundsToOrigin();
|
||||||
if (result.minimumTranslationVector.equals(es.Vector2.zero))
|
if (result.value.minimumTranslationVector.equals(es.Vector2.zero))
|
||||||
return false;
|
return false;
|
||||||
result.normal = result.minimumTranslationVector.scale(-1);
|
result.value.normal = result.value.minimumTranslationVector.scale(-1);
|
||||||
result.normal = result.normal.normalize();
|
result.value.normal = result.value.normal.normalize();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -9355,37 +9356,43 @@ var es;
|
|||||||
function ShapeCollisionsCircle() {
|
function ShapeCollisionsCircle() {
|
||||||
}
|
}
|
||||||
ShapeCollisionsCircle.circleToCircleCast = function (first, second, deltaMovement, hit) {
|
ShapeCollisionsCircle.circleToCircleCast = function (first, second, deltaMovement, hit) {
|
||||||
|
hit.value = new es.RaycastHit();
|
||||||
|
// 在动圆的运动矢量上找到离圆中心最近的点(第一个)
|
||||||
var endPointOfCast = first.position.add(deltaMovement);
|
var endPointOfCast = first.position.add(deltaMovement);
|
||||||
var d = this.closestPointOnLine(first.position, endPointOfCast, second.position);
|
var d = this.closestPointOnLine(first.position, endPointOfCast, second.position);
|
||||||
|
// 然后求最近点到圆心的距离
|
||||||
var closestDistanceSquared = es.Vector2.sqrDistance(second.position, d);
|
var closestDistanceSquared = es.Vector2.sqrDistance(second.position, d);
|
||||||
var sumOfRadiiSquared = (first.radius + second.radius) * (first.radius + second.radius);
|
var sumOfRadiiSquared = (first.radius + second.radius) * (first.radius + second.radius);
|
||||||
|
// 如果它小于半径之和,则发生碰撞
|
||||||
if (closestDistanceSquared <= sumOfRadiiSquared) {
|
if (closestDistanceSquared <= sumOfRadiiSquared) {
|
||||||
var normalizedDeltaMovement = deltaMovement.normalize();
|
var normalizedDeltaMovement = deltaMovement.normalize();
|
||||||
|
// 边缘情况:如果端点等于线上最近的点,那么从它到 second.position 的线将不垂直于射线
|
||||||
if (d === endPointOfCast) {
|
if (d === endPointOfCast) {
|
||||||
|
// 延长投射半径距离的终点,因此我们得到一个垂直的点
|
||||||
endPointOfCast = first.position.add(deltaMovement.add(normalizedDeltaMovement.scale(second.radius)));
|
endPointOfCast = first.position.add(deltaMovement.add(normalizedDeltaMovement.scale(second.radius)));
|
||||||
d = this.closestPointOnLine(first.position, endPointOfCast, second.position);
|
d = this.closestPointOnLine(first.position, endPointOfCast, second.position);
|
||||||
closestDistanceSquared = es.Vector2.sqrDistance(second.position, d);
|
closestDistanceSquared = es.Vector2.sqrDistance(second.position, d);
|
||||||
}
|
}
|
||||||
var backDist = Math.sqrt(sumOfRadiiSquared - closestDistanceSquared);
|
var backDist = Math.sqrt(sumOfRadiiSquared - closestDistanceSquared);
|
||||||
hit.centroid = d.sub(normalizedDeltaMovement.scale(backDist));
|
hit.value.centroid = d.sub(normalizedDeltaMovement.scale(backDist));
|
||||||
hit.normal = hit.centroid.sub(second.position).normalize();
|
hit.value.normal = hit.value.centroid.sub(second.position).normalize();
|
||||||
hit.fraction = (hit.centroid.x - first.position.x) / deltaMovement.x;
|
hit.value.fraction = (hit.value.centroid.x - first.position.x) / deltaMovement.x;
|
||||||
hit.distance = es.Vector2.distance(first.position, hit.centroid);
|
hit.value.distance = es.Vector2.distance(first.position, hit.value.centroid);
|
||||||
hit.point = second.position.add(hit.normal.scale(second.radius));
|
hit.value.point = second.position.add(hit.value.normal.scale(second.radius));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
ShapeCollisionsCircle.circleToCircle = function (first, second, result) {
|
ShapeCollisionsCircle.circleToCircle = function (first, second, result) {
|
||||||
if (result === void 0) { result = new es.CollisionResult(); }
|
result.value = new es.CollisionResult();
|
||||||
var distanceSquared = es.Vector2.sqrDistance(first.position, second.position);
|
var distanceSquared = es.Vector2.sqrDistance(first.position, second.position);
|
||||||
var sumOfRadii = first.radius + second.radius;
|
var sumOfRadii = first.radius + second.radius;
|
||||||
var collided = distanceSquared < sumOfRadii * sumOfRadii;
|
var collided = distanceSquared < sumOfRadii * sumOfRadii;
|
||||||
if (collided) {
|
if (collided) {
|
||||||
result.normal = first.position.sub(second.position).normalize();
|
result.value.normal = first.position.sub(second.position).normalize();
|
||||||
var depth = sumOfRadii - Math.sqrt(distanceSquared);
|
var depth = sumOfRadii - Math.sqrt(distanceSquared);
|
||||||
result.minimumTranslationVector = result.normal.scale(-depth);
|
result.value.minimumTranslationVector = result.value.normal.scale(-depth);
|
||||||
result.point = second.position.add(result.normal.scale(second.radius));
|
result.value.point = second.position.add(result.value.normal.scale(second.radius));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -9397,38 +9404,40 @@ var es;
|
|||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
ShapeCollisionsCircle.circleToBox = function (circle, box, result) {
|
ShapeCollisionsCircle.circleToBox = function (circle, box, result) {
|
||||||
if (result === void 0) { result = new es.CollisionResult(); }
|
result.value = new es.CollisionResult();
|
||||||
var closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position, result.normal);
|
var normal = new es.Out();
|
||||||
|
var closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position, normal);
|
||||||
|
result.value.normal = normal.value;
|
||||||
// 先处理中心在盒子里的圆,如果我们是包含的, 它的成本更低,
|
// 先处理中心在盒子里的圆,如果我们是包含的, 它的成本更低,
|
||||||
if (box.containsPoint(circle.position)) {
|
if (box.containsPoint(circle.position)) {
|
||||||
result.point = closestPointOnBounds;
|
result.value.point = closestPointOnBounds;
|
||||||
// 计算MTV。找出安全的、非碰撞的位置,并从中得到MTV
|
// 计算MTV。找出安全的、非碰撞的位置,并从中得到MTV
|
||||||
var safePlace = closestPointOnBounds.add(result.normal.scale(circle.radius));
|
var safePlace = closestPointOnBounds.add(result.value.normal.scale(circle.radius));
|
||||||
result.minimumTranslationVector = circle.position.sub(safePlace);
|
result.value.minimumTranslationVector = circle.position.sub(safePlace);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var sqrDistance = es.Vector2.sqrDistance(closestPointOnBounds, circle.position);
|
var sqrDistance = es.Vector2.sqrDistance(closestPointOnBounds, circle.position);
|
||||||
// 看框上的点距圆的半径是否小于圆的半径
|
// 看框上的点距圆的半径是否小于圆的半径
|
||||||
if (sqrDistance == 0) {
|
if (sqrDistance == 0) {
|
||||||
result.minimumTranslationVector = result.normal.scale(circle.radius);
|
result.value.minimumTranslationVector = result.value.normal.scale(circle.radius);
|
||||||
}
|
}
|
||||||
else if (sqrDistance <= circle.radius * circle.radius) {
|
else if (sqrDistance <= circle.radius * circle.radius) {
|
||||||
result.normal = circle.position.sub(closestPointOnBounds);
|
result.value.normal = circle.position.sub(closestPointOnBounds);
|
||||||
var depth = result.normal.magnitude() - circle.radius;
|
var depth = result.value.normal.magnitude() - circle.radius;
|
||||||
result.point = closestPointOnBounds;
|
result.value.point = closestPointOnBounds;
|
||||||
result.normal = result.normal.normalize();
|
result.value.normal = result.value.normal.normalize();
|
||||||
result.minimumTranslationVector = result.normal.scale(depth);
|
result.value.minimumTranslationVector = result.value.normal.scale(depth);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
ShapeCollisionsCircle.circleToPolygon = function (circle, polygon, result) {
|
ShapeCollisionsCircle.circleToPolygon = function (circle, polygon, result) {
|
||||||
if (result === void 0) { result = new es.CollisionResult(); }
|
result.value = new es.CollisionResult();
|
||||||
// 圆圈在多边形中的位置坐标
|
// 圆圈在多边形中的位置坐标
|
||||||
var poly2Circle = circle.position.sub(polygon.position);
|
var poly2Circle = circle.position.sub(polygon.position);
|
||||||
// 首先,我们需要找到从圆到多边形的最近距离
|
// 首先,我们需要找到从圆到多边形的最近距离
|
||||||
var res = es.Polygon.getClosestPointOnPolygonToPoint(polygon.points, poly2Circle);
|
var res = es.Polygon.getClosestPointOnPolygonToPoint(polygon.points, poly2Circle);
|
||||||
result.normal = res.edgeNormal;
|
result.value.normal = res.edgeNormal;
|
||||||
// 确保距离的平方小于半径的平方,否则我们不会相撞。
|
// 确保距离的平方小于半径的平方,否则我们不会相撞。
|
||||||
// 请注意,如果圆完全包含在多边形中,距离可能大于半径。
|
// 请注意,如果圆完全包含在多边形中,距离可能大于半径。
|
||||||
// 正因为如此,我们还要确保圆的位置不在多边形内。
|
// 正因为如此,我们还要确保圆的位置不在多边形内。
|
||||||
@@ -9438,12 +9447,12 @@ var es;
|
|||||||
// 算出MTV。我们要注意处理完全包含在多边形中的圆或包含其中心的圆
|
// 算出MTV。我们要注意处理完全包含在多边形中的圆或包含其中心的圆
|
||||||
var mtv;
|
var mtv;
|
||||||
if (circleCenterInsidePoly) {
|
if (circleCenterInsidePoly) {
|
||||||
mtv = result.normal.scale(Math.sqrt(res.distanceSquared) - circle.radius);
|
mtv = result.value.normal.scale(Math.sqrt(res.distanceSquared) - circle.radius);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 如果我们没有距离,这意味着圆心在多边形的边缘上。只需根据它的半径移动它
|
// 如果我们没有距离,这意味着圆心在多边形的边缘上。只需根据它的半径移动它
|
||||||
if (res.distanceSquared === 0) {
|
if (res.distanceSquared === 0) {
|
||||||
mtv = result.normal.scale(circle.radius);
|
mtv = result.value.normal.scale(circle.radius);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var distance = Math.sqrt(res.distanceSquared);
|
var distance = Math.sqrt(res.distanceSquared);
|
||||||
@@ -9452,8 +9461,8 @@ var es;
|
|||||||
.scale(((circle.radius - distance) / distance) * -1);
|
.scale(((circle.radius - distance) / distance) * -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.minimumTranslationVector = mtv;
|
result.value.minimumTranslationVector = mtv;
|
||||||
result.point = res.closestPoint.add(polygon.position);
|
result.value.point = res.closestPoint.add(polygon.position);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
ShapeCollisionsCircle.closestPointOnLine = function (lineA, lineB, closestTo) {
|
ShapeCollisionsCircle.closestPointOnLine = function (lineA, lineB, closestTo) {
|
||||||
@@ -9473,7 +9482,7 @@ var es;
|
|||||||
function ShapeCollisionsLine() {
|
function ShapeCollisionsLine() {
|
||||||
}
|
}
|
||||||
ShapeCollisionsLine.lineToPoly = function (start, end, polygon, hit) {
|
ShapeCollisionsLine.lineToPoly = function (start, end, polygon, hit) {
|
||||||
if (hit === void 0) { hit = new es.RaycastHit(); }
|
hit.value = new es.RaycastHit();
|
||||||
var normal = es.Vector2.zero;
|
var normal = es.Vector2.zero;
|
||||||
var intersectionPoint = es.Vector2.zero;
|
var intersectionPoint = es.Vector2.zero;
|
||||||
var fraction = Number.MAX_VALUE;
|
var fraction = Number.MAX_VALUE;
|
||||||
@@ -9500,7 +9509,7 @@ var es;
|
|||||||
if (hasIntersection) {
|
if (hasIntersection) {
|
||||||
normal = normal.normalize();
|
normal = normal.normalize();
|
||||||
var distance = es.Vector2.distance(start, intersectionPoint);
|
var distance = es.Vector2.distance(start, intersectionPoint);
|
||||||
hit.setValues(fraction, distance, intersectionPoint, normal);
|
hit.value.setValues(fraction, distance, intersectionPoint, normal);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -9525,6 +9534,7 @@ var es;
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
ShapeCollisionsLine.lineToCircle = function (start, end, s, hit) {
|
ShapeCollisionsLine.lineToCircle = function (start, end, s, hit) {
|
||||||
|
hit.value = new es.RaycastHit();
|
||||||
// 计算这里的长度并分别对d进行标准化,因为如果我们命中了我们需要它来得到分数
|
// 计算这里的长度并分别对d进行标准化,因为如果我们命中了我们需要它来得到分数
|
||||||
var lineLength = es.Vector2.distance(start, end);
|
var lineLength = es.Vector2.distance(start, end);
|
||||||
var d = es.Vector2.divideScaler(end.sub(start), lineLength);
|
var d = es.Vector2.divideScaler(end.sub(start), lineLength);
|
||||||
@@ -9539,14 +9549,14 @@ var es;
|
|||||||
if (discr < 0)
|
if (discr < 0)
|
||||||
return false;
|
return false;
|
||||||
// 射线相交圆
|
// 射线相交圆
|
||||||
hit.fraction = -b - Math.sqrt(discr);
|
hit.value.fraction = -b - Math.sqrt(discr);
|
||||||
// 如果分数为负数,射线从圈内开始,
|
// 如果分数为负数,射线从圈内开始,
|
||||||
if (hit.fraction < 0)
|
if (hit.value.fraction < 0)
|
||||||
hit.fraction = 0;
|
hit.value.fraction = 0;
|
||||||
hit.point = start.add(d.scale(hit.fraction));
|
hit.value.point = start.add(d.scale(hit.value.fraction));
|
||||||
hit.distance = es.Vector2.distance(start, hit.point);
|
hit.value.distance = es.Vector2.distance(start, hit.value.point);
|
||||||
hit.normal = hit.point.sub(s.position).normalize();
|
hit.value.normal = hit.value.point.sub(s.position).normalize();
|
||||||
hit.fraction = hit.distance / lineLength;
|
hit.value.fraction = hit.value.distance / lineLength;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
return ShapeCollisionsLine;
|
return ShapeCollisionsLine;
|
||||||
@@ -9559,36 +9569,39 @@ var es;
|
|||||||
function ShapeCollisionsPoint() {
|
function ShapeCollisionsPoint() {
|
||||||
}
|
}
|
||||||
ShapeCollisionsPoint.pointToCircle = function (point, circle, result) {
|
ShapeCollisionsPoint.pointToCircle = function (point, circle, result) {
|
||||||
|
result.value = new es.CollisionResult();
|
||||||
var distanceSquared = es.Vector2.sqrDistance(point, circle.position);
|
var distanceSquared = es.Vector2.sqrDistance(point, circle.position);
|
||||||
var sumOfRadii = 1 + circle.radius;
|
var sumOfRadii = 1 + circle.radius;
|
||||||
var collided = distanceSquared < sumOfRadii * sumOfRadii;
|
var collided = distanceSquared < sumOfRadii * sumOfRadii;
|
||||||
if (collided) {
|
if (collided) {
|
||||||
result.normal = point.sub(circle.position).normalize();
|
result.value.normal = point.sub(circle.position).normalize();
|
||||||
var depth = sumOfRadii - Math.sqrt(distanceSquared);
|
var depth = sumOfRadii - Math.sqrt(distanceSquared);
|
||||||
result.minimumTranslationVector = result.normal.scale(-depth);
|
result.value.minimumTranslationVector = result.value.normal.scale(-depth);
|
||||||
;
|
;
|
||||||
result.point = circle.position.add(result.normal.scale(circle.radius));
|
result.value.point = circle.position.add(result.value.normal.scale(circle.radius));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
ShapeCollisionsPoint.pointToBox = function (point, box, result) {
|
ShapeCollisionsPoint.pointToBox = function (point, box, result) {
|
||||||
if (result === void 0) { result = new es.CollisionResult(); }
|
result.value = new es.CollisionResult();
|
||||||
if (box.containsPoint(point)) {
|
if (box.containsPoint(point)) {
|
||||||
// 在方框的空间里找到点
|
// 在方框的空间里找到点
|
||||||
result.point = box.bounds.getClosestPointOnRectangleBorderToPoint(point, result.normal);
|
var normal = new es.Out();
|
||||||
result.minimumTranslationVector = point.sub(result.point);
|
result.value.point = box.bounds.getClosestPointOnRectangleBorderToPoint(point, normal);
|
||||||
|
result.value.normal = normal.value;
|
||||||
|
result.value.minimumTranslationVector = point.sub(result.value.point);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
ShapeCollisionsPoint.pointToPoly = function (point, poly, result) {
|
ShapeCollisionsPoint.pointToPoly = function (point, poly, result) {
|
||||||
if (result === void 0) { result = new es.CollisionResult(); }
|
result.value = new es.CollisionResult();
|
||||||
if (poly.containsPoint(point)) {
|
if (poly.containsPoint(point)) {
|
||||||
var res = es.Polygon.getClosestPointOnPolygonToPoint(poly.points, point.sub(poly.position));
|
var res = es.Polygon.getClosestPointOnPolygonToPoint(poly.points, point.sub(poly.position));
|
||||||
result.normal = res.edgeNormal;
|
result.value.normal = res.edgeNormal;
|
||||||
result.minimumTranslationVector = result.normal.scale(Math.sqrt(res.distanceSquared));
|
result.value.minimumTranslationVector = result.value.normal.scale(Math.sqrt(res.distanceSquared));
|
||||||
result.point = res.closestPoint.sub(poly.position);
|
result.value.point = res.closestPoint.sub(poly.position);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -9609,6 +9622,7 @@ var es;
|
|||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
ShapeCollisionsPolygon.polygonToPolygon = function (first, second, result) {
|
ShapeCollisionsPolygon.polygonToPolygon = function (first, second, result) {
|
||||||
|
result.value = new es.CollisionResult();
|
||||||
var isIntersecting = true;
|
var isIntersecting = true;
|
||||||
var firstEdges = first.edgeNormals;
|
var firstEdges = first.edgeNormals;
|
||||||
var secondEdges = second.edgeNormals;
|
var secondEdges = second.edgeNormals;
|
||||||
@@ -9648,8 +9662,8 @@ var es;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 利用最小平移向量对多边形进行推入。
|
// 利用最小平移向量对多边形进行推入。
|
||||||
result.normal = translationAxis;
|
result.value.normal = translationAxis;
|
||||||
result.minimumTranslationVector = translationAxis.scale(-minIntervalDistance);
|
result.value.minimumTranslationVector = translationAxis.scale(-minIntervalDistance);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@@ -11336,6 +11350,17 @@ var es;
|
|||||||
es.ValueChangeCommand = ValueChangeCommand;
|
es.ValueChangeCommand = ValueChangeCommand;
|
||||||
})(es || (es = {}));
|
})(es || (es = {}));
|
||||||
var es;
|
var es;
|
||||||
|
(function (es) {
|
||||||
|
var Out = /** @class */ (function () {
|
||||||
|
function Out(value) {
|
||||||
|
if (value === void 0) { value = null; }
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
return Out;
|
||||||
|
}());
|
||||||
|
es.Out = Out;
|
||||||
|
})(es || (es = {}));
|
||||||
|
var es;
|
||||||
(function (es) {
|
(function (es) {
|
||||||
var Ref = /** @class */ (function () {
|
var Ref = /** @class */ (function () {
|
||||||
function Ref(value) {
|
function Ref(value) {
|
||||||
@@ -13916,8 +13941,8 @@ var es;
|
|||||||
RectangleExt.getClosestPointOnRectangleBorderToPoint = function (rect, point) {
|
RectangleExt.getClosestPointOnRectangleBorderToPoint = function (rect, point) {
|
||||||
// 对于每个轴,如果该点在盒子外面,则将在盒子上,否则不理会它
|
// 对于每个轴,如果该点在盒子外面,则将在盒子上,否则不理会它
|
||||||
var res = es.Vector2.zero;
|
var res = es.Vector2.zero;
|
||||||
res.x = es.MathHelper.clamp(Math.trunc(point.x), rect.left, rect.right);
|
res.x = es.MathHelper.clamp(es.MathHelper.toInt(point.x), rect.left, rect.right);
|
||||||
res.y = es.MathHelper.clamp(Math.trunc(point.y), rect.top, rect.bottom);
|
res.y = es.MathHelper.clamp(es.MathHelper.toInt(point.y), rect.top, rect.bottom);
|
||||||
// 如果点在矩形内,我们需要将res推到边框,因为它将在矩形内
|
// 如果点在矩形内,我们需要将res推到边框,因为它将在矩形内
|
||||||
if (rect.contains(res.x, res.y)) {
|
if (rect.contains(res.x, res.y)) {
|
||||||
var dl = rect.x - rect.left;
|
var dl = rect.x - rect.left;
|
||||||
@@ -13968,14 +13993,14 @@ var es;
|
|||||||
if (pt.y > maxY)
|
if (pt.y > maxY)
|
||||||
maxY = pt.y;
|
maxY = pt.y;
|
||||||
}
|
}
|
||||||
return this.fromMinMaxVector(new es.Vector2(Math.trunc(minX), Math.trunc(minY)), new es.Vector2(Math.trunc(maxX), Math.trunc(maxY)));
|
return this.fromMinMaxVector(new es.Vector2(es.MathHelper.toInt(minX), es.MathHelper.toInt(minY)), new es.Vector2(es.MathHelper.toInt(maxX), es.MathHelper.toInt(maxY)));
|
||||||
};
|
};
|
||||||
RectangleExt.calculateBounds = function (rect, parentPosition, position, origin, scale, rotation, width, height) {
|
RectangleExt.calculateBounds = function (rect, parentPosition, position, origin, scale, rotation, width, height) {
|
||||||
if (rotation == 0) {
|
if (rotation == 0) {
|
||||||
rect.x = Math.trunc(parentPosition.x + position.x - origin.x * scale.x);
|
rect.x = es.MathHelper.toInt(parentPosition.x + position.x - origin.x * scale.x);
|
||||||
rect.y = Math.trunc(parentPosition.y + position.y - origin.y * scale.y);
|
rect.y = es.MathHelper.toInt(parentPosition.y + position.y - origin.y * scale.y);
|
||||||
rect.width = Math.trunc(width * scale.x);
|
rect.width = es.MathHelper.toInt(width * scale.x);
|
||||||
rect.height = Math.trunc(height * scale.y);
|
rect.height = es.MathHelper.toInt(height * scale.y);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 我们需要找到我们的绝对最小/最大值,并据此创建边界
|
// 我们需要找到我们的绝对最小/最大值,并据此创建边界
|
||||||
@@ -14001,13 +14026,13 @@ var es;
|
|||||||
es.Vector2Ext.transformR(bottomLeft, transformMatrix, bottomLeft);
|
es.Vector2Ext.transformR(bottomLeft, transformMatrix, bottomLeft);
|
||||||
es.Vector2Ext.transformR(bottomRight, transformMatrix, bottomRight);
|
es.Vector2Ext.transformR(bottomRight, transformMatrix, bottomRight);
|
||||||
// 找出最小值和最大值,这样我们就可以计算出我们的边界框。
|
// 找出最小值和最大值,这样我们就可以计算出我们的边界框。
|
||||||
var minX = Math.trunc(Math.min(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
var minX = es.MathHelper.toInt(Math.min(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
||||||
var maxX = Math.trunc(Math.max(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
var maxX = es.MathHelper.toInt(Math.max(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
||||||
var minY = Math.trunc(Math.min(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
var minY = es.MathHelper.toInt(Math.min(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
||||||
var maxY = Math.trunc(Math.max(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
var maxY = es.MathHelper.toInt(Math.max(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
||||||
rect.location = new es.Vector2(minX, minY);
|
rect.location = new es.Vector2(minX, minY);
|
||||||
rect.width = Math.trunc(maxX - minX);
|
rect.width = es.MathHelper.toInt(maxX - minX);
|
||||||
rect.height = Math.trunc(maxY - minY);
|
rect.height = es.MathHelper.toInt(maxY - minY);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@@ -14016,10 +14041,10 @@ var es;
|
|||||||
* @param scale
|
* @param scale
|
||||||
*/
|
*/
|
||||||
RectangleExt.scale = function (rect, scale) {
|
RectangleExt.scale = function (rect, scale) {
|
||||||
rect.x = Math.trunc(rect.x * scale.x);
|
rect.x = es.MathHelper.toInt(rect.x * scale.x);
|
||||||
rect.y = Math.trunc(rect.y * scale.y);
|
rect.y = es.MathHelper.toInt(rect.y * scale.y);
|
||||||
rect.width = Math.trunc(rect.width * scale.x);
|
rect.width = es.MathHelper.toInt(rect.width * scale.x);
|
||||||
rect.height = Math.trunc(rect.height * scale.y);
|
rect.height = es.MathHelper.toInt(rect.height * scale.y);
|
||||||
};
|
};
|
||||||
RectangleExt.translate = function (rect, vec) {
|
RectangleExt.translate = function (rect, vec) {
|
||||||
rect.location.addEqual(vec);
|
rect.location.addEqual(vec);
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -153,8 +153,6 @@ module es {
|
|||||||
this.velocity.addEqual(Physics.gravity.scale(Time.deltaTime));
|
this.velocity.addEqual(Physics.gravity.scale(Time.deltaTime));
|
||||||
this.entity.position = this.entity.position.add(this.velocity.scale(Time.deltaTime));
|
this.entity.position = this.entity.position.add(this.velocity.scale(Time.deltaTime));
|
||||||
|
|
||||||
let collisionResult = new CollisionResult();
|
|
||||||
|
|
||||||
// 捞取我们在新的位置上可能会碰撞到的任何东西
|
// 捞取我们在新的位置上可能会碰撞到的任何东西
|
||||||
let neighbors = Physics.boxcastBroadphaseExcludingSelf(this._collider, this._collider.bounds, this._collider.collidesWithLayers.value);
|
let neighbors = Physics.boxcastBroadphaseExcludingSelf(this._collider, this._collider.bounds, this._collider.collidesWithLayers.value);
|
||||||
if (neighbors.length > 0) {
|
if (neighbors.length > 0) {
|
||||||
@@ -168,16 +166,17 @@ module es {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const collisionResult = new Out<CollisionResult>();
|
||||||
if (this._collider.collidesWithNonMotion(neighbor, collisionResult)) {
|
if (this._collider.collidesWithNonMotion(neighbor, collisionResult)) {
|
||||||
// 如果附近有一个ArcadeRigidbody,我们就会处理完整的碰撞响应。如果没有,我们会根据附近是不可移动的来计算事情
|
// 如果附近有一个ArcadeRigidbody,我们就会处理完整的碰撞响应。如果没有,我们会根据附近是不可移动的来计算事情
|
||||||
let neighborRigidbody = neighbor.entity.getComponent(ArcadeRigidbody);
|
let neighborRigidbody = neighbor.entity.getComponent(ArcadeRigidbody);
|
||||||
if (neighborRigidbody != null) {
|
if (neighborRigidbody != null) {
|
||||||
this.processOverlap(neighborRigidbody, collisionResult.minimumTranslationVector);
|
this.processOverlap(neighborRigidbody, collisionResult.value.minimumTranslationVector);
|
||||||
this.processCollision(neighborRigidbody, collisionResult.minimumTranslationVector);
|
this.processCollision(neighborRigidbody, collisionResult.value.minimumTranslationVector);
|
||||||
} else {
|
} else {
|
||||||
// 没有ArcadeRigidbody,所以我们假设它是不动的,只移动我们自己的
|
// 没有ArcadeRigidbody,所以我们假设它是不动的,只移动我们自己的
|
||||||
this.entity.position = this.entity.position.sub(collisionResult.minimumTranslationVector);
|
this.entity.position = this.entity.position.sub(collisionResult.value.minimumTranslationVector);
|
||||||
const relativeVelocity = this.calculateResponseVelocity(this.velocity, collisionResult.minimumTranslationVector);
|
const relativeVelocity = this.calculateResponseVelocity(this.velocity, collisionResult.value.minimumTranslationVector);
|
||||||
this.velocity.addEqual(relativeVelocity);
|
this.velocity.addEqual(relativeVelocity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,14 +184,14 @@ module es {
|
|||||||
* @param motion
|
* @param motion
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
public collidesWith(collider: Collider, motion: Vector2, result: CollisionResult = new CollisionResult()): boolean {
|
public collidesWith(collider: Collider, motion: Vector2, result: Out<CollisionResult>): boolean {
|
||||||
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
|
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
|
||||||
const oldPosition = this.entity.position;
|
const oldPosition = this.entity.position;
|
||||||
this.entity.position = this.entity.position.add(motion);
|
this.entity.position = this.entity.position.add(motion);
|
||||||
|
|
||||||
const didCollide = this.shape.collidesWithShape(collider.shape, result);
|
const didCollide = this.shape.collidesWithShape(collider.shape, result);
|
||||||
if (didCollide)
|
if (didCollide)
|
||||||
result.collider = collider;
|
result.value.collider = collider;
|
||||||
|
|
||||||
// 将图形位置返回到检查前的位置
|
// 将图形位置返回到检查前的位置
|
||||||
this.entity.position = oldPosition;
|
this.entity.position = oldPosition;
|
||||||
@@ -204,13 +204,13 @@ module es {
|
|||||||
* @param collider
|
* @param collider
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
public collidesWithNonMotion(collider: Collider, result: CollisionResult = new CollisionResult()): boolean {
|
public collidesWithNonMotion(collider: Collider, result: Out<CollisionResult>): boolean {
|
||||||
if (this.shape.collidesWithShape(collider.shape, result)) {
|
if (this.shape.collidesWithShape(collider.shape, result)) {
|
||||||
result.collider = collider;
|
result.value.collider = collider;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.collider = null;
|
result.value.collider = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +220,9 @@ module es {
|
|||||||
* @param motion
|
* @param motion
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
public collidesWithAny(motion: Vector2, result: CollisionResult) {
|
public collidesWithAny(motion: Vector2, result: Out<CollisionResult>) {
|
||||||
|
result.value = new CollisionResult();
|
||||||
|
|
||||||
// 在我们的新位置上获取我们可能会碰到的任何东西
|
// 在我们的新位置上获取我们可能会碰到的任何东西
|
||||||
let colliderBounds = this.bounds.clone();
|
let colliderBounds = this.bounds.clone();
|
||||||
colliderBounds.x += motion.x;
|
colliderBounds.x += motion.x;
|
||||||
@@ -232,19 +234,17 @@ module es {
|
|||||||
this.shape.position = Vector2.add(this.shape.position, motion);
|
this.shape.position = Vector2.add(this.shape.position, motion);
|
||||||
|
|
||||||
let didCollide = false;
|
let didCollide = false;
|
||||||
if (neighbors.length > 0) {
|
|
||||||
for (let i = 0; i < neighbors.length; i ++ ){
|
for (let i = 0; i < neighbors.length; i ++ ){
|
||||||
const neighbor = neighbors[i];
|
const neighbor = neighbors[i];
|
||||||
if (neighbor.isTrigger)
|
if (neighbor.isTrigger)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (this.collidesWithNonMotion(neighbor, result)) {
|
if (this.collidesWithNonMotion(neighbor, result)) {
|
||||||
motion = motion.sub(result.minimumTranslationVector);
|
motion = motion.sub(result.value.minimumTranslationVector);
|
||||||
this.shape.position = this.shape.position.sub(result.minimumTranslationVector);
|
this.shape.position = this.shape.position.sub(result.value.minimumTranslationVector);
|
||||||
didCollide = true;
|
didCollide = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 将形状位置返回到检查之前的位置
|
// 将形状位置返回到检查之前的位置
|
||||||
this.shape.position = oldPosition;
|
this.shape.position = oldPosition;
|
||||||
@@ -256,7 +256,8 @@ module es {
|
|||||||
* 检查此碰撞器是否与场景中的其他碰撞器碰撞。它相交的第一个碰撞器将在碰撞结果中返回碰撞数据。
|
* 检查此碰撞器是否与场景中的其他碰撞器碰撞。它相交的第一个碰撞器将在碰撞结果中返回碰撞数据。
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
public collidesWithAnyNonMotion(result: CollisionResult = new CollisionResult()) {
|
public collidesWithAnyNonMotion(result: Out<CollisionResult>) {
|
||||||
|
result.value = new CollisionResult();
|
||||||
// 在我们的新位置上获取我们可能会碰到的任何东西
|
// 在我们的新位置上获取我们可能会碰到的任何东西
|
||||||
let neighbors = Physics.boxcastBroadphaseExcludingSelfNonRect(this, this.collidesWithLayers.value);
|
let neighbors = Physics.boxcastBroadphaseExcludingSelfNonRect(this, this.collidesWithLayers.value);
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ module es {
|
|||||||
* @param motion
|
* @param motion
|
||||||
* @param collisionResult
|
* @param collisionResult
|
||||||
*/
|
*/
|
||||||
public calculateMovement(motion: Vector2, collisionResult: CollisionResult): boolean {
|
public calculateMovement(motion: Vector2, collisionResult: Out<CollisionResult>): boolean {
|
||||||
|
collisionResult.value = new CollisionResult();
|
||||||
|
|
||||||
let collider = null;
|
let collider = null;
|
||||||
if (this.entity.components.buffer.length > 0)
|
if (this.entity.components.buffer.length > 0)
|
||||||
for (let i = 0; i < this.entity.components.buffer.length; i++) {
|
for (let i = 0; i < this.entity.components.buffer.length; i++) {
|
||||||
@@ -65,16 +67,16 @@ module es {
|
|||||||
if (neighbor.isTrigger)
|
if (neighbor.isTrigger)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let _internalcollisionResult: CollisionResult = new CollisionResult();
|
let _internalcollisionResult = new Out<CollisionResult>();
|
||||||
if (collider.collidesWith(neighbor, motion, _internalcollisionResult)) {
|
if (collider.collidesWith(neighbor, motion, _internalcollisionResult)) {
|
||||||
// 如果碰撞 则退回之前的移动量
|
// 如果碰撞 则退回之前的移动量
|
||||||
motion.subEqual(_internalcollisionResult.minimumTranslationVector);
|
motion.subEqual(_internalcollisionResult.value.minimumTranslationVector);
|
||||||
// 如果我们碰到多个对象,为了简单起见,只取第一个。
|
// 如果我们碰到多个对象,为了简单起见,只取第一个。
|
||||||
if (_internalcollisionResult.collider != null) {
|
if (_internalcollisionResult.value.collider != null) {
|
||||||
collisionResult.collider = _internalcollisionResult.collider;
|
collisionResult.value.collider = _internalcollisionResult.value.collider;
|
||||||
collisionResult.minimumTranslationVector = _internalcollisionResult.minimumTranslationVector;
|
collisionResult.value.minimumTranslationVector = _internalcollisionResult.value.minimumTranslationVector;
|
||||||
collisionResult.normal = _internalcollisionResult.normal;
|
collisionResult.value.normal = _internalcollisionResult.value.normal;
|
||||||
collisionResult.point = _internalcollisionResult.point;
|
collisionResult.value.point = _internalcollisionResult.value.point;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +85,7 @@ module es {
|
|||||||
}
|
}
|
||||||
ListPool.free(Collider, colliders);
|
ListPool.free(Collider, colliders);
|
||||||
|
|
||||||
return collisionResult.collider != null;
|
return collisionResult.value.collider != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,10 +106,10 @@ module es {
|
|||||||
* @param motion
|
* @param motion
|
||||||
* @param collisionResult
|
* @param collisionResult
|
||||||
*/
|
*/
|
||||||
public move(motion: Vector2, collisionResult: CollisionResult) {
|
public move(motion: Vector2, collisionResult: Out<CollisionResult>) {
|
||||||
this.calculateMovement(motion, collisionResult);
|
this.calculateMovement(motion, collisionResult);
|
||||||
this.applyMovement(motion);
|
this.applyMovement(motion);
|
||||||
return collisionResult.collider != null;
|
return collisionResult.value.collider != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ module es {
|
|||||||
*/
|
*/
|
||||||
public static checkEvery(interval: number) {
|
public static checkEvery(interval: number) {
|
||||||
// 我们减去了delta,因为timeSinceSceneLoad已经包含了这个update ticks delta
|
// 我们减去了delta,因为timeSinceSceneLoad已经包含了这个update ticks delta
|
||||||
return this.timeSinceSceneLoad / interval > (this.timeSinceSceneLoad - this.deltaTime) / interval;
|
return MathHelper.toInt(this.timeSinceSceneLoad / interval) > MathHelper.toInt((this.timeSinceSceneLoad - this.deltaTime) / interval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -318,9 +318,10 @@ module es {
|
|||||||
* @param edgeNormal
|
* @param edgeNormal
|
||||||
* @returns 矩形边框上离点最近的点
|
* @returns 矩形边框上离点最近的点
|
||||||
*/
|
*/
|
||||||
public getClosestPointOnRectangleBorderToPoint(point: Vector2, edgeNormal: Vector2): Vector2 {
|
public getClosestPointOnRectangleBorderToPoint(point: Vector2, edgeNormal: Out<Vector2>): Vector2 {
|
||||||
|
edgeNormal.value = Vector2.zero;
|
||||||
// 对于每条轴,如果点在框外,就把它限制在框内,否则就不要管它
|
// 对于每条轴,如果点在框外,就把它限制在框内,否则就不要管它
|
||||||
let res = es.Vector2.zero;
|
const res = Vector2.zero;
|
||||||
res.x = MathHelper.clamp(point.x, this.left, this.right);
|
res.x = MathHelper.clamp(point.x, this.left, this.right);
|
||||||
res.y = MathHelper.clamp(point.y, this.top, this.bottom);
|
res.y = MathHelper.clamp(point.y, this.top, this.bottom);
|
||||||
|
|
||||||
@@ -334,22 +335,22 @@ module es {
|
|||||||
let min = Math.min(dl, dr, dt, db);
|
let min = Math.min(dl, dr, dt, db);
|
||||||
if (min == dt) {
|
if (min == dt) {
|
||||||
res.y = this.top;
|
res.y = this.top;
|
||||||
edgeNormal.y = -1;
|
edgeNormal.value.y = -1;
|
||||||
} else if (min == db) {
|
} else if (min == db) {
|
||||||
res.y = this.bottom;
|
res.y = this.bottom;
|
||||||
edgeNormal.y = 1;
|
edgeNormal.value.y = 1;
|
||||||
} else if (min == dl) {
|
} else if (min == dl) {
|
||||||
res.x = this.left;
|
res.x = this.left;
|
||||||
edgeNormal.x = -1;
|
edgeNormal.value.x = -1;
|
||||||
} else {
|
} else {
|
||||||
res.x = this.right;
|
res.x = this.right;
|
||||||
edgeNormal.x = 1;
|
edgeNormal.value.x = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (res.x == this.left) edgeNormal.x = -1;
|
if (res.x == this.left) edgeNormal.value.x = -1;
|
||||||
if (res.x == this.right) edgeNormal.x = 1;
|
if (res.x == this.right) edgeNormal.value.x = 1;
|
||||||
if (res.y == this.top) edgeNormal.y = -1;
|
if (res.y == this.top) edgeNormal.value.y = -1;
|
||||||
if (res.y == this.bottom) edgeNormal.y = 1;
|
if (res.y == this.bottom) edgeNormal.value.y = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ module es {
|
|||||||
return super.overlaps(other);
|
return super.overlaps(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public collidesWithShape(other: Shape, result: CollisionResult): boolean {
|
public collidesWithShape(other: Shape, result: Out<CollisionResult>): boolean {
|
||||||
// 特殊情况,这一个高性能方式实现,其他情况则使用polygon方法检测
|
// 特殊情况,这一个高性能方式实现,其他情况则使用polygon方法检测
|
||||||
if (other instanceof Box && (other as Box).isUnrotated) {
|
if (other instanceof Box && (other as Box).isUnrotated) {
|
||||||
return ShapeCollisionsBox.boxToBox(this, other, result);
|
return ShapeCollisionsBox.boxToBox(this, other, result);
|
||||||
@@ -84,7 +84,7 @@ module es {
|
|||||||
return super.containsPoint(point);
|
return super.containsPoint(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
public pointCollidesWithShape(point: es.Vector2, result: es.CollisionResult): boolean {
|
public pointCollidesWithShape(point: Vector2, result: Out<CollisionResult>): boolean {
|
||||||
if (this.isUnrotated)
|
if (this.isUnrotated)
|
||||||
return ShapeCollisionsPoint.pointToBox(point, this, result);
|
return ShapeCollisionsPoint.pointToBox(point, this, result);
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ module es {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public overlaps(other: Shape) {
|
public overlaps(other: Shape) {
|
||||||
let result: CollisionResult = new CollisionResult();
|
const result = new Out<CollisionResult>();
|
||||||
if (other instanceof Box && (other as Box).isUnrotated)
|
if (other instanceof Box && (other as Box).isUnrotated)
|
||||||
return Collisions.rectToCircle(other.bounds, this.position, this.radius);
|
return Collisions.rectToCircle(other.bounds, this.position, this.radius);
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ module es {
|
|||||||
throw new Error(`overlaps of circle to ${other} are not supported`);
|
throw new Error(`overlaps of circle to ${other} are not supported`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public collidesWithShape(other: Shape, result: CollisionResult): boolean {
|
public collidesWithShape(other: Shape, result: Out<CollisionResult>): boolean {
|
||||||
if (other instanceof Box && (other as Box).isUnrotated) {
|
if (other instanceof Box && (other as Box).isUnrotated) {
|
||||||
return ShapeCollisionsCircle.circleToBox(this, other, result);
|
return ShapeCollisionsCircle.circleToBox(this, other, result);
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ module es {
|
|||||||
throw new Error(`Collisions of Circle to ${other} are not supported`);
|
throw new Error(`Collisions of Circle to ${other} are not supported`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public collidesWithLine(start: Vector2, end: Vector2, hit: RaycastHit): boolean {
|
public collidesWithLine(start: Vector2, end: Vector2, hit: Out<RaycastHit>): boolean {
|
||||||
return ShapeCollisionsLine.lineToCircle(start, end, this, hit);
|
return ShapeCollisionsLine.lineToCircle(start, end, this, hit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ module es {
|
|||||||
return (point.sub(this.position)).lengthSquared() <= this.radius * this.radius;
|
return (point.sub(this.position)).lengthSquared() <= this.radius * this.radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
public pointCollidesWithShape(point: Vector2, result: CollisionResult): boolean {
|
public pointCollidesWithShape(point: Vector2, result: Out<CollisionResult>): boolean {
|
||||||
return ShapeCollisionsPoint.pointToCircle(point, this, result);
|
return ShapeCollisionsPoint.pointToCircle(point, this, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,13 +287,13 @@ module es {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public overlaps(other: Shape) {
|
public overlaps(other: Shape) {
|
||||||
let result: CollisionResult = new CollisionResult();
|
let result = new Out<CollisionResult>();
|
||||||
if (other instanceof Polygon)
|
if (other instanceof Polygon)
|
||||||
return ShapeCollisionsPolygon.polygonToPolygon(this, other, result);
|
return ShapeCollisionsPolygon.polygonToPolygon(this, other, result);
|
||||||
|
|
||||||
if (other instanceof Circle) {
|
if (other instanceof Circle) {
|
||||||
if (ShapeCollisionsCircle.circleToPolygon(other, this, result)) {
|
if (ShapeCollisionsCircle.circleToPolygon(other, this, result)) {
|
||||||
result.invertResult();
|
result.value.invertResult();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,14 +303,14 @@ module es {
|
|||||||
throw new Error(`overlaps of Pologon to ${other} are not supported`);
|
throw new Error(`overlaps of Pologon to ${other} are not supported`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public collidesWithShape(other: Shape, result: CollisionResult): boolean {
|
public collidesWithShape(other: Shape, result: Out<CollisionResult>): boolean {
|
||||||
if (other instanceof Polygon) {
|
if (other instanceof Polygon) {
|
||||||
return ShapeCollisionsPolygon.polygonToPolygon(this, other, result);
|
return ShapeCollisionsPolygon.polygonToPolygon(this, other, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other instanceof Circle) {
|
if (other instanceof Circle) {
|
||||||
if (ShapeCollisionsCircle.circleToPolygon(other, this, result)) {
|
if (ShapeCollisionsCircle.circleToPolygon(other, this, result)) {
|
||||||
result.invertResult();
|
result.value.invertResult();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,7 +320,7 @@ module es {
|
|||||||
throw new Error(`overlaps of Polygon to ${other} are not supported`);
|
throw new Error(`overlaps of Polygon to ${other} are not supported`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public collidesWithLine(start: es.Vector2, end: es.Vector2, hit: es.RaycastHit): boolean {
|
public collidesWithLine(start: Vector2, end: Vector2, hit: Out<RaycastHit>): boolean {
|
||||||
return ShapeCollisionsLine.lineToPoly(start, end, this, hit);
|
return ShapeCollisionsLine.lineToPoly(start, end, this, hit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +345,7 @@ module es {
|
|||||||
return isInside;
|
return isInside;
|
||||||
}
|
}
|
||||||
|
|
||||||
public pointCollidesWithShape(point: Vector2, result: CollisionResult): boolean {
|
public pointCollidesWithShape(point: Vector2, result: Out<CollisionResult>): boolean {
|
||||||
return ShapeCollisionsPoint.pointToPoly(point, this, result);
|
return ShapeCollisionsPoint.pointToPoly(point, this, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ module es {
|
|||||||
|
|
||||||
public abstract overlaps(other: Shape): boolean;
|
public abstract overlaps(other: Shape): boolean;
|
||||||
|
|
||||||
public abstract collidesWithShape(other: Shape, collisionResult: CollisionResult): boolean;
|
public abstract collidesWithShape(other: Shape, collisionResult: Out<CollisionResult>): boolean;
|
||||||
|
|
||||||
public abstract collidesWithLine(start: Vector2, end: Vector2, hit: RaycastHit): boolean;
|
public abstract collidesWithLine(start: Vector2, end: Vector2, hit: Out<RaycastHit>): boolean;
|
||||||
|
|
||||||
public abstract containsPoint(point: Vector2);
|
public abstract containsPoint(point: Vector2);
|
||||||
|
|
||||||
public abstract pointCollidesWithShape(point: Vector2, result: CollisionResult): boolean;
|
public abstract pointCollidesWithShape(point: Vector2, result: Out<CollisionResult>): boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
module es {
|
module es {
|
||||||
export class ShapeCollisionsBox {
|
export class ShapeCollisionsBox {
|
||||||
public static boxToBox(first: Box, second: Box, result: CollisionResult): boolean {
|
public static boxToBox(first: Box, second: Box, result: Out<CollisionResult>): boolean {
|
||||||
|
result.value = new CollisionResult();
|
||||||
|
|
||||||
const minkowskiDiff = this.minkowskiDifference(first, second);
|
const minkowskiDiff = this.minkowskiDifference(first, second);
|
||||||
if (minkowskiDiff.contains(0, 0)) {
|
if (minkowskiDiff.contains(0, 0)) {
|
||||||
// 计算MTV。如果它是零,我们就可以称它为非碰撞
|
// 计算MTV。如果它是零,我们就可以称它为非碰撞
|
||||||
result.minimumTranslationVector = minkowskiDiff.getClosestPointOnBoundsToOrigin();
|
result.value.minimumTranslationVector = minkowskiDiff.getClosestPointOnBoundsToOrigin();
|
||||||
|
|
||||||
if (result.minimumTranslationVector.equals(Vector2.zero))
|
if (result.value.minimumTranslationVector.equals(Vector2.zero))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
result.normal = result.minimumTranslationVector.scale(-1);
|
result.value.normal = result.value.minimumTranslationVector.scale(-1);
|
||||||
result.normal = result.normal.normalize();
|
result.value.normal = result.value.normal.normalize();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,51 @@
|
|||||||
module es {
|
module es {
|
||||||
export class ShapeCollisionsCircle {
|
export class ShapeCollisionsCircle {
|
||||||
public static circleToCircleCast(first: Circle,second: Circle,deltaMovement: Vector2,hit: RaycastHit): boolean {
|
public static circleToCircleCast(first: Circle, second: Circle, deltaMovement: Vector2, hit: Out<RaycastHit>): boolean {
|
||||||
|
hit.value = new RaycastHit();
|
||||||
|
|
||||||
|
// 在动圆的运动矢量上找到离圆中心最近的点(第一个)
|
||||||
let endPointOfCast = first.position.add(deltaMovement);
|
let endPointOfCast = first.position.add(deltaMovement);
|
||||||
let d = this.closestPointOnLine(first.position, endPointOfCast, second.position);
|
let d = this.closestPointOnLine(first.position, endPointOfCast, second.position);
|
||||||
|
|
||||||
|
// 然后求最近点到圆心的距离
|
||||||
let closestDistanceSquared = Vector2.sqrDistance(second.position, d);
|
let closestDistanceSquared = Vector2.sqrDistance(second.position, d);
|
||||||
const sumOfRadiiSquared = (first.radius + second.radius) * (first.radius + second.radius);
|
const sumOfRadiiSquared = (first.radius + second.radius) * (first.radius + second.radius);
|
||||||
|
|
||||||
|
// 如果它小于半径之和,则发生碰撞
|
||||||
if (closestDistanceSquared <= sumOfRadiiSquared) {
|
if (closestDistanceSquared <= sumOfRadiiSquared) {
|
||||||
const normalizedDeltaMovement = deltaMovement.normalize();
|
const normalizedDeltaMovement = deltaMovement.normalize();
|
||||||
|
|
||||||
|
// 边缘情况:如果端点等于线上最近的点,那么从它到 second.position 的线将不垂直于射线
|
||||||
if (d === endPointOfCast) {
|
if (d === endPointOfCast) {
|
||||||
endPointOfCast = first.position.add(
|
// 延长投射半径距离的终点,因此我们得到一个垂直的点
|
||||||
deltaMovement.add(normalizedDeltaMovement.scale(second.radius))
|
endPointOfCast = first.position.add(deltaMovement.add(normalizedDeltaMovement.scale(second.radius)));
|
||||||
);
|
d = this.closestPointOnLine(first.position, endPointOfCast, second.position);
|
||||||
d = this.closestPointOnLine(
|
|
||||||
first.position,
|
|
||||||
endPointOfCast,
|
|
||||||
second.position
|
|
||||||
);
|
|
||||||
closestDistanceSquared = Vector2.sqrDistance(second.position, d);
|
closestDistanceSquared = Vector2.sqrDistance(second.position, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
const backDist = Math.sqrt(sumOfRadiiSquared - closestDistanceSquared);
|
const backDist = Math.sqrt(sumOfRadiiSquared - closestDistanceSquared);
|
||||||
hit.centroid = d.sub(normalizedDeltaMovement.scale(backDist));
|
hit.value.centroid = d.sub(normalizedDeltaMovement.scale(backDist));
|
||||||
hit.normal = hit.centroid.sub(second.position).normalize();
|
hit.value.normal = hit.value.centroid.sub(second.position).normalize();
|
||||||
hit.fraction = (hit.centroid.x - first.position.x) / deltaMovement.x;
|
hit.value.fraction = (hit.value.centroid.x - first.position.x) / deltaMovement.x;
|
||||||
hit.distance = Vector2.distance(first.position, hit.centroid);
|
hit.value.distance = Vector2.distance(first.position, hit.value.centroid);
|
||||||
hit.point = second.position.add(hit.normal.scale(second.radius));
|
hit.value.point = second.position.add(hit.value.normal.scale(second.radius));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static circleToCircle(first: Circle, second: Circle, result: CollisionResult = new CollisionResult()): boolean {
|
public static circleToCircle(first: Circle, second: Circle, result: Out<CollisionResult>): boolean {
|
||||||
|
result.value = new CollisionResult();
|
||||||
|
|
||||||
const distanceSquared = Vector2.sqrDistance(first.position, second.position);
|
const distanceSquared = Vector2.sqrDistance(first.position, second.position);
|
||||||
const sumOfRadii = first.radius + second.radius;
|
const sumOfRadii = first.radius + second.radius;
|
||||||
const collided = distanceSquared < sumOfRadii * sumOfRadii;
|
const collided = distanceSquared < sumOfRadii * sumOfRadii;
|
||||||
if (collided) {
|
if (collided) {
|
||||||
result.normal = first.position.sub(second.position).normalize();
|
result.value.normal = first.position.sub(second.position).normalize();
|
||||||
const depth = sumOfRadii - Math.sqrt(distanceSquared);
|
const depth = sumOfRadii - Math.sqrt(distanceSquared);
|
||||||
result.minimumTranslationVector = result.normal.scale(-depth);
|
result.value.minimumTranslationVector = result.value.normal.scale(-depth);
|
||||||
result.point = second.position.add(result.normal.scale(second.radius));
|
result.value.point = second.position.add(result.value.normal.scale(second.radius));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -54,16 +59,19 @@ module es {
|
|||||||
* @param box
|
* @param box
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
public static circleToBox(circle: Circle, box: Box, result: CollisionResult = new CollisionResult()): boolean {
|
public static circleToBox(circle: Circle, box: Box, result: Out<CollisionResult>): boolean {
|
||||||
const closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position, result.normal);
|
result.value = new CollisionResult();
|
||||||
|
const normal = new Out<Vector2>();
|
||||||
|
const closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position, normal);
|
||||||
|
result.value.normal = normal.value;
|
||||||
|
|
||||||
// 先处理中心在盒子里的圆,如果我们是包含的, 它的成本更低,
|
// 先处理中心在盒子里的圆,如果我们是包含的, 它的成本更低,
|
||||||
if (box.containsPoint(circle.position)) {
|
if (box.containsPoint(circle.position)) {
|
||||||
result.point = closestPointOnBounds;
|
result.value.point = closestPointOnBounds;
|
||||||
|
|
||||||
// 计算MTV。找出安全的、非碰撞的位置,并从中得到MTV
|
// 计算MTV。找出安全的、非碰撞的位置,并从中得到MTV
|
||||||
const safePlace = closestPointOnBounds.add(result.normal.scale(circle.radius));
|
const safePlace = closestPointOnBounds.add(result.value.normal.scale(circle.radius));
|
||||||
result.minimumTranslationVector = circle.position.sub(safePlace);
|
result.value.minimumTranslationVector = circle.position.sub(safePlace);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -72,14 +80,14 @@ module es {
|
|||||||
|
|
||||||
// 看框上的点距圆的半径是否小于圆的半径
|
// 看框上的点距圆的半径是否小于圆的半径
|
||||||
if (sqrDistance == 0) {
|
if (sqrDistance == 0) {
|
||||||
result.minimumTranslationVector = result.normal.scale(circle.radius);
|
result.value.minimumTranslationVector = result.value.normal.scale(circle.radius);
|
||||||
} else if (sqrDistance <= circle.radius * circle.radius) {
|
} else if (sqrDistance <= circle.radius * circle.radius) {
|
||||||
result.normal = circle.position.sub(closestPointOnBounds);
|
result.value.normal = circle.position.sub(closestPointOnBounds);
|
||||||
const depth = result.normal.magnitude() - circle.radius;
|
const depth = result.value.normal.magnitude() - circle.radius;
|
||||||
|
|
||||||
result.point = closestPointOnBounds;
|
result.value.point = closestPointOnBounds;
|
||||||
result.normal = result.normal.normalize();
|
result.value.normal = result.value.normal.normalize();
|
||||||
result.minimumTranslationVector = result.normal.scale(depth);
|
result.value.minimumTranslationVector = result.value.normal.scale(depth);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -87,13 +95,15 @@ module es {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static circleToPolygon(circle: Circle, polygon: Polygon, result: CollisionResult = new CollisionResult()): boolean {
|
public static circleToPolygon(circle: Circle, polygon: Polygon, result: Out<CollisionResult>): boolean {
|
||||||
|
result.value = new CollisionResult();
|
||||||
|
|
||||||
// 圆圈在多边形中的位置坐标
|
// 圆圈在多边形中的位置坐标
|
||||||
const poly2Circle = circle.position.sub(polygon.position);
|
const poly2Circle = circle.position.sub(polygon.position);
|
||||||
|
|
||||||
// 首先,我们需要找到从圆到多边形的最近距离
|
// 首先,我们需要找到从圆到多边形的最近距离
|
||||||
const res = Polygon.getClosestPointOnPolygonToPoint(polygon.points, poly2Circle);
|
const res = Polygon.getClosestPointOnPolygonToPoint(polygon.points, poly2Circle);
|
||||||
result.normal = res.edgeNormal;
|
result.value.normal = res.edgeNormal;
|
||||||
|
|
||||||
// 确保距离的平方小于半径的平方,否则我们不会相撞。
|
// 确保距离的平方小于半径的平方,否则我们不会相撞。
|
||||||
// 请注意,如果圆完全包含在多边形中,距离可能大于半径。
|
// 请注意,如果圆完全包含在多边形中,距离可能大于半径。
|
||||||
@@ -105,11 +115,11 @@ module es {
|
|||||||
// 算出MTV。我们要注意处理完全包含在多边形中的圆或包含其中心的圆
|
// 算出MTV。我们要注意处理完全包含在多边形中的圆或包含其中心的圆
|
||||||
let mtv: Vector2;
|
let mtv: Vector2;
|
||||||
if (circleCenterInsidePoly) {
|
if (circleCenterInsidePoly) {
|
||||||
mtv = result.normal.scale(Math.sqrt(res.distanceSquared) - circle.radius);
|
mtv = result.value.normal.scale(Math.sqrt(res.distanceSquared) - circle.radius);
|
||||||
} else {
|
} else {
|
||||||
// 如果我们没有距离,这意味着圆心在多边形的边缘上。只需根据它的半径移动它
|
// 如果我们没有距离,这意味着圆心在多边形的边缘上。只需根据它的半径移动它
|
||||||
if (res.distanceSquared === 0) {
|
if (res.distanceSquared === 0) {
|
||||||
mtv = result.normal.scale(circle.radius);
|
mtv = result.value.normal.scale(circle.radius);
|
||||||
} else {
|
} else {
|
||||||
const distance = Math.sqrt(res.distanceSquared);
|
const distance = Math.sqrt(res.distanceSquared);
|
||||||
mtv = poly2Circle
|
mtv = poly2Circle
|
||||||
@@ -118,8 +128,8 @@ module es {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.minimumTranslationVector = mtv;
|
result.value.minimumTranslationVector = mtv;
|
||||||
result.point = res.closestPoint.add(polygon.position);
|
result.value.point = res.closestPoint.add(polygon.position);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
module es {
|
module es {
|
||||||
export class ShapeCollisionsLine {
|
export class ShapeCollisionsLine {
|
||||||
public static lineToPoly(start: Vector2, end: Vector2, polygon: Polygon, hit: RaycastHit = new RaycastHit()): boolean {
|
public static lineToPoly(start: Vector2, end: Vector2, polygon: Polygon, hit: Out<RaycastHit>): boolean {
|
||||||
|
hit.value = new RaycastHit();
|
||||||
|
|
||||||
let normal = Vector2.zero;
|
let normal = Vector2.zero;
|
||||||
let intersectionPoint = Vector2.zero;
|
let intersectionPoint = Vector2.zero;
|
||||||
let fraction = Number.MAX_VALUE;
|
let fraction = Number.MAX_VALUE;
|
||||||
@@ -31,7 +33,7 @@ module es {
|
|||||||
if (hasIntersection){
|
if (hasIntersection){
|
||||||
normal = normal.normalize();
|
normal = normal.normalize();
|
||||||
const distance = Vector2.distance(start, intersectionPoint);
|
const distance = Vector2.distance(start, intersectionPoint);
|
||||||
hit.setValues(fraction, distance, intersectionPoint, normal);
|
hit.value.setValues(fraction, distance, intersectionPoint, normal);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +65,9 @@ module es {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static lineToCircle(start: Vector2, end: Vector2, s: Circle, hit: RaycastHit): boolean{
|
public static lineToCircle(start: Vector2, end: Vector2, s: Circle, hit: Out<RaycastHit>): boolean{
|
||||||
|
hit.value = new RaycastHit();
|
||||||
|
|
||||||
// 计算这里的长度并分别对d进行标准化,因为如果我们命中了我们需要它来得到分数
|
// 计算这里的长度并分别对d进行标准化,因为如果我们命中了我们需要它来得到分数
|
||||||
const lineLength = Vector2.distance(start, end);
|
const lineLength = Vector2.distance(start, end);
|
||||||
const d = Vector2.divideScaler(end.sub(start), lineLength);
|
const d = Vector2.divideScaler(end.sub(start), lineLength);
|
||||||
@@ -81,16 +85,16 @@ module es {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 射线相交圆
|
// 射线相交圆
|
||||||
hit.fraction = -b - Math.sqrt(discr);
|
hit.value.fraction = -b - Math.sqrt(discr);
|
||||||
|
|
||||||
// 如果分数为负数,射线从圈内开始,
|
// 如果分数为负数,射线从圈内开始,
|
||||||
if (hit.fraction < 0)
|
if (hit.value.fraction < 0)
|
||||||
hit.fraction = 0;
|
hit.value.fraction = 0;
|
||||||
|
|
||||||
hit.point = start.add(d.scale(hit.fraction));
|
hit.value.point = start.add(d.scale(hit.value.fraction));
|
||||||
hit.distance = Vector2.distance(start, hit.point);
|
hit.value.distance = Vector2.distance(start, hit.value.point);
|
||||||
hit.normal = hit.point.sub(s.position).normalize();
|
hit.value.normal = hit.value.point.sub(s.position).normalize();
|
||||||
hit.fraction = hit.distance / lineLength;
|
hit.value.fraction = hit.value.distance / lineLength;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
module es {
|
module es {
|
||||||
export class ShapeCollisionsPoint {
|
export class ShapeCollisionsPoint {
|
||||||
public static pointToCircle(point: Vector2, circle: Circle, result: CollisionResult): boolean {
|
public static pointToCircle(point: Vector2, circle: Circle, result: Out<CollisionResult>): boolean {
|
||||||
|
result.value = new CollisionResult();
|
||||||
|
|
||||||
let distanceSquared = Vector2.sqrDistance(point, circle.position);
|
let distanceSquared = Vector2.sqrDistance(point, circle.position);
|
||||||
let sumOfRadii = 1 + circle.radius;
|
let sumOfRadii = 1 + circle.radius;
|
||||||
let collided = distanceSquared < sumOfRadii * sumOfRadii;
|
let collided = distanceSquared < sumOfRadii * sumOfRadii;
|
||||||
if (collided) {
|
if (collided) {
|
||||||
result.normal = point.sub(circle.position).normalize();
|
result.value.normal = point.sub(circle.position).normalize();
|
||||||
let depth = sumOfRadii - Math.sqrt(distanceSquared);
|
let depth = sumOfRadii - Math.sqrt(distanceSquared);
|
||||||
result.minimumTranslationVector = result.normal.scale(-depth);;
|
result.value.minimumTranslationVector = result.value.normal.scale(-depth);;
|
||||||
result.point = circle.position.add(result.normal.scale(circle.radius));
|
result.value.point = circle.position.add(result.value.normal.scale(circle.radius));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -16,11 +18,15 @@ module es {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static pointToBox(point: Vector2, box: Box, result: CollisionResult = new CollisionResult()) {
|
public static pointToBox(point: Vector2, box: Box, result: Out<CollisionResult>) {
|
||||||
|
result.value = new CollisionResult();
|
||||||
|
|
||||||
if (box.containsPoint(point)) {
|
if (box.containsPoint(point)) {
|
||||||
// 在方框的空间里找到点
|
// 在方框的空间里找到点
|
||||||
result.point = box.bounds.getClosestPointOnRectangleBorderToPoint(point, result.normal);
|
const normal = new Out<Vector2>();
|
||||||
result.minimumTranslationVector = point.sub(result.point);
|
result.value.point = box.bounds.getClosestPointOnRectangleBorderToPoint(point, normal);
|
||||||
|
result.value.normal = normal.value;
|
||||||
|
result.value.minimumTranslationVector = point.sub(result.value.point);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -28,17 +34,17 @@ module es {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static pointToPoly(point: Vector2, poly: Polygon, result: CollisionResult = new CollisionResult()): boolean {
|
public static pointToPoly(point: Vector2, poly: Polygon, result: Out<CollisionResult>): boolean {
|
||||||
|
result.value = new CollisionResult();
|
||||||
|
|
||||||
if (poly.containsPoint(point)) {
|
if (poly.containsPoint(point)) {
|
||||||
const res = Polygon.getClosestPointOnPolygonToPoint(
|
const res = Polygon.getClosestPointOnPolygonToPoint(
|
||||||
poly.points,
|
poly.points,
|
||||||
point.sub(poly.position)
|
point.sub(poly.position)
|
||||||
);
|
);
|
||||||
result.normal = res.edgeNormal;
|
result.value.normal = res.edgeNormal;
|
||||||
result.minimumTranslationVector = result.normal.scale(
|
result.value.minimumTranslationVector = result.value.normal.scale(Math.sqrt(res.distanceSquared));
|
||||||
Math.sqrt(res.distanceSquared)
|
result.value.point = res.closestPoint.sub(poly.position);
|
||||||
);
|
|
||||||
result.point = res.closestPoint.sub(poly.position);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ module es {
|
|||||||
* @param second
|
* @param second
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
public static polygonToPolygon(first: Polygon, second: Polygon, result: CollisionResult): boolean {
|
public static polygonToPolygon(first: Polygon, second: Polygon, result: Out<CollisionResult>): boolean {
|
||||||
|
result.value = new CollisionResult();
|
||||||
let isIntersecting = true;
|
let isIntersecting = true;
|
||||||
|
|
||||||
const firstEdges = first.edgeNormals;
|
const firstEdges = first.edgeNormals;
|
||||||
@@ -56,8 +57,8 @@ module es {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 利用最小平移向量对多边形进行推入。
|
// 利用最小平移向量对多边形进行推入。
|
||||||
result.normal = translationAxis;
|
result.value.normal = translationAxis;
|
||||||
result.minimumTranslationVector = translationAxis.scale(-minIntervalDistance);
|
result.value.minimumTranslationVector = translationAxis.scale(-minIntervalDistance);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ module es {
|
|||||||
*/
|
*/
|
||||||
public overlapRectangle(rect: Rectangle, results: Collider[], layerMask: number) {
|
public overlapRectangle(rect: Rectangle, results: Collider[], layerMask: number) {
|
||||||
this._overlapTestBox.updateBox(rect.width, rect.height);
|
this._overlapTestBox.updateBox(rect.width, rect.height);
|
||||||
this._overlapTestBox.position = rect.location.clone();
|
this._overlapTestBox.position = rect.location;
|
||||||
|
|
||||||
let resultCounter = 0;
|
let resultCounter = 0;
|
||||||
let potentials = this.aabbBroadphase(rect, null, layerMask);
|
let potentials = this.aabbBroadphase(rect, null, layerMask);
|
||||||
@@ -410,15 +410,16 @@ module es {
|
|||||||
const colliderBounds = potential.bounds;
|
const colliderBounds = potential.bounds;
|
||||||
const res = colliderBounds.rayIntersects(this._ray);
|
const res = colliderBounds.rayIntersects(this._ray);
|
||||||
if (res.intersected && res.distance <= 1) {
|
if (res.intersected && res.distance <= 1) {
|
||||||
if (potential.shape.collidesWithLine(this._ray.start, this._ray.end, this._tempHit)) {
|
let tempHit = new Out<RaycastHit>(this._tempHit);
|
||||||
|
if (potential.shape.collidesWithLine(this._ray.start, this._ray.end, tempHit)) {
|
||||||
// 检查一下,我们应该排除这些射线,射线cast是否在碰撞器中开始
|
// 检查一下,我们应该排除这些射线,射线cast是否在碰撞器中开始
|
||||||
if (!Physics.raycastsStartInColliders && potential.shape.containsPoint(this._ray.start))
|
if (!Physics.raycastsStartInColliders && potential.shape.containsPoint(this._ray.start))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO: 确保碰撞点在当前单元格中,如果它没有保存它以供以后计算
|
// TODO: 确保碰撞点在当前单元格中,如果它没有保存它以供以后计算
|
||||||
|
|
||||||
this._tempHit.collider = potential;
|
tempHit.value.collider = potential;
|
||||||
this._cellHits.push(this._tempHit);
|
this._cellHits.push(tempHit.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,8 +265,8 @@ module es {
|
|||||||
public static getClosestPointOnRectangleBorderToPoint(rect: Rectangle, point: Vector2) {
|
public static getClosestPointOnRectangleBorderToPoint(rect: Rectangle, point: Vector2) {
|
||||||
// 对于每个轴,如果该点在盒子外面,则将在盒子上,否则不理会它
|
// 对于每个轴,如果该点在盒子外面,则将在盒子上,否则不理会它
|
||||||
let res = es.Vector2.zero;
|
let res = es.Vector2.zero;
|
||||||
res.x = MathHelper.clamp(Math.trunc(point.x), rect.left, rect.right)
|
res.x = MathHelper.clamp(MathHelper.toInt(point.x), rect.left, rect.right)
|
||||||
res.y = MathHelper.clamp(Math.trunc(point.y), rect.top, rect.bottom);
|
res.y = MathHelper.clamp(MathHelper.toInt(point.y), rect.top, rect.bottom);
|
||||||
|
|
||||||
// 如果点在矩形内,我们需要将res推到边框,因为它将在矩形内
|
// 如果点在矩形内,我们需要将res推到边框,因为它将在矩形内
|
||||||
if (rect.contains(res.x, res.y)) {
|
if (rect.contains(res.x, res.y)) {
|
||||||
@@ -327,16 +327,16 @@ module es {
|
|||||||
maxY = pt.y;
|
maxY = pt.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.fromMinMaxVector(new Vector2(Math.trunc(minX), Math.trunc(minY)), new Vector2(Math.trunc(maxX), Math.trunc(maxY)));
|
return this.fromMinMaxVector(new Vector2(MathHelper.toInt(minX), MathHelper.toInt(minY)), new Vector2(MathHelper.toInt(maxX), MathHelper.toInt(maxY)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static calculateBounds(rect: Rectangle, parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2,
|
public static calculateBounds(rect: Rectangle, parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2,
|
||||||
rotation: number, width: number, height: number) {
|
rotation: number, width: number, height: number) {
|
||||||
if (rotation == 0) {
|
if (rotation == 0) {
|
||||||
rect.x = Math.trunc(parentPosition.x + position.x - origin.x * scale.x);
|
rect.x = MathHelper.toInt(parentPosition.x + position.x - origin.x * scale.x);
|
||||||
rect.y = Math.trunc(parentPosition.y + position.y - origin.y * scale.y);
|
rect.y = MathHelper.toInt(parentPosition.y + position.y - origin.y * scale.y);
|
||||||
rect.width = Math.trunc(width * scale.x);
|
rect.width = MathHelper.toInt(width * scale.x);
|
||||||
rect.height = Math.trunc(height * scale.y);
|
rect.height = MathHelper.toInt(height * scale.y);
|
||||||
} else {
|
} else {
|
||||||
// 我们需要找到我们的绝对最小/最大值,并据此创建边界
|
// 我们需要找到我们的绝对最小/最大值,并据此创建边界
|
||||||
let worldPosX = parentPosition.x + position.x;
|
let worldPosX = parentPosition.x + position.x;
|
||||||
@@ -366,14 +366,14 @@ module es {
|
|||||||
Vector2Ext.transformR(bottomRight, transformMatrix, bottomRight);
|
Vector2Ext.transformR(bottomRight, transformMatrix, bottomRight);
|
||||||
|
|
||||||
// 找出最小值和最大值,这样我们就可以计算出我们的边界框。
|
// 找出最小值和最大值,这样我们就可以计算出我们的边界框。
|
||||||
let minX = Math.trunc(Math.min(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
let minX = MathHelper.toInt(Math.min(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
||||||
let maxX = Math.trunc(Math.max(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
let maxX = MathHelper.toInt(Math.max(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
||||||
let minY = Math.trunc(Math.min(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
let minY = MathHelper.toInt(Math.min(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
||||||
let maxY = Math.trunc(Math.max(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
let maxY = MathHelper.toInt(Math.max(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
||||||
|
|
||||||
rect.location = new Vector2(minX, minY);
|
rect.location = new Vector2(minX, minY);
|
||||||
rect.width = Math.trunc(maxX - minX);
|
rect.width = MathHelper.toInt(maxX - minX);
|
||||||
rect.height = Math.trunc(maxY - minY);
|
rect.height = MathHelper.toInt(maxY - minY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,10 +383,10 @@ module es {
|
|||||||
* @param scale
|
* @param scale
|
||||||
*/
|
*/
|
||||||
public static scale(rect: Rectangle, scale: Vector2) {
|
public static scale(rect: Rectangle, scale: Vector2) {
|
||||||
rect.x = Math.trunc(rect.x * scale.x);
|
rect.x = MathHelper.toInt(rect.x * scale.x);
|
||||||
rect.y = Math.trunc(rect.y * scale.y);
|
rect.y = MathHelper.toInt(rect.y * scale.y);
|
||||||
rect.width = Math.trunc(rect.width * scale.x);
|
rect.width = MathHelper.toInt(rect.width * scale.x);
|
||||||
rect.height = Math.trunc(rect.height * scale.y);
|
rect.height = MathHelper.toInt(rect.height * scale.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static translate(rect: Rectangle, vec: Vector2) {
|
public static translate(rect: Rectangle, vec: Vector2) {
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
module es {
|
||||||
|
export class Out<T> {
|
||||||
|
public value: T;
|
||||||
|
|
||||||
|
constructor(value: T = null) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user