Files
esengine/source/src/ECS/Components/Physics/Colliders/Collider.ts

211 lines
7.8 KiB
TypeScript
Raw Normal View History

module es {
export abstract class Collider extends Component {
/**
*
*/
public shape: Shape;
/**
* localOffset添加到实体
* /
*/
public get localOffset(): Vector2{
return this._localOffset;
}
2020-07-22 20:07:14 +08:00
/**
* localOffset添加到实体
* /
* @param value
*/
public set localOffset(value: Vector2){
this.setLocalOffset(value);
}
2020-06-15 10:42:06 +08:00
/**
*
*/
public get absolutePosition(): Vector2{
return Vector2.add(this.entity.transform.position, this._localOffset);
}
2020-07-22 20:07:14 +08:00
/**
* transform.rotation
*/
public get rotation(): number{
if (this.shouldColliderScaleAndRotateWithTransform && this.entity)
return this.entity.transform.rotation;
return 0;
}
/**
*
*/
public isTrigger: boolean;
/**
* physicsLayer可以用作过滤器Flags类有帮助位掩码的方法
*/
public physicsLayer = 1 << 0;
/**
* 使
*
*/
public collidesWithLayers = Physics.allLayers;
/**
* true
*/
public shouldColliderScaleAndRotateWithTransform = true;
public get bounds(): Rectangle {
this.shape.recalculateBounds(this);
return this.shape.bounds;
}
/**
*
* 使
*/
public registeredPhysicsBounds: Rectangle = new Rectangle();
protected _colliderRequiresAutoSizing;
protected _localOffset: Vector2 = Vector2.zero;
public _localOffsetLength: number;
/**
*
*/
protected _isParentEntityAddedToScene;
/**
*
*/
protected _isColliderRegistered;
/**
* localOffset添加到实体
*
* @param offset
*/
public setLocalOffset(offset: Vector2): Collider{
if (this._localOffset != offset){
this.unregisterColliderWithPhysicsSystem();
this._localOffset = offset;
this._localOffsetLength = this._localOffset.length();
this.registerColliderWithPhysicsSystem();
}
return this;
}
/**
* true
* @param shouldColliderScaleAndRotationWithTransform
*/
public setShouldColliderScaleAndRotateWithTransform(shouldColliderScaleAndRotationWithTransform: boolean): Collider {
this.shouldColliderScaleAndRotateWithTransform = shouldColliderScaleAndRotationWithTransform;
return this;
}
public onAddedToEntity() {
if (this._colliderRequiresAutoSizing) {
if (!(this instanceof BoxCollider || this instanceof CircleCollider)) {
console.error("Only box and circle colliders can be created automatically");
return;
}
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
if (renderable) {
let bounds = renderable.bounds;
// 这里我们需要大小*反尺度,因为当我们自动调整碰撞器的大小时,它需要没有缩放的渲染
let width = bounds.width / this.entity.scale.x;
let height = bounds.height / this.entity.scale.y;
// 圆碰撞器需要特别注意原点
if (this instanceof CircleCollider){
let circleCollider = this as CircleCollider;
circleCollider.radius = Math.max(width, height) * 0.5;
} else {
this.width = width;
this.height = height;
}
// 获取渲染的中心将其转移到本地坐标并使用它作为碰撞器的localOffset
this.localOffset = Vector2.subtract(bounds.center, this.entity.transform.position);
} else {
console.warn("Collider has no shape and no RenderableComponent. Can't figure out how to size it.");
2020-07-09 14:16:10 +08:00
}
}
this._isParentEntityAddedToScene = true;
this.registerColliderWithPhysicsSystem();
}
public onRemovedFromEntity() {
this.unregisterColliderWithPhysicsSystem();
this._isParentEntityAddedToScene = false;
}
2020-07-09 14:16:10 +08:00
public onEntityTransformChanged(comp: transform.Component) {
if (this._isColliderRegistered)
Physics.updateCollider(this);
}
public onEnabled() {
this.registerColliderWithPhysicsSystem();
}
2020-06-16 00:04:28 +08:00
public onDisabled() {
this.unregisterColliderWithPhysicsSystem();
}
2020-07-08 15:15:15 +08:00
/**
* ()
*/
public registerColliderWithPhysicsSystem() {
// 如果在将我们添加到实体之前更改了origin等属性则实体可以为null
if (this._isParentEntityAddedToScene && !this._isColliderRegistered) {
Physics.addCollider(this);
this._isColliderRegistered = true;
}
}
/**
* ()
*/
public unregisterColliderWithPhysicsSystem() {
if (this._isParentEntityAddedToScene && this._isColliderRegistered) {
Physics.removeCollider(this);
}
this._isColliderRegistered = false;
}
/**
*
* @param other
*/
public overlaps(other: Collider) {
return this.shape.overlaps(other.shape);
}
/**
* ()true
* @param collider
* @param motion
*/
public collidesWith(collider: Collider, motion: Vector2) {
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
let oldPosition = this.entity.position;
this.entity.position = Vector2.add(this.entity.position, motion);
let result = this.shape.collidesWithShape(collider.shape);
if (result)
result.collider = collider;
// 将图形位置返回到检查前的位置
this.entity.position = oldPosition;
2020-07-09 14:16:10 +08:00
return result;
2020-07-09 14:16:10 +08:00
}
}
}