Files
esengine/source/src/ECS/Components/Physics/Mover.ts

98 lines
4.1 KiB
TypeScript
Raw Normal View History

2020-07-23 09:10:27 +08:00
module es {
2020-07-08 18:12:17 +08:00
/**
2020-07-23 09:10:27 +08:00
*
* ITriggerListener接口用于管理对移动过程中违反的任何触发器的回调
* move方法
*
* ITriggerListener
2020-07-08 18:12:17 +08:00
*/
2020-07-23 09:10:27 +08:00
export class Mover extends Component {
private _triggerHelper: ColliderTriggerHelper;
2020-07-28 16:25:20 +08:00
public onAddedToEntity() {
2020-07-23 09:10:27 +08:00
this._triggerHelper = new ColliderTriggerHelper(this.entity);
}
2020-07-23 09:10:27 +08:00
/**
*
* @param motion
* @param collisionResult
2020-07-23 09:10:27 +08:00
*/
2020-07-28 16:25:20 +08:00
public calculateMovement(motion: Vector2, collisionResult: CollisionResult): boolean {
2021-05-27 18:32:38 +08:00
let collider = null;
for (let i = 0; i < this.entity.components.buffer.length; i++) {
let component = this.entity.components.buffer[i];
if (component instanceof Collider) {
collider = component;
break;
}
}
if (collider == null || this._triggerHelper == null) {
return false;
2020-07-23 09:10:27 +08:00
}
2020-07-23 09:10:27 +08:00
// 移动所有的非触发碰撞器并获得最近的碰撞
let colliders: Collider[] = this.entity.getComponents(Collider);
2020-07-28 16:25:20 +08:00
for (let i = 0; i < colliders.length; i++) {
2020-07-23 09:10:27 +08:00
let collider = colliders[i];
2020-07-23 09:10:27 +08:00
// 不检测触发器 在我们移动后会重新访问它
if (collider.isTrigger)
continue;
// 获取我们在新位置可能发生碰撞的任何东西
let bounds = collider.bounds.clone();
2020-07-23 09:10:27 +08:00
bounds.x += motion.x;
bounds.y += motion.y;
2020-08-27 18:48:20 +08:00
let neighbors = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers.value);
2020-07-23 09:10:27 +08:00
2020-12-03 10:24:30 +08:00
neighbors.forEach(value => {
let neighbor = value;
2020-07-23 09:10:27 +08:00
// 不检测触发器
if (neighbor.isTrigger)
2020-12-03 10:24:30 +08:00
return;
2020-07-23 09:10:27 +08:00
let _internalcollisionResult: CollisionResult = new CollisionResult();
2020-07-28 16:25:20 +08:00
if (collider.collidesWith(neighbor, motion, _internalcollisionResult)) {
2020-07-23 09:10:27 +08:00
// 如果碰撞 则退回之前的移动量
motion.subtract(_internalcollisionResult.minimumTranslationVector);
2020-07-23 09:10:27 +08:00
// 如果我们碰到多个对象,为了简单起见,只取第一个。
2020-07-28 16:25:20 +08:00
if (_internalcollisionResult.collider != null) {
2020-07-23 09:10:27 +08:00
collisionResult = _internalcollisionResult;
}
}
2020-12-03 10:24:30 +08:00
});
}
2020-07-23 09:10:27 +08:00
ListPool.free(colliders);
return collisionResult.collider != null;
2020-07-23 09:10:27 +08:00
}
2020-07-23 09:10:27 +08:00
/**
* calculatemomovement应用到实体并更新triggerHelper
* @param motion
*/
2020-07-28 16:25:20 +08:00
public applyMovement(motion: Vector2) {
2020-07-23 09:10:27 +08:00
// 移动实体到它的新位置,如果我们有一个碰撞,否则移动全部数量。当碰撞发生时,运动被更新
this.entity.position = Vector2.add(this.entity.position, motion);
// 对所有是触发器的碰撞器与所有宽相位碰撞器进行重叠检查。任何重叠都会导致触发事件。
if (this._triggerHelper)
this._triggerHelper.update();
}
2020-07-23 09:10:27 +08:00
/**
* calculateMovement和applyMovement来移动考虑碰撞的实体;
* @param motion
* @param collisionResult
2020-07-23 09:10:27 +08:00
*/
2020-07-28 16:25:20 +08:00
public move(motion: Vector2, collisionResult: CollisionResult) {
this.calculateMovement(motion, collisionResult);
2020-07-23 09:10:27 +08:00
this.applyMovement(motion);
return collisionResult.collider != null;
2020-07-23 09:10:27 +08:00
}
}
2020-07-23 09:10:27 +08:00
}