我的AABB碰撞检测/解决代码有什么问题?

时间:2016-11-19 22:49:56

标签: javascript algorithm math collision

我正在研究JavaScript中的游戏引擎,目前我正在研究碰撞系统。我做了一个算法来解决与玩家检测到的碰撞,但我没有得到预期的行为。这是代码:

if (gameObjects [i].hasComponent ("BoxCollider") == true) {
        for (var x = 0; x < gameObjects.length; x++) {
            if (gameObjects [x].hasComponent ("BoxCollider") == true && gameObjects [i] != gameObjects [x]) {
                if (gameObjects [i].transform.xPos - (gameObjects [i].getComponent ("BoxCollider").width / 2) < gameObjects [x].transform.xPos + (gameObjects [x].getComponent ("BoxCollider").width / 2) && gameObjects [i].transform.xPos + (gameObjects [i].getComponent ("BoxCollider").width / 2) > gameObjects [x].transform.xPos - (gameObjects [x].getComponent ("BoxCollider").width / 2) && gameObjects [i].transform.yPos - (gameObjects [i].getComponent ("BoxCollider").height / 2) < gameObjects [x].transform.yPos + (gameObjects [x].getComponent ("BoxCollider").height / 2) && gameObjects [i].transform.yPos + (gameObjects [i].getComponent ("BoxCollider").height / 2) > gameObjects [x].transform.yPos - (gameObjects [x].getComponent ("BoxCollider").height / 2)) {
                    //collision
                    if (gameObjects [i] == player) {

                        var xPenetration = 0;
                        var yPenetration = 0;

                        //i is left of x
                        if (gameObjects [i].transform.xPos < gameObjects [x].transform.xPos) {
                            xPenetration = -1 * ((/*i right edge*/gameObjects [i].transform.xPos + gameObjects [i].boxCollider.width / 2) - (/*x left edge*/gameObjects [x].transform.xPos - gameObjects [x].boxCollider.width / 2));
                        }

                        //i is right of x
                        else if (gameObjects [i].transform.xPos > gameObjects [x].transform.xPos) {
                            xPenetration = ((/*x right edge*/gameObjects [x].transform.xPos + gameObjects [x].boxCollider.width / 2) - (/*i left edge*/gameObjects [i].transform.xPos - gameObjects [i].boxCollider.width / 2));
                        }

                        //i is top of x
                        if (gameObjects [i].transform.yPos < gameObjects [x].transform.yPos) {
                            yPenetration = -1 * ((/*i bottom edge*/gameObjects [i].transform.yPos + gameObjects [i].boxCollider.height / 2) - (/*x top edge*/gameObjects [x].transform.yPos - gameObjects [x].boxCollider.height / 2));
                        }

                        //i is bottom of x
                        else if (gameObjects [i].transform.yPos > gameObjects [x].transform.yPos) {
                            yPenetration = ((/*x bottom edge*/gameObjects [x].transform.yPos + gameObjects [x].boxCollider.height / 2) - (/*i top edge*/gameObjects [i].transform.yPos - gameObjects [i].boxCollider.height / 2));
                        }

                        if (Math.abs (xPenetration) > Math.abs (yPenetration)) {
                            gameObjects [i].transform.xPos += xPenetration;
                        } else {
                            gameObjects [i].transform.yPos += yPenetration;
                        }

                    }
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

有几个问题。首先,您需要处理gameObjects [i].transform.xPos完全等于gameObjects [x].transform.xPos的情况(对于y位置也是如此)。目前你处理的是小于和大于但不相等的。因此,只需将<更改为<=或将>更改为>=,例如:

if (gameObjects [i].transform.xPos <= gameObjects [x].transform.xPos)

另一个问题是,当你碰撞时,如果你将一个物体推出它沿着轴与最小穿透距离碰撞的物体,它看起来会更自然。因此,只需更改此行以选择x和y的min而不是max:

if (Math.abs (xPenetration) < Math.abs (yPenetration))