2020-06-12 08:47:13 +08:00
|
|
|
|
abstract class Collider extends Component{
|
|
|
|
|
|
public shape: Shape;
|
|
|
|
|
|
public physicsLayer = 1 << 0;
|
2020-06-12 20:24:51 +08:00
|
|
|
|
public isTrigger: boolean;
|
2020-06-15 10:42:06 +08:00
|
|
|
|
public registeredPhysicsBounds: Rectangle;
|
2020-06-16 00:04:28 +08:00
|
|
|
|
public shouldColliderScaleAndRotationWithTransform = true;
|
|
|
|
|
|
public collidesWithLayers = Physics.allLayers;
|
2020-06-15 10:42:06 +08:00
|
|
|
|
|
2020-06-16 00:04:28 +08:00
|
|
|
|
public _localOffsetLength: number;
|
2020-06-16 11:22:37 +08:00
|
|
|
|
public _isPositionDirty = true;
|
|
|
|
|
|
public _isRotationDirty = true;
|
2020-06-15 10:42:06 +08:00
|
|
|
|
protected _isParentEntityAddedToScene;
|
|
|
|
|
|
protected _colliderRequiresAutoSizing;
|
2020-06-16 11:59:40 +08:00
|
|
|
|
protected _localOffset: Vector2 = new Vector2(0, 0);
|
2020-06-16 16:35:17 +08:00
|
|
|
|
protected _isColliderRegistered;
|
2020-06-12 08:47:13 +08:00
|
|
|
|
|
|
|
|
|
|
public get bounds(): Rectangle {
|
2020-06-15 20:08:21 +08:00
|
|
|
|
if (this._isPositionDirty || this._isRotationDirty){
|
|
|
|
|
|
this.shape.recalculateBounds(this);
|
|
|
|
|
|
this._isPositionDirty = this._isRotationDirty = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-06-12 08:47:13 +08:00
|
|
|
|
return this.shape.bounds;
|
|
|
|
|
|
}
|
2020-06-15 10:42:06 +08:00
|
|
|
|
|
2020-06-15 20:08:21 +08:00
|
|
|
|
public get localOffset(){
|
|
|
|
|
|
return this._localOffset;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public set localOffset(value: Vector2){
|
|
|
|
|
|
this.setLocalOffset(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public setLocalOffset(offset: Vector2){
|
|
|
|
|
|
if (this._localOffset != offset){
|
|
|
|
|
|
this.unregisterColliderWithPhysicsSystem();
|
|
|
|
|
|
this._localOffset = offset;
|
2020-06-16 00:04:28 +08:00
|
|
|
|
this._localOffsetLength = this._localOffset.length();
|
2020-06-15 20:08:21 +08:00
|
|
|
|
this._isPositionDirty = true;
|
|
|
|
|
|
this.registerColliderWithPhysicsSystem();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public registerColliderWithPhysicsSystem(){
|
2020-06-16 16:35:17 +08:00
|
|
|
|
if (this._isParentEntityAddedToScene && !this._isColliderRegistered){
|
2020-06-15 20:08:21 +08:00
|
|
|
|
Physics.addCollider(this);
|
2020-06-16 16:35:17 +08:00
|
|
|
|
this._isColliderRegistered = true;
|
2020-06-15 20:08:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public unregisterColliderWithPhysicsSystem(){
|
2020-06-16 16:35:17 +08:00
|
|
|
|
if (this._isParentEntityAddedToScene && this._isColliderRegistered){
|
2020-06-15 20:08:21 +08:00
|
|
|
|
Physics.removeCollider(this);
|
|
|
|
|
|
}
|
2020-06-16 16:35:17 +08:00
|
|
|
|
this._isColliderRegistered = false;
|
2020-06-15 20:08:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-06-16 00:04:28 +08:00
|
|
|
|
public overlaps(other: Collider){
|
|
|
|
|
|
return this.shape.overlaps(other.shape);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-07-08 15:15:15 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 检查这个与运动应用的碰撞器(移动向量)是否与碰撞器碰撞。如果是这样,将返回true,并且结果将填充碰撞数据。
|
|
|
|
|
|
* @param collider
|
|
|
|
|
|
* @param motion
|
|
|
|
|
|
*/
|
2020-06-16 11:22:37 +08:00
|
|
|
|
public collidesWith(collider: Collider, motion: Vector2){
|
2020-07-08 15:15:15 +08:00
|
|
|
|
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
|
2020-06-16 11:22:37 +08:00
|
|
|
|
let oldPosition = this.shape.position;
|
|
|
|
|
|
this.shape.position = Vector2.add(this.shape.position, motion);
|
|
|
|
|
|
|
|
|
|
|
|
let result = this.shape.collidesWithShape(collider.shape);
|
|
|
|
|
|
if (result)
|
|
|
|
|
|
result.collider = collider;
|
|
|
|
|
|
|
2020-07-08 15:15:15 +08:00
|
|
|
|
// 将图形位置返回到检查前的位置
|
2020-06-16 11:22:37 +08:00
|
|
|
|
this.shape.position = oldPosition;
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public onAddedToEntity(){
|
|
|
|
|
|
if (this._colliderRequiresAutoSizing){
|
|
|
|
|
|
if (!(this instanceof BoxCollider)){
|
|
|
|
|
|
console.error("Only box and circle colliders can be created automatically");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
|
2020-06-16 20:22:22 +08:00
|
|
|
|
if (renderable){
|
2020-06-16 11:22:37 +08:00
|
|
|
|
let renderbaleBounds = renderable.bounds;
|
|
|
|
|
|
|
2020-07-08 15:15:15 +08:00
|
|
|
|
// 这里我们需要大小*反尺度,因为当我们自动调整碰撞器的大小时,它需要没有缩放的渲染
|
2020-06-29 15:41:02 +08:00
|
|
|
|
let width = renderbaleBounds.width / this.entity.scale.x;
|
|
|
|
|
|
let height = renderbaleBounds.height / this.entity.scale.y;
|
2020-06-16 11:22:37 +08:00
|
|
|
|
|
|
|
|
|
|
if (this instanceof BoxCollider){
|
|
|
|
|
|
let boxCollider = this as BoxCollider;
|
|
|
|
|
|
boxCollider.width = width;
|
|
|
|
|
|
boxCollider.height = height;
|
|
|
|
|
|
|
2020-07-08 15:15:15 +08:00
|
|
|
|
// 获取渲染的中心,将其转移到本地坐标,并使用它作为碰撞器的localOffset
|
2020-06-29 15:41:02 +08:00
|
|
|
|
this.localOffset = Vector2.subtract(renderbaleBounds.center, this.entity.position);
|
2020-06-16 11:22:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this._isParentEntityAddedToScene = true;
|
|
|
|
|
|
this.registerColliderWithPhysicsSystem();
|
|
|
|
|
|
}
|
2020-06-16 20:22:22 +08:00
|
|
|
|
|
|
|
|
|
|
public onRemovedFromEntity(){
|
|
|
|
|
|
this.unregisterColliderWithPhysicsSystem();
|
|
|
|
|
|
this._isParentEntityAddedToScene = false;
|
|
|
|
|
|
}
|
2020-06-16 11:22:37 +08:00
|
|
|
|
|
2020-06-16 00:04:28 +08:00
|
|
|
|
public onEnabled(){
|
|
|
|
|
|
this.registerColliderWithPhysicsSystem();
|
|
|
|
|
|
this._isPositionDirty = this._isRotationDirty = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public onDisabled(){
|
|
|
|
|
|
this.unregisterColliderWithPhysicsSystem();
|
2020-06-15 10:42:06 +08:00
|
|
|
|
}
|
2020-07-08 15:15:15 +08:00
|
|
|
|
|
|
|
|
|
|
public update(){
|
|
|
|
|
|
let spriteRenderer = this.entity.getComponent(SpriteRenderer);
|
|
|
|
|
|
// 将显示目标设置为碰撞盒
|
|
|
|
|
|
if (spriteRenderer){
|
|
|
|
|
|
this.bounds.x = spriteRenderer.x;
|
|
|
|
|
|
this.bounds.y = spriteRenderer.y;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-12 08:47:13 +08:00
|
|
|
|
}
|