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

271 lines
10 KiB
TypeScript
Raw Normal View History

module es {
2021-03-29 17:28:58 +08:00
export class Collider extends Component {
/**
*
*/
public shape: Shape;
/**
2020-07-28 16:25:20 +08:00
*
*/
public isTrigger: boolean = false;
/**
2020-07-28 16:25:20 +08:00
* physicsLayer可以用作过滤器Flags类有帮助位掩码的方法
*/
2020-08-27 18:48:20 +08:00
public physicsLayer = new Ref(1 << 0);
2020-07-28 16:25:20 +08:00
/**
* 使
*
*/
2020-08-27 18:48:20 +08:00
public collidesWithLayers: Ref<number> = new Ref(Physics.allLayers);
2020-07-28 16:25:20 +08:00
/**
* true
*/
public shouldColliderScaleAndRotateWithTransform = true;
/**
*
* 使
*/
public registeredPhysicsBounds: Rectangle = new Rectangle();
2020-12-27 22:23:29 +08:00
protected _colliderRequiresAutoSizing: boolean;
2020-07-28 16:25:20 +08:00
public _localOffsetLength: number;
public _isPositionDirty: boolean = true;
public _isRotationDirty: boolean = true;
/**
*
*/
protected _isParentEntityAddedToScene;
/**
*
*/
protected _isColliderRegistered;
2020-06-15 10:42:06 +08:00
/**
*
*/
2020-07-23 13:25:10 +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
*/
2020-07-23 13:25:10 +08:00
public get rotation(): number {
2020-12-27 22:23:29 +08:00
if (this.shouldColliderScaleAndRotateWithTransform && this.entity != null)
return this.entity.transform.rotation;
return 0;
}
public get bounds(): Rectangle {
2020-07-28 16:25:20 +08:00
if (this._isPositionDirty || this._isRotationDirty) {
2020-07-23 13:25:10 +08:00
this.shape.recalculateBounds(this);
this._isPositionDirty = this._isRotationDirty = false;
}
return this.shape.bounds;
}
protected _localOffset: Vector2 = Vector2.zero;
/**
2020-07-28 16:25:20 +08:00
* localOffset添加到实体
* /
*/
2020-07-28 16:25:20 +08:00
public get localOffset(): Vector2 {
return this._localOffset;
}
/**
2020-07-28 16:25:20 +08:00
* localOffset添加到实体
* /
* @param value
*/
2020-07-28 16:25:20 +08:00
public set localOffset(value: Vector2) {
this.setLocalOffset(value);
}
2020-07-23 13:25:10 +08:00
/**
* localOffset添加到实体
*
* @param offset
*/
2020-07-23 13:25:10 +08:00
public setLocalOffset(offset: Vector2): Collider {
2020-12-27 22:23:29 +08:00
if (!this._localOffset.equals(offset)) {
this.unregisterColliderWithPhysicsSystem();
this._localOffset = offset;
this._localOffsetLength = this._localOffset.length();
2020-07-23 13:25:10 +08:00
this._isPositionDirty = true;
this.registerColliderWithPhysicsSystem();
}
return this;
}
/**
* true
* @param shouldColliderScaleAndRotationWithTransform
*/
public setShouldColliderScaleAndRotateWithTransform(shouldColliderScaleAndRotationWithTransform: boolean): Collider {
this.shouldColliderScaleAndRotateWithTransform = shouldColliderScaleAndRotationWithTransform;
2020-07-23 13:25:10 +08:00
this._isPositionDirty = this._isRotationDirty = true;
return this;
}
public onAddedToEntity() {
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) {
2020-07-23 13:25:10 +08:00
switch (comp) {
case transform.Component.position:
this._isPositionDirty = true;
break;
case transform.Component.scale:
this._isPositionDirty = true;
break;
case transform.Component.rotation:
this._isRotationDirty = true;
break;
}
if (this._isColliderRegistered)
Physics.updateCollider(this);
}
public onEnabled() {
this.registerColliderWithPhysicsSystem();
2020-07-23 13:25:10 +08:00
this._isPositionDirty = this._isRotationDirty = true;
}
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): boolean {
return this.shape.overlaps(other.shape);
}
/**
* ()true
* @param collider
* @param motion
* @param result
*/
public collidesWith(collider: Collider, motion: Vector2, result: CollisionResult = new CollisionResult()): boolean {
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
let oldPosition = this.entity.position.clone();
this.entity.position = Vector2.add(this.entity.position, motion);
let didCollide = this.shape.collidesWithShape(collider.shape, result);
if (didCollide)
result.collider = collider;
// 将图形位置返回到检查前的位置
this.entity.position = oldPosition;
2020-07-09 14:16:10 +08:00
return didCollide;
2020-07-09 14:16:10 +08:00
}
/**
* true
* @param collider
* @param result
*/
public collidesWithNonMotion(collider: Collider, result: CollisionResult = new CollisionResult()): boolean {
if (this.shape.collidesWithShape(collider.shape, result)) {
result.collider = collider;
return true;
}
return false;
}
2021-04-14 10:44:33 +08:00
2021-04-14 10:51:18 +08:00
/**
*
* true使
* @param motion
* @param result
*/
public collidesWithAny(motion: Vector2, result: CollisionResult) {
// 在我们的新位置上获取我们可能会碰到的任何东西
let colliderBounds = this.bounds.clone();
colliderBounds.x += motion.x;
colliderBounds.y += motion.y;
let neighbors = Physics.boxcastBroadphaseExcludingSelf(this, colliderBounds, this.collidesWithLayers.value);
// 更改形状位置,使其处于移动后的位置,以便我们检查是否有重叠
let oldPosition = this.shape.position.clone();
this.shape.position = Vector2.add(this.shape.position, motion);
let didCollide = false;
for (let neighbor of neighbors) {
if (neighbor.isTrigger)
continue;
if (this.collidesWithNonMotion(neighbor, result)) {
motion = Vector2.subtract(motion, result.minimumTranslationVector);
this.shape.position = Vector2.subtract(this.shape.position, result.minimumTranslationVector);
didCollide = true;
}
}
// 将形状位置返回到检查之前的位置
this.shape.position = oldPosition;
return didCollide;
}
2021-04-14 10:44:33 +08:00
/**
*
* @param result
*/
2021-04-14 10:51:18 +08:00
public collidesWithAnyNonMotion(result: CollisionResult = new CollisionResult()) {
2021-04-14 10:44:33 +08:00
// 在我们的新位置上获取我们可能会碰到的任何东西
let neighbors = Physics.boxcastBroadphaseExcludingSelfNonRect(this, this.collidesWithLayers.value);
for (let neighbor of neighbors) {
if (neighbor.isTrigger)
continue;
if (this.collidesWithNonMotion(neighbor, result))
return true;
}
return false;
}
2020-07-09 14:16:10 +08:00
}
}