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

161 lines
6.0 KiB
TypeScript
Raw Normal View History

abstract class Collider extends Component {
2020-07-08 18:12:17 +08:00
/** 对撞机的基本形状 */
2020-06-12 08:47:13 +08:00
public shape: Shape;
2020-07-22 20:07:14 +08:00
protected _localOffset: Vector2 = Vector2.zero;
public get localOffset(){
return this._localOffset;
}
public set localOffset(){
}
public _localOffsetLength: number;
2020-07-08 18:12:17 +08:00
/** 在处理冲突时physicsLayer可以用作过滤器。Flags类有帮助位掩码的方法。 */
2020-06-12 08:47:13 +08:00
public physicsLayer = 1 << 0;
2020-07-08 18:12:17 +08:00
/** 如果这个碰撞器是一个触发器,它将不会引起碰撞,但它仍然会触发事件 */
public isTrigger: boolean;
2020-07-08 18:12:17 +08:00
/**
*
* 使
*/
public registeredPhysicsBounds: Rectangle = new Rectangle();
/** 如果为true碰撞器将根据附加的变换缩放和旋转 */
public shouldColliderScaleAndRotateWithTransform = true;
/** 默认为所有层。 */
2020-06-16 00:04:28 +08:00
public collidesWithLayers = Physics.allLayers;
2020-06-15 10:42:06 +08:00
2020-07-08 18:12:17 +08:00
/** 标记来跟踪我们的实体是否被添加到场景中 */
2020-06-15 10:42:06 +08:00
protected _isParentEntityAddedToScene;
protected _colliderRequiresAutoSizing;
2020-07-08 18:12:17 +08:00
/** 标记来记录我们是否注册了物理系统 */
protected _isColliderRegistered;
2020-06-12 08:47:13 +08:00
public get bounds(): Rectangle {
2020-07-20 16:38:49 +08:00
let shapeBounds = this.shape.bounds;
2020-07-22 20:07:14 +08:00
let colliderBuonds = new Rectangle(this.entity.x, this.entity.y, shapeBounds.width, shapeBounds.height);
2020-07-20 16:38:49 +08:00
return colliderBuonds;
2020-06-12 08:47:13 +08:00
}
2020-06-15 10:42:06 +08:00
2020-07-08 18:12:17 +08:00
/**
2020-07-22 20:07:14 +08:00
* localOffset添加到实体
*
* @param offset
2020-07-08 18:12:17 +08:00
*/
2020-07-22 20:07:14 +08:00
public setLocalOffset(offset: Vector2): Collider{
if (this._localOffset != offset){
this.unregisterColliderWithPhysicsSystem();
2020-07-09 14:16:10 +08:00
this._localOffset = offset;
2020-06-16 00:04:28 +08:00
this._localOffsetLength = this._localOffset.length();
this.registerColliderWithPhysicsSystem();
}
2020-07-22 20:07:14 +08:00
return this;
}
2020-07-08 18:12:17 +08:00
/**
* ()
*/
2020-07-09 14:16:10 +08:00
public registerColliderWithPhysicsSystem() {
2020-07-08 18:12:17 +08:00
// 如果在将我们添加到实体之前更改了origin等属性则实体可以为null
2020-07-09 14:16:10 +08:00
if (this._isParentEntityAddedToScene && !this._isColliderRegistered) {
Physics.addCollider(this);
this._isColliderRegistered = true;
}
}
2020-07-08 18:12:17 +08:00
/**
* ()
*/
2020-07-09 14:16:10 +08:00
public unregisterColliderWithPhysicsSystem() {
if (this._isParentEntityAddedToScene && this._isColliderRegistered) {
Physics.removeCollider(this);
}
this._isColliderRegistered = false;
}
2020-07-08 18:12:17 +08:00
/**
*
* @param other
*/
2020-07-09 14:16:10 +08:00
public overlaps(other: Collider) {
2020-06-16 00:04:28 +08:00
return this.shape.overlaps(other.shape);
}
2020-07-08 15:15:15 +08:00
/**
* ()true
* @param collider
* @param motion
*/
2020-07-09 14:16:10 +08:00
public collidesWith(collider: Collider, motion: Vector2) {
2020-07-08 15:15:15 +08:00
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
2020-07-22 20:07:14 +08:00
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;
2020-07-08 15:15:15 +08:00
// 将图形位置返回到检查前的位置
2020-07-22 20:07:14 +08:00
this.entity.position = oldPosition;
return result;
}
2020-07-09 14:16:10 +08:00
public onAddedToEntity() {
if (this._colliderRequiresAutoSizing) {
if (!(this instanceof BoxCollider || this instanceof CircleCollider)) {
console.error("Only box and circle colliders can be created automatically");
}
2020-07-09 14:16:10 +08:00
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
if (renderable) {
let bounds = renderable.bounds;
2020-07-09 14:16:10 +08:00
// 这里我们需要大小*反尺度,因为当我们自动调整碰撞器的大小时,它需要没有缩放的渲染
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 {
2020-07-20 16:38:49 +08:00
this.width = width;
this.height = height;
2020-07-09 14:16:10 +08:00
}
2020-07-22 20:07:14 +08:00
// 获取渲染的中心将其转移到本地坐标并使用它作为碰撞器的localOffset
this.localOffset = Vector2.subtract(bounds.center, this.entity.position);
2020-07-09 14:16:10 +08:00
} else {
console.warn("Collider has no shape and no RenderableComponent. Can't figure out how to size it.");
}
}
this._isParentEntityAddedToScene = true;
this.registerColliderWithPhysicsSystem();
}
2020-07-09 14:16:10 +08:00
public onRemovedFromEntity() {
2020-06-16 20:22:22 +08:00
this.unregisterColliderWithPhysicsSystem();
this._isParentEntityAddedToScene = false;
}
2020-07-09 14:16:10 +08:00
public onEnabled() {
2020-06-16 00:04:28 +08:00
this.registerColliderWithPhysicsSystem();
}
2020-07-09 14:16:10 +08:00
public onDisabled() {
2020-06-16 00:04:28 +08:00
this.unregisterColliderWithPhysicsSystem();
2020-06-15 10:42:06 +08:00
}
2020-07-08 15:15:15 +08:00
2020-07-09 14:16:10 +08:00
public onEntityTransformChanged(comp: TransformComponent) {
2020-07-08 18:12:17 +08:00
if (this._isColliderRegistered)
Physics.updateCollider(this);
2020-07-08 15:15:15 +08:00
}
2020-07-09 14:16:10 +08:00
public update(){
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
if (renderable){
2020-07-22 20:07:14 +08:00
this.$setX(renderable.x);
this.$setY(renderable.y);
2020-07-09 14:16:10 +08:00
}
}
2020-06-12 08:47:13 +08:00
}