我的 AABB 碰撞 detection/resolution 代码有什么问题?
What's wrong with my AABB collision detection/resolution code?
我正在 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;
}
}
}
}
}
}
}
有几个问题。首先,您需要处理 gameObjects [i].transform.xPos
正好等于 gameObjects [x].transform.xPos
的情况(y 位置也相同)。目前你正在处理小于和大于但不等于。所以只需将 <
更改为 <=
或将 >
更改为 >=
例如:
if (gameObjects [i].transform.xPos <= gameObjects [x].transform.xPos)
另外一个问题是,当你碰撞的时候,如果你沿着最小穿透距离的轴将一个物体从它碰撞的物体中推出,看起来会更自然。所以只需将此行更改为 select x 和 y 的最小值而不是最大值:
if (Math.abs (xPenetration) < Math.abs (yPenetration))
我正在 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;
}
}
}
}
}
}
}
有几个问题。首先,您需要处理 gameObjects [i].transform.xPos
正好等于 gameObjects [x].transform.xPos
的情况(y 位置也相同)。目前你正在处理小于和大于但不等于。所以只需将 <
更改为 <=
或将 >
更改为 >=
例如:
if (gameObjects [i].transform.xPos <= gameObjects [x].transform.xPos)
另外一个问题是,当你碰撞的时候,如果你沿着最小穿透距离的轴将一个物体从它碰撞的物体中推出,看起来会更自然。所以只需将此行更改为 select x 和 y 的最小值而不是最大值:
if (Math.abs (xPenetration) < Math.abs (yPenetration))