修复boxcollider碰撞问题
This commit is contained in:
@@ -13,6 +13,10 @@ abstract class Component extends egret.DisplayObjectContainer {
|
||||
this.setEnabled(value);
|
||||
}
|
||||
|
||||
public get localPosition(){
|
||||
return new Vector2(this.entity.x + this.x, this.entity.y + this.y);
|
||||
}
|
||||
|
||||
public setEnabled(isEnabled: boolean){
|
||||
if (this._enabled != isEnabled){
|
||||
this._enabled = isEnabled;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
abstract class Collider extends Component{
|
||||
abstract class Collider extends Component {
|
||||
/** 对撞机的基本形状 */
|
||||
public shape: Shape;
|
||||
/** 在处理冲突时,physicsLayer可以用作过滤器。Flags类有帮助位掩码的方法。 */
|
||||
@@ -24,27 +24,25 @@ abstract class Collider extends Component{
|
||||
protected _isColliderRegistered;
|
||||
|
||||
public get bounds(): Rectangle {
|
||||
// this.shape.recalculateBounds(this);
|
||||
let bds = this.entity.getBounds();
|
||||
return new Rectangle(bds.x, bds.y, bds.width, bds.height);
|
||||
this.shape.recalculateBounds(this);
|
||||
return this.shape.bounds;
|
||||
}
|
||||
|
||||
public get localOffset(){
|
||||
return new Vector2(this.x, this.y);
|
||||
public get localOffset() {
|
||||
return this._localOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将localOffset添加到实体。获取碰撞器的最终位置。这允许您向一个实体添加多个碰撞器并分别定位它们。
|
||||
*/
|
||||
public set localOffset(value: Vector2){
|
||||
public set localOffset(value: Vector2) {
|
||||
this.setLocalOffset(value);
|
||||
}
|
||||
|
||||
public setLocalOffset(offset: Vector2){
|
||||
if (this._localOffset != offset){
|
||||
public setLocalOffset(offset: Vector2) {
|
||||
if (this._localOffset != offset) {
|
||||
this.unregisterColliderWithPhysicsSystem();
|
||||
this.$setX(offset.x);
|
||||
this.$setY(offset.y);
|
||||
this._localOffset = offset;
|
||||
this._localOffsetLength = this._localOffset.length();
|
||||
this.registerColliderWithPhysicsSystem();
|
||||
}
|
||||
@@ -53,9 +51,9 @@ abstract class Collider extends Component{
|
||||
/**
|
||||
* 父实体会在不同的时间调用它(当添加到场景,启用,等等)
|
||||
*/
|
||||
public registerColliderWithPhysicsSystem(){
|
||||
public registerColliderWithPhysicsSystem() {
|
||||
// 如果在将我们添加到实体之前更改了origin等属性,则实体可以为null
|
||||
if (this._isParentEntityAddedToScene && !this._isColliderRegistered){
|
||||
if (this._isParentEntityAddedToScene && !this._isColliderRegistered) {
|
||||
Physics.addCollider(this);
|
||||
this._isColliderRegistered = true;
|
||||
}
|
||||
@@ -64,8 +62,8 @@ abstract class Collider extends Component{
|
||||
/**
|
||||
* 父实体会在不同的时候调用它(从场景中移除,禁用,等等)
|
||||
*/
|
||||
public unregisterColliderWithPhysicsSystem(){
|
||||
if (this._isParentEntityAddedToScene && this._isColliderRegistered){
|
||||
public unregisterColliderWithPhysicsSystem() {
|
||||
if (this._isParentEntityAddedToScene && this._isColliderRegistered) {
|
||||
Physics.removeCollider(this);
|
||||
}
|
||||
this._isColliderRegistered = false;
|
||||
@@ -75,7 +73,7 @@ abstract class Collider extends Component{
|
||||
* 检查这个形状是否与物理系统中的其他对撞机重叠
|
||||
* @param other
|
||||
*/
|
||||
public overlaps(other: Collider){
|
||||
public overlaps(other: Collider) {
|
||||
return this.shape.overlaps(other.shape);
|
||||
}
|
||||
|
||||
@@ -84,7 +82,7 @@ abstract class Collider extends Component{
|
||||
* @param collider
|
||||
* @param motion
|
||||
*/
|
||||
public collidesWith(collider: Collider, motion: Vector2){
|
||||
public collidesWith(collider: Collider, motion: Vector2) {
|
||||
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
|
||||
let oldPosition = this.shape.position;
|
||||
this.shape.position = Vector2.add(this.shape.position, motion);
|
||||
@@ -99,48 +97,60 @@ abstract class Collider extends Component{
|
||||
return result;
|
||||
}
|
||||
|
||||
public onAddedToEntity(){
|
||||
if (this._colliderRequiresAutoSizing){
|
||||
if (!(this instanceof BoxCollider)){
|
||||
public onAddedToEntity() {
|
||||
if (this._colliderRequiresAutoSizing) {
|
||||
if (!(this instanceof BoxCollider)) {
|
||||
console.error("Only box and circle colliders can be created automatically");
|
||||
}
|
||||
|
||||
let bounds = this.entity.getBounds();
|
||||
let renderbaleBounds = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
|
||||
if (renderable) {
|
||||
let bounds = renderable.bounds;
|
||||
|
||||
// 这里我们需要大小*反尺度,因为当我们自动调整碰撞器的大小时,它需要没有缩放的渲染
|
||||
let width = renderbaleBounds.width / this.entity.scale.x;
|
||||
let height = renderbaleBounds.height / this.entity.scale.y;
|
||||
// 这里我们需要大小*反尺度,因为当我们自动调整碰撞器的大小时,它需要没有缩放的渲染
|
||||
let width = bounds.width / this.entity.scale.x;
|
||||
let height = bounds.height / this.entity.scale.y;
|
||||
|
||||
if (this instanceof BoxCollider){
|
||||
let boxCollider = this as BoxCollider;
|
||||
boxCollider.width = width;
|
||||
boxCollider.height = height;
|
||||
if (this instanceof BoxCollider) {
|
||||
let boxCollider = this as BoxCollider;
|
||||
boxCollider.width = width;
|
||||
boxCollider.height = height;
|
||||
|
||||
// 获取渲染的中心,将其转移到本地坐标,并使用它作为碰撞器的localOffset
|
||||
this.localOffset = Vector2.subtract(renderbaleBounds.center, this.entity.position);
|
||||
// 获取渲染的中心,将其转移到本地坐标,并使用它作为碰撞器的localOffset
|
||||
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(){
|
||||
|
||||
public onRemovedFromEntity() {
|
||||
this.unregisterColliderWithPhysicsSystem();
|
||||
this._isParentEntityAddedToScene = false;
|
||||
}
|
||||
|
||||
public onEnabled(){
|
||||
public onEnabled() {
|
||||
this.registerColliderWithPhysicsSystem();
|
||||
}
|
||||
|
||||
public onDisabled(){
|
||||
public onDisabled() {
|
||||
this.unregisterColliderWithPhysicsSystem();
|
||||
}
|
||||
|
||||
public onEntityTransformChanged(comp: TransformComponent){
|
||||
public onEntityTransformChanged(comp: TransformComponent) {
|
||||
if (this._isColliderRegistered)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
|
||||
public update(){
|
||||
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
|
||||
if (renderable){
|
||||
this.$setX(renderable.x + this.localOffset.x);
|
||||
this.$setY(renderable.y + this.localOffset.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,10 @@ class Entity extends egret.DisplayObjectContainer {
|
||||
this.onEntityTransformChanged(TransformComponent.rotation);
|
||||
}
|
||||
|
||||
public get rotation(){
|
||||
return this.$getRotation();
|
||||
}
|
||||
|
||||
public get enabled(){
|
||||
return this._enabled;
|
||||
}
|
||||
@@ -81,6 +85,11 @@ class Entity extends egret.DisplayObjectContainer {
|
||||
this.id = Entity._idGenerator ++;
|
||||
|
||||
this.componentBits = new BitSet();
|
||||
this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
|
||||
}
|
||||
|
||||
private onAddToStage(){
|
||||
this.onEntityTransformChanged(TransformComponent.position);
|
||||
}
|
||||
|
||||
public get updateOrder(){
|
||||
@@ -206,9 +215,14 @@ class Entity extends egret.DisplayObjectContainer {
|
||||
|
||||
public destroy(){
|
||||
this._isDestoryed = true;
|
||||
this.removeEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
|
||||
|
||||
this.scene.entities.remove(this);
|
||||
this.removeChildren();
|
||||
|
||||
if (this.parent)
|
||||
this.parent.removeChild(this);
|
||||
|
||||
for (let i = this.numChildren - 1; i >= 0; i --){
|
||||
let child = this.getChildAt(i);
|
||||
(child as Component).entity.destroy();
|
||||
|
||||
@@ -62,7 +62,7 @@ abstract class SceneTransition {
|
||||
this.isNewSceneLoaded = true;
|
||||
}
|
||||
|
||||
public tickEffectProgressProperty(filter: egret.CustomFilter, duration: number, easeType: Function, reverseDirection = false){
|
||||
public tickEffectProgressProperty(filter: egret.CustomFilter, duration: number, easeType: Function, reverseDirection = false): Promise<boolean>{
|
||||
return new Promise((resolve)=>{
|
||||
let start = reverseDirection ? 1 : 0;
|
||||
let end = reverseDirection ? 0 : 1;
|
||||
|
||||
@@ -10,7 +10,7 @@ class Flags {
|
||||
* @param self
|
||||
* @param flag
|
||||
*/
|
||||
public static isFlagSet(self: number, flag: number){
|
||||
public static isFlagSet(self: number, flag: number): boolean{
|
||||
return (self & flag) != 0;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class Flags {
|
||||
* @param self
|
||||
* @param flag
|
||||
*/
|
||||
public static isUnshiftedFlagSet(self: number, flag: number){
|
||||
public static isUnshiftedFlagSet(self: number, flag: number): boolean{
|
||||
flag = 1 << flag;
|
||||
return (self & flag) != 0;
|
||||
}
|
||||
|
||||
@@ -41,16 +41,6 @@ class Rectangle extends egret.Rectangle {
|
||||
this.top < value.bottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断点是否在矩形内
|
||||
* @param value
|
||||
*/
|
||||
public containsInVec(value: Vector2) {
|
||||
return ((((this.x <= value.x) && (value.x < (this.x + this.width))) &&
|
||||
(this.y <= value.y)) &&
|
||||
(value.y < (this.y + this.height)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所提供的矩形是否在此矩形的边界内
|
||||
* @param value
|
||||
@@ -89,7 +79,7 @@ class Rectangle extends egret.Rectangle {
|
||||
res.y = MathHelper.clamp(point.y, this.top, this.bottom);
|
||||
|
||||
// 如果点在矩形内,我们需要推res到边界,因为它将在矩形内
|
||||
if (this.containsInVec(res)) {
|
||||
if (this.contains(res.x, res.y)) {
|
||||
let dl = res.x - this.left;
|
||||
let dr = this.right - res.x;
|
||||
let dt = res.y - this.top;
|
||||
|
||||
@@ -78,7 +78,7 @@ class Box extends Polygon {
|
||||
|
||||
public containsPoint(point: Vector2){
|
||||
if (this.isUnrotated)
|
||||
return this.bounds.containsInVec(point);
|
||||
return this.bounds.contains(point.x, point.y);
|
||||
|
||||
return super.containsPoint(point);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
class Circle extends Shape {
|
||||
public radius: number;
|
||||
private _originalRadius: number;
|
||||
public center = new Vector2();
|
||||
|
||||
constructor(radius: number) {
|
||||
super();
|
||||
|
||||
@@ -5,6 +5,7 @@ class Polygon extends Shape {
|
||||
private _polygonCenter: Vector2;
|
||||
private _areEdgeNormalsDirty = true;
|
||||
protected _originalPoints: Vector2[];
|
||||
public center = new Vector2();
|
||||
|
||||
public _edgeNormals: Vector2[];
|
||||
public get edgeNormals(){
|
||||
@@ -183,8 +184,8 @@ class Polygon extends Shape {
|
||||
|
||||
public recalculateBounds(collider: Collider) {
|
||||
// 如果我们没有旋转或不关心TRS我们使用localOffset作为中心,我们会从那开始
|
||||
this.center = collider.localOffset;
|
||||
|
||||
// this.center = collider.localOffset;
|
||||
let localOffset = collider.localOffset;
|
||||
if (collider.shouldColliderScaleAndRotateWithTransform){
|
||||
let hasUnitScale = true;
|
||||
let tempMat: Matrix2D;
|
||||
@@ -198,7 +199,7 @@ class Polygon extends Shape {
|
||||
|
||||
// 缩放偏移量并将其设置为中心。如果我们有旋转,它会在下面重置
|
||||
let scaledOffset = Vector2.multiply(collider.localOffset, collider.entity.scale);
|
||||
this.center = scaledOffset;
|
||||
localOffset = scaledOffset;
|
||||
}
|
||||
|
||||
if (collider.entity.rotation != 0){
|
||||
@@ -209,7 +210,7 @@ class Polygon extends Shape {
|
||||
// 我们还需要处理这里的比例所以我们先对偏移进行缩放以得到合适的长度。
|
||||
let offsetAngle = Math.atan2(collider.localOffset.y, collider.localOffset.x) * MathHelper.Rad2Deg;
|
||||
let offsetLength = hasUnitScale ? collider._localOffsetLength : (Vector2.multiply(collider.localOffset, collider.entity.scale)).length();
|
||||
this.center = MathHelper.pointOnCirlce(Vector2.zero, offsetLength, MathHelper.toDegrees(collider.entity.rotation) + offsetAngle);
|
||||
localOffset = MathHelper.pointOnCirlce(Vector2.zero, offsetLength, MathHelper.toDegrees(collider.entity.rotation) + offsetAngle);
|
||||
}
|
||||
|
||||
tempMat = Matrix2D.createTranslation(this._polygonCenter.x, this._polygonCenter.y);
|
||||
@@ -220,8 +221,9 @@ class Polygon extends Shape {
|
||||
this.isUnrotated = collider.entity.rotation == 0;
|
||||
}
|
||||
|
||||
this.position = Vector2.add(collider.entity.position, this.center);
|
||||
this.position = Vector2.add(collider.entity.position, localOffset);
|
||||
this.bounds = Rectangle.rectEncompassingPoints(this.points);
|
||||
this.bounds.location = Vector2.add(this.bounds.location, this.position);
|
||||
this.center = localOffset;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
abstract class Shape {
|
||||
public bounds: Rectangle;
|
||||
public position: Vector2;
|
||||
public center: Vector2;
|
||||
public bounds: Rectangle = new Rectangle();
|
||||
public position: Vector2 = Vector2.zero;
|
||||
public abstract center: Vector2;
|
||||
|
||||
public abstract recalculateBounds(collider: Collider);
|
||||
public abstract pointCollidesWithShape(point: Vector2): CollisionResult;
|
||||
|
||||
@@ -274,7 +274,7 @@ class ShapeCollisions {
|
||||
let result = new CollisionResult();
|
||||
|
||||
let minkowskiDiff = this.minkowskiDifference(first, second);
|
||||
if (minkowskiDiff.containsInVec(new Vector2(0, 0))){
|
||||
if (minkowskiDiff.contains(0, 0)){
|
||||
// 计算MTV。如果它是零,我们就可以称它为非碰撞
|
||||
result.minimumTranslationVector = minkowskiDiff.getClosestPointOnBoundsToOrigin();
|
||||
|
||||
|
||||
@@ -51,11 +51,11 @@ class SpatialHash {
|
||||
let p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||
|
||||
// 更新边界以跟踪网格大小
|
||||
if (!this.gridBounds.containsInVec(new Vector2(p1.x, p1.y))) {
|
||||
if (!this.gridBounds.contains(p1.x, p1.y)) {
|
||||
this.gridBounds = RectangleExt.union(this.gridBounds, p1);
|
||||
}
|
||||
|
||||
if (!this.gridBounds.containsInVec(new Vector2(p2.x, p2.y))) {
|
||||
if (!this.gridBounds.contains(p2.x, p2.y)) {
|
||||
this.gridBounds = RectangleExt.union(this.gridBounds, p2);
|
||||
}
|
||||
|
||||
@@ -190,6 +190,10 @@ class NumberDictionary {
|
||||
return Long.fromNumber(x).shiftLeft(32).or(this.intToUint(y)).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param i
|
||||
*/
|
||||
private intToUint(i) {
|
||||
if (i >= 0)
|
||||
return i;
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
class RectangleExt {
|
||||
public static union(first: Rectangle, point: Vector2){
|
||||
let rect = new Rectangle(point.x, point.y, 0, 0);
|
||||
return this.unionR(first, rect);
|
||||
}
|
||||
|
||||
public static unionR(value1: Rectangle, value2: Rectangle){
|
||||
let result = new Rectangle();
|
||||
result.x = Math.min(value1.x, value2.x);
|
||||
result.y = Math.min(value1.y, value2.y);
|
||||
result.width = Math.max(value1.right, value2.right) - result.x;
|
||||
result.height = Math.max(value1.bottom, value2.bottom) - result.y;
|
||||
|
||||
return result;
|
||||
let rectResult = first.union(rect);
|
||||
return new Rectangle(rectResult.x, rectResult.y, rectResult.width, rectResult.height);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user