abstract class Collider extends Component implements IUpdatable { /** 对撞机的基本形状 */ public shape: Shape; /** 在处理冲突时,physicsLayer可以用作过滤器。Flags类有帮助位掩码的方法。 */ public physicsLayer = 1 << 0; /** 如果这个碰撞器是一个触发器,它将不会引起碰撞,但它仍然会触发事件 */ public isTrigger: boolean; /** * 这个对撞机在物理系统注册时的边界。 * 存储这个允许我们始终能够安全地从物理系统中移除对撞机,即使它在试图移除它之前已经被移动了。 */ public registeredPhysicsBounds: Rectangle = new Rectangle(); /** 如果为true,碰撞器将根据附加的变换缩放和旋转 */ public shouldColliderScaleAndRotateWithTransform = true; /** 默认为所有层。 */ public collidesWithLayers = Physics.allLayers; public _localOffsetLength: number; /** 标记来跟踪我们的实体是否被添加到场景中 */ protected _isParentEntityAddedToScene; protected _colliderRequiresAutoSizing; protected _localOffset: Vector2 = new Vector2(0, 0); /** 标记来记录我们是否注册了物理系统 */ protected _isColliderRegistered; public get bounds(): Rectangle { this.shape.recalculateBounds(this); return this.shape.bounds; } public get localOffset() { return this._localOffset; } /** * 将localOffset添加到实体。获取碰撞器的最终位置。这允许您向一个实体添加多个碰撞器并分别定位它们。 */ public set localOffset(value: Vector2) { this.setLocalOffset(value); } public setLocalOffset(offset: Vector2) { if (this._localOffset != offset) { this.unregisterColliderWithPhysicsSystem(); this._localOffset = offset; this._localOffsetLength = this._localOffset.length(); this.registerColliderWithPhysicsSystem(); } } /** * 父实体会在不同的时间调用它(当添加到场景,启用,等等) */ 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.shape.position; this.shape.position = Vector2.add(this.shape.position, motion); let result = this.shape.collidesWithShape(collider.shape); if (result) result.collider = collider; // 将图形位置返回到检查前的位置 this.shape.position = oldPosition; return result; } public onAddedToEntity() { if (this._colliderRequiresAutoSizing) { if (!(this instanceof BoxCollider || this instanceof CircleCollider)) { console.error("Only box and circle colliders can be created automatically"); } let renderable = this.entity.getComponent(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; this.localOffset = bounds.location; } else { let boxCollider = this; boxCollider.width = width; boxCollider.height = height; this.localOffset = bounds.location; } } else { console.warn("Collider has no shape and no RenderableComponent. Can't figure out how to size it."); } } this._isParentEntityAddedToScene = true; this.registerColliderWithPhysicsSystem(); } public onRemovedFromEntity() { this.unregisterColliderWithPhysicsSystem(); this._isParentEntityAddedToScene = false; } public onEnabled() { this.registerColliderWithPhysicsSystem(); } public onDisabled() { this.unregisterColliderWithPhysicsSystem(); } public onEntityTransformChanged(comp: TransformComponent) { if (this._isColliderRegistered) Physics.updateCollider(this); } public update(){ let renderable = this.entity.getComponent(RenderableComponent); if (renderable){ this.$setX(renderable.x + this.localOffset.x); this.$setY(renderable.y + this.localOffset.y); } } }