如何从另一个矩形中驱逐一个矩形 - Javascript

时间:2015-03-11 18:43:45

标签: javascript function collision rect

我想让rect1rect2内移出来。我试图环顾四周,但我无法找到一个令人满意的芒果。我可以检测到相交的矩形,但我无法驱逐rect1,因此它会超出rect2。你能提供一些代码来帮我这么做吗?到目前为止,我将提供检测代码。

代码:

var DoCollision = function(rect1, rect2, objectToMove){
    if (rect1.x + rect1.w > rect2.x &&
        rect1.x < rect2.x + rect2.w &&
        rect1.y + rect1.h > rect2.y &&
        rect1.y < rect2.y + rect2.h){
            // Expel rect1 from rect2 here using objectToMove as the object being expelled (In this case, rect1).
    };
};

感谢您的回复。

我应该告诉你更大的图景。我正在尝试创建一个函数,我输入3 rect个对象,以测试它们是否发生碰撞,如果是,我希望第三个rect对象相应地移动。例如,函数参数是rect1rect2rect1,这意味着当rect1在左侧与rect2相交时,我想要第三个参数{{ 1}}向左移动

2 个答案:

答案 0 :(得分:1)

一种方法是确定在X或Y方向上移动然后移动该数量所需的最小量。这不会考虑任何边界矩形:

function doCollision(rect1, rect2, objectToMove){
    if (rect1.x + rect1.w > rect2.x &&
        rect1.x < rect2.x + rect2.w &&
        rect1.y + rect1.h > rect2.y &&
        rect1.y < rect2.y + rect2.h){
            if (objectToMove === rect1) {
                moveOutside(objectToMove, rect2);
            }
            else if (objectToMove === rect2) {
                moveOutside(objectToMove, rect1);
            }
    };
};

function moveOutside(rectToMove, otherRect) {
    // Determine if the overlap is due more to x or to y,
    // then perform the appropriate move

    var moveOverOtherX = rectToMove.x + rectToMove.w - otherRect.x;
    var otherOverMoveX = otherRect.x + otherRect.w - rectToMove.x;

    var moveOverOtherY = rectToMove.y + rectToMove.h - otherRect.y;
    var otherOverMoveY = otherRect.y + otherRect.h - rectToMove.y;

    var minOver = Math.min(moveOverOtherX, otherOverMoveX, moveOverOtherY, otherOverMoveY);

    if (minOver == moveOverOtherX) {
        rectToMove.x = otherRect.x - rectToMove.w;
    }
    else if (minOver == otherOverMoveX) {
        rectToMove.x = otherRect.x + otherRect.w;
    }
    else if (minOver == moveOverOtherY) {
        rectToMove.y = otherRect.y - rectToMove.h;
    }
    else {
        rectToMove.y = otherRect.y + otherRect.h;
    }

    rectToMove.update();
}

a fiddle here中查看。

答案 1 :(得分:0)

一个简单的解决方案:

var DoCollision = function(rect1, rect2, objectToMove){
    if (rect1.x + rect1.w > rect2.x &&
        rect1.x < rect2.x + rect2.w &&
        rect1.y + rect1.h > rect2.y &&
        rect1.y < rect2.y + rect2.h){
            objectToMove.x = Math.max(rect1.x + rect1.w, rect2.x + rect2.w);
            objectToMove.y = Math.max(rect1.y + rect1.h, rect2.y + rect2.h);
    };
};

但请注意,只有整个数据集中只有两个矩形时,这才有效。如果有许多矩形,移动rect1以避免与rect2发生碰撞可能会与其他一些矩形发生碰撞。一般来说,将物体移动到最小距离以避免与所有其他物体碰撞的问题非常困难(可能是NP难的,但我还没有对此进行验证)。

编辑:最好通过在更改移动物体的位置之前检查是否发生碰撞来移动碰撞物体远离碰撞(即计算所需位置,检查)如果它会导致碰撞,如果是这样的话,根本不会移动物体)。但如果你之后必须这样做,你可以推广上述方法:

var DoCollision = function(rect1, rect2, objectToMove){
    var intersectInX = rect1.x + rect1.w > rect2.x &&
                       rect1.x < rect2.x + rect2.w;
    var intersectInY = rect1.y + rect1.h > rect2.y &&
                       rect1.y < rect2.y + rect2.h;
    var collide = intersectInX && intersectInY;
    if ( ! collide ) { return; }
    if (intersectInX) {
        var leftmostEdge = Math.min(rect1.x, rect2.x);
        var rightmostEdge = Math.max(rect1.x, rect2.x);
        if (objectToMove.x > leftmostEdge) { // move right rectangle
            objectToMove.x = rightmostEdge;
        } else {                             // move left rectangle
            objectToMove.x = leftmostEdge - objectToMove.w;
        }
    }
    if (intersectInY) {
        var topmostEdge = Math.min(rect1.y, rect2.y);
        var bottommostEdge = Math.max(rect1.y, rect2.y);
        if (objectToMove.y > topmostEdge) { // move bottom rectangle
            objectToMove.y = bottommostEdge;
        } else {                            // move top rectangle
            objectToMove.y = topmostEdge - objectToMove.h;
        }
    }
};

这不涉及2个需要决定矩形行为方式的情况: 1)如果一个矩形完全包围另一个矩形。它们将被拆开,但不一定按你想要的方式移动。 2)如果移动导致与外边界相交。