module es { /** * 辅助类说明了一种处理移动的方法,它考虑了包括触发器在内的所有冲突。 * ITriggerListener接口用于管理对移动过程中违反的任何触发器的回调。 * 一个物体只能通过移动器移动。要正确报告触发器的move方法。 * * 请注意,多个移动者相互交互将多次调用ITriggerListener。 */ export class Mover extends Component { private _triggerHelper: ColliderTriggerHelper; public onAddedToEntity(){ this._triggerHelper = new ColliderTriggerHelper(this.entity); } /** * 计算修改运动矢量的运动,以考虑移动时可能发生的碰撞 * @param motion */ public calculateMovement(motion: Vector2){ let collisionResult = new CollisionResult(); if (!this.entity.getComponent(Collider) || !this._triggerHelper){ return null; } // 移动所有的非触发碰撞器并获得最近的碰撞 let colliders: Collider[] = this.entity.getComponents(Collider); for (let i = 0; i < colliders.length; i ++){ let collider = colliders[i]; // 不检测触发器 在我们移动后会重新访问它 if (collider.isTrigger) continue; // 获取我们在新位置可能发生碰撞的任何东西 let bounds = collider.bounds; bounds.x += motion.x; bounds.y += motion.y; let boxcastResult = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers); bounds = boxcastResult.bounds; let neighbors = boxcastResult.tempHashSet; for (let j = 0; j < neighbors.length; j ++){ let neighbor = neighbors[j]; // 不检测触发器 if (neighbor.isTrigger) continue; let _internalcollisionResult = collider.collidesWith(neighbor, motion); if (_internalcollisionResult){ // 如果碰撞 则退回之前的移动量 motion = Vector2.subtract(motion, _internalcollisionResult.minimumTranslationVector); // 如果我们碰到多个对象,为了简单起见,只取第一个。 if (_internalcollisionResult.collider){ collisionResult = _internalcollisionResult; } } } } ListPool.free(colliders); return {collisionResult: collisionResult, motion: motion}; } /** * 将calculatemomovement应用到实体并更新triggerHelper * @param motion */ public applyMovement(motion: Vector2){ // 移动实体到它的新位置,如果我们有一个碰撞,否则移动全部数量。当碰撞发生时,运动被更新 this.entity.position = Vector2.add(this.entity.position, motion); // 对所有是触发器的碰撞器与所有宽相位碰撞器进行重叠检查。任何重叠都会导致触发事件。 if (this._triggerHelper) this._triggerHelper.update(); } /** * 通过调用calculateMovement和applyMovement来移动考虑碰撞的实体; * @param motion */ public move(motion: Vector2){ let movementResult = this.calculateMovement(motion); let collisionResult = movementResult.collisionResult; motion = movementResult.motion; this.applyMovement(motion); return collisionResult; } } }