Files
esengine/source/src/Physics/Shapes/Circle.ts

83 lines
3.6 KiB
TypeScript
Raw Normal View History

2020-06-12 08:47:13 +08:00
///<reference path="./Shape.ts" />
2020-07-23 09:10:27 +08:00
module es {
export class Circle extends Shape {
public radius: number;
public _originalRadius: number;
2020-06-12 08:47:13 +08:00
2020-07-23 09:10:27 +08:00
constructor(radius: number) {
super();
this.radius = radius;
this._originalRadius = radius;
}
2020-07-20 16:38:49 +08:00
2021-04-28 14:43:48 +08:00
public recalculateBounds(collider: Collider) {
2020-07-23 09:10:27 +08:00
// 如果我们没有旋转或不关心TRS我们使用localOffset作为中心
this.center = collider.localOffset;
2020-07-23 09:10:27 +08:00
if (collider.shouldColliderScaleAndRotateWithTransform) {
// 我们只将直线缩放为一个圆,所以我们将使用最大值
let scale = collider.entity.transform.scale;
let hasUnitScale = scale.x == 1 && scale.y == 1;
let maxScale = Math.max(scale.x, scale.y);
this.radius = this._originalRadius * maxScale;
2020-07-23 09:10:27 +08:00
if (collider.entity.transform.rotation != 0) {
// 为了处理偏移原点的旋转,我们只需要将圆心围绕(0,0)在一个圆上移动我们的偏移量就是0角
let offsetAngle = Math.atan2(collider.localOffset.y, collider.localOffset.x) * MathHelper.Rad2Deg;
let offsetLength = hasUnitScale ? collider._localOffsetLength : Vector2.multiply(collider.localOffset, collider.entity.transform.scale).length();
2020-08-27 18:48:20 +08:00
this.center = MathHelper.pointOnCirlce(Vector2.zero, offsetLength, collider.entity.transform.rotationDegrees + offsetAngle);
2020-07-23 09:10:27 +08:00
}
}
2020-08-27 18:48:20 +08:00
this.position = Vector2.add(collider.entity.transform.position, this.center);
2020-07-23 09:10:27 +08:00
this.bounds = new Rectangle(this.position.x - this.radius, this.position.y - this.radius, this.radius * 2, this.radius * 2);
}
2020-07-23 09:10:27 +08:00
public overlaps(other: Shape) {
let result: CollisionResult = new CollisionResult();
2020-07-23 09:10:27 +08:00
if (other instanceof Box && (other as Box).isUnrotated)
2020-08-27 18:48:20 +08:00
return Collisions.rectToCircle(other.bounds, this.position, this.radius);
2020-07-23 09:10:27 +08:00
if (other instanceof Circle)
2020-08-27 18:48:20 +08:00
return Collisions.circleToCircle(this.position, this.radius, other.position, (other as Circle).radius);
2020-07-23 09:10:27 +08:00
if (other instanceof Polygon)
2021-04-28 14:43:48 +08:00
return ShapeCollisionsCircle.circleToPolygon(this, other, result);
2020-07-23 09:10:27 +08:00
throw new Error(`overlaps of circle to ${other} are not supported`);
}
public collidesWithShape(other: Shape, result: CollisionResult): boolean {
2020-07-23 09:10:27 +08:00
if (other instanceof Box && (other as Box).isUnrotated) {
2021-04-28 14:43:48 +08:00
return ShapeCollisionsCircle.circleToBox(this, other, result);
2020-07-23 09:10:27 +08:00
}
2020-07-23 09:10:27 +08:00
if (other instanceof Circle) {
2021-04-28 14:43:48 +08:00
return ShapeCollisionsCircle.circleToCircle(this, other, result);
2020-07-23 09:10:27 +08:00
}
2020-06-16 00:04:28 +08:00
2020-07-23 09:10:27 +08:00
if (other instanceof Polygon) {
2021-04-28 14:43:48 +08:00
return ShapeCollisionsCircle.circleToPolygon(this, other, result);
2020-07-23 09:10:27 +08:00
}
2020-06-16 00:04:28 +08:00
2020-07-23 09:10:27 +08:00
throw new Error(`Collisions of Circle to ${other} are not supported`);
}
2020-06-16 00:04:28 +08:00
2021-04-28 14:43:48 +08:00
public collidesWithLine(start: Vector2, end: Vector2, hit: RaycastHit): boolean {
return ShapeCollisionsLine.lineToCircle(start, end, this, hit);
2020-08-03 14:45:57 +08:00
}
/**
*
* @param point
*/
2021-04-28 14:43:48 +08:00
public containsPoint(point: Vector2) {
2020-08-03 14:45:57 +08:00
return (Vector2.subtract(point, this.position)).lengthSquared() <= this.radius * this.radius;
}
public pointCollidesWithShape(point: Vector2, result: CollisionResult): boolean {
2021-04-28 14:43:48 +08:00
return ShapeCollisionsPoint.pointToCircle(point, this, result);
2020-07-23 09:10:27 +08:00
}
}
2020-07-23 09:10:27 +08:00
}