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

How to expel a rect from inside another rect - Javascript

本文关键字:一个 Javascript 驱逐 另一个      更新时间:2023-09-26

我试图让rect1rect2内部移出。我试图四处寻找一个awsner,但我找不到一个令人满意的awnser。我可以检测到矩形相交,但我无法驱逐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相交时,我希望第三个参数rect1向左移动

一种方法是确定在 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();
}

在这里看到它的小提琴。

一个简单的解决方案:

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-hard,尽管我还没有验证这一点)。

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

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)如果移动导致与外边框相交。