collider更改
This commit is contained in:
@@ -24,8 +24,9 @@ abstract class Collider extends Component {
|
||||
protected _isColliderRegistered;
|
||||
|
||||
public get bounds(): Rectangle {
|
||||
this.shape.recalculateBounds(this);
|
||||
return this.shape.bounds;
|
||||
let shapeBounds = this.shape.bounds;
|
||||
let colliderBuonds = new Rectangle(this.x + this.localOffset.x, this.y + this.localOffset.y, shapeBounds.width, shapeBounds.height);
|
||||
return colliderBuonds;
|
||||
}
|
||||
|
||||
public get localOffset() {
|
||||
@@ -118,9 +119,8 @@ abstract class Collider extends Component {
|
||||
|
||||
this.localOffset = bounds.location;
|
||||
} else {
|
||||
let boxCollider = this;
|
||||
boxCollider.width = width;
|
||||
boxCollider.height = height;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.localOffset = bounds.location;
|
||||
}
|
||||
|
||||
@@ -137,6 +137,18 @@ class Rectangle extends egret.Rectangle {
|
||||
|
||||
return boundsPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将egret矩形转化为Rectangle
|
||||
* @param rect
|
||||
*/
|
||||
public setEgretRect(rect: egret.Rectangle): Rectangle{
|
||||
this.x = rect.x;
|
||||
this.y = rect.y;
|
||||
this.width = rect.width;
|
||||
this.height = rect.height;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给定多边形的点,计算边界
|
||||
|
||||
@@ -78,7 +78,7 @@ class Collisions {
|
||||
return Vector2.distanceSquared(circleCenter, point) < radius * radius;
|
||||
}
|
||||
|
||||
public static isRectToCircle(rect: Rectangle, cPosition: Vector2, cRadius: number): boolean {
|
||||
public static isRectToCircle(rect: egret.Rectangle, cPosition: Vector2, cRadius: number): boolean {
|
||||
let ew = rect.width * 0.5;
|
||||
let eh = rect.height * 0.5;
|
||||
let vx = Math.max(0, Math.max(cPosition.x - rect.x) - ew);
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
* 多边形的特殊情况。在进行SAT碰撞检查时,我们只需要检查2个轴而不是8个轴
|
||||
*/
|
||||
class Box extends Polygon {
|
||||
public width: number;
|
||||
public height: number;
|
||||
|
||||
constructor(width: number, height: number){
|
||||
super(Box.buildBox(width, height), true);
|
||||
this.width = width;
|
||||
@@ -32,20 +29,18 @@ class Box extends Polygon {
|
||||
|
||||
public overlaps(other: Shape){
|
||||
// 特殊情况,这一个高性能方式实现,其他情况则使用polygon方法检测
|
||||
if (this.isUnrotated){
|
||||
if (other instanceof Box && other.isUnrotated)
|
||||
return this.bounds.intersects(other.bounds);
|
||||
if (other instanceof Box)
|
||||
return this.bounds.intersects(other.bounds);
|
||||
|
||||
if (other instanceof Circle)
|
||||
return Collisions.isRectToCircle(this.bounds, other.position, other.radius);
|
||||
}
|
||||
if (other instanceof Circle)
|
||||
return Collisions.isRectToCircle(this.bounds, other.position, other.radius);
|
||||
|
||||
return super.overlaps(other);
|
||||
}
|
||||
|
||||
public collidesWithShape(other: Shape){
|
||||
// 特殊情况,这一个高性能方式实现,其他情况则使用polygon方法检测
|
||||
if (this.isUnrotated && other instanceof Box && other.isUnrotated){
|
||||
if (other instanceof Box){
|
||||
return ShapeCollisions.boxToBox(this, other);
|
||||
}
|
||||
|
||||
@@ -76,10 +71,11 @@ class Box extends Polygon {
|
||||
this._originalPoints[i] = this.points[i];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param point
|
||||
*/
|
||||
public containsPoint(point: Vector2){
|
||||
if (this.isUnrotated)
|
||||
return this.bounds.contains(point.x, point.y);
|
||||
|
||||
return super.containsPoint(point);
|
||||
return this.bounds.contains(point.x, point.y);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,10 @@ class Circle extends Shape {
|
||||
public _originalRadius: number;
|
||||
public center = new Vector2();
|
||||
|
||||
public get bounds(){
|
||||
return new Rectangle().setEgretRect(this.getBounds());
|
||||
}
|
||||
|
||||
constructor(radius: number) {
|
||||
super();
|
||||
this.radius = radius;
|
||||
@@ -15,7 +19,7 @@ class Circle extends Shape {
|
||||
}
|
||||
|
||||
public collidesWithShape(other: Shape): CollisionResult {
|
||||
if (other instanceof Box && (other as Box).isUnrotated) {
|
||||
if (other instanceof Box) {
|
||||
return ShapeCollisions.circleToBox(this, other);
|
||||
}
|
||||
|
||||
@@ -30,28 +34,8 @@ class Circle extends Shape {
|
||||
throw new Error(`Collisions of Circle to ${other} are not supported`);
|
||||
}
|
||||
|
||||
public recalculateBounds(collider: Collider) {
|
||||
this.center = collider.localOffset;
|
||||
|
||||
if (collider.shouldColliderScaleAndRotateWithTransform) {
|
||||
let scale = collider.entity.scale;
|
||||
let hasUnitScale = scale.x == 1 && scale.y == 1;
|
||||
let maxScale = Math.max(scale.x, scale.y);
|
||||
this.radius = this._originalRadius * maxScale;
|
||||
|
||||
if (collider.entity.rotation != 0) {
|
||||
let offsetAngle = Math.atan2(collider.localOffset.y, collider.localOffset.x) * MathHelper.Rad2Deg;
|
||||
let offsetLength = hasUnitScale ? collider._localOffsetLength : (Vector2.multiply(collider.localOffset, collider.entity.scale)).length();
|
||||
this.center = MathHelper.pointOnCirlce(Vector2.zero, offsetLength, MathHelper.toDegrees(collider.entity.rotation) + offsetAngle);
|
||||
}
|
||||
}
|
||||
|
||||
this.position = Vector2.add(collider.entity.position, this.center);
|
||||
this.bounds = new Rectangle(this.position.x - this.radius, this.position.y - this.radius, this.radius * 2, this.radius * 2);
|
||||
}
|
||||
|
||||
public overlaps(other: Shape){
|
||||
if (other instanceof Box && (other as Box).isUnrotated)
|
||||
if (other instanceof Box)
|
||||
return Collisions.isRectToCircle(other.bounds, this.position, this.radius);
|
||||
|
||||
if (other instanceof Circle)
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
///<reference path="./Shape.ts" />
|
||||
class Polygon extends Shape {
|
||||
public points: Vector2[];
|
||||
public isUnrotated: boolean = true;
|
||||
private _polygonCenter: Vector2;
|
||||
private _areEdgeNormalsDirty = true;
|
||||
protected _originalPoints: Vector2[];
|
||||
public center = new Vector2();
|
||||
|
||||
public get bounds(){
|
||||
return new Rectangle(0, 0, this.width, this.height);
|
||||
}
|
||||
|
||||
public _edgeNormals: Vector2[];
|
||||
public get edgeNormals(){
|
||||
if (this._areEdgeNormalsDirty)
|
||||
@@ -195,49 +198,4 @@ class Polygon extends Shape {
|
||||
|
||||
return verts;
|
||||
}
|
||||
|
||||
public recalculateBounds(collider: Collider) {
|
||||
// 如果我们没有旋转或不关心TRS我们使用localOffset作为中心,我们会从那开始
|
||||
// this.center = collider.localOffset;
|
||||
let localOffset = collider.localOffset;
|
||||
if (collider.shouldColliderScaleAndRotateWithTransform){
|
||||
let hasUnitScale = true;
|
||||
let tempMat: Matrix2D;
|
||||
let combinedMatrix = Matrix2D.createTranslation(-this._polygonCenter.x, -this._polygonCenter.y);
|
||||
|
||||
if (collider.entity.scale != Vector2.one){
|
||||
tempMat = Matrix2D.createScale(collider.entity.scale.x, collider.entity.scale.y);
|
||||
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
|
||||
|
||||
hasUnitScale = false;
|
||||
|
||||
// 缩放偏移量并将其设置为中心。如果我们有旋转,它会在下面重置
|
||||
let scaledOffset = Vector2.multiply(collider.localOffset, collider.entity.scale);
|
||||
localOffset = scaledOffset;
|
||||
}
|
||||
|
||||
if (collider.entity.rotation != 0){
|
||||
tempMat = Matrix2D.createRotation(collider.entity.rotation, tempMat);
|
||||
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
|
||||
|
||||
// 为了处理偏移原点的旋转我们只需要将圆心在(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.scale)).length();
|
||||
localOffset = MathHelper.pointOnCirlce(Vector2.zero, offsetLength, MathHelper.toDegrees(collider.entity.rotation) + offsetAngle);
|
||||
}
|
||||
|
||||
tempMat = Matrix2D.createTranslation(this._polygonCenter.x, this._polygonCenter.y);
|
||||
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
|
||||
|
||||
// 最后变换原始点
|
||||
Vector2Ext.transform(this._originalPoints, combinedMatrix, this.points);
|
||||
this.isUnrotated = collider.entity.rotation == 0;
|
||||
}
|
||||
|
||||
this.position = Vector2.add(collider.entity.position, localOffset);
|
||||
this.bounds = Rectangle.rectEncompassingPoints(this.points);
|
||||
this.bounds.location = Vector2.add(this.bounds.location, this.position);
|
||||
this.center = localOffset;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
abstract class Shape {
|
||||
public bounds: Rectangle = new Rectangle();
|
||||
abstract class Shape extends egret.DisplayObject {
|
||||
public abstract bounds: Rectangle;
|
||||
public position: Vector2 = Vector2.zero;
|
||||
public abstract center: Vector2;
|
||||
|
||||
public abstract recalculateBounds(collider: Collider);
|
||||
public abstract pointCollidesWithShape(point: Vector2): CollisionResult;
|
||||
public abstract overlaps(other: Shape);
|
||||
public abstract collidesWithShape(other: Shape): CollisionResult;
|
||||
|
||||
@@ -209,26 +209,15 @@ class RaycastResultParser {
|
||||
* 它的主要目的是将int、int x、y坐标散列到单个Uint32键中,使用O(1)查找。
|
||||
*/
|
||||
class NumberDictionary {
|
||||
private _store: Map<number, Collider[]> = new Map<number, Collider[]>();
|
||||
private _store: Map<string, Collider[]> = new Map<string, Collider[]>();
|
||||
|
||||
/**
|
||||
* 根据x和y值计算并返回散列键
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
private getKey(x: number, y: number): number {
|
||||
return Long.fromNumber(x).shiftLeft(32).or(this.intToUint(y)).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param i
|
||||
*/
|
||||
private intToUint(i) {
|
||||
if (i >= 0)
|
||||
return i;
|
||||
else
|
||||
return 4294967296 + i;
|
||||
private getKey(x: number, y: number): string {
|
||||
return Long.fromNumber(x).shiftLeft(32).or(Long.fromNumber(y, false)).toString();
|
||||
}
|
||||
|
||||
public add(x: number, y: number, list: Collider[]) {
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
class RectangleExt {
|
||||
/**
|
||||
* 计算两个矩形的并集。结果将是一个包含其他两个的矩形。
|
||||
* @param first
|
||||
* @param point
|
||||
*/
|
||||
public static union(first: Rectangle, point: Vector2){
|
||||
let rect = new Rectangle(point.x, point.y, 0, 0);
|
||||
let rectResult = first.union(rect);
|
||||
return new Rectangle(rectResult.x, rectResult.y, rectResult.width, rectResult.height);
|
||||
// let rectResult = first.union(rect);
|
||||
let result = new Rectangle();
|
||||
result.x = Math.min(first.x, rect.x);
|
||||
result.y = Math.min(first.y, rect.y);
|
||||
result.width = Math.max(first.right, rect.right) - result.x;
|
||||
result.height = Math.max(first.bottom, result.bottom) - result.y;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user