如何根据两个矩形的相对位置计算碰撞时的偏移量?

问题描述 投票:0回答:1

我正在开发一个碰撞检测系统,其中移动矩形(movingRect)与静止矩形(steadyRect)发生碰撞。发生碰撞时,我想计算应该应用于稳定矩形的偏移量以解决碰撞。目标是将稳定矩形与移动矩形分开所需的最小量,同时保持偏移方向与其相对位置一致。

这是我当前正在使用的功能。 COLLISION_THRESHOLD 是不会触发碰撞的元素之间的最大距离。如果元素靠近,则会记录碰撞。

function getCollisionOffset(movingRect: DOMRect, steadyRect: DOMRect) {        
        const movingCenter = {
            x: movingRect.left + movingRect.width / 2,
            y: movingRect.top + movingRect.height / 2
        };
        const steadyCenter = {
            x: steadyRect.left + steadyRect.width / 2,
            y: steadyRect.top + steadyRect.height / 2
        };
        const vector = {
            x: steadyCenter.x - movingCenter.x,
            y: steadyCenter.y - movingCenter.y 
        };

        const b1 = Math.abs(vector.x);
        const b2 = (movingRect.width / 2) + (steadyRect.width / 2) + COLLISION_THRESHOLD;
        const c1 = Math.abs(vector.y);
        const c2 = (movingRect.height / 2) + (steadyRect.height / 2) + COLLISION_THRESHOLD
        
        return { 
            x: (Math.abs(vector.x) / b2 * b1) * Math.sign(vector.x),
            y: (Math.abs(vector.y) / c2 * c1) * Math.sign(vector.y) 
        }; 

    }

它使元素向正确的方向偏移,但偏移量总是太大。

javascript vector geometry collision-detection
1个回答
0
投票

您需要找到移动矩形以防止重叠所需的最小距离。最简单的方法是找到解决碰撞所需的每个基本向量,然后选择其中最小的

const rect1Left = movingRect.left;
const rect1Right = movingRect.left + movingRect.width;
const rect2Left = steadyRect.left;
const rect2Right = steadyRect.left + steadyRect.width;


let xSolveRect = 0;
if
(
    (rect2Left < rect1Right && rect2Right > rect1Left) || // left-side overlap
    (rect2Right > rect1Left && rect2Left < rect1Right) || // right-side overlap
    (rect2Left > rect1Left && rect2Right < rect1Right) || // rect2 inside of rect1
    (rect1Left > rect2Left && rect1Right < rect2Right) // rect1 inside of rect2
)
{
    // there is horizontal overlap
    const xMoveRight = rect1Right - rect2Left;
    const xMoveLeft = rect2Right - rect1Left;
    xSolveRect = (xMoveRight < xMoveLeft && xMoveRight > 0) ? xMoveRight : -xMoveLeft;
}

//
// same concept for vertical:

const ySolveRect = 0;
// fill in vertical solve here


return { 
    x: xSolveRect,
    y: ySolveRect
}; 

rect vs. rect overlap solve

© www.soinside.com 2019 - 2024. All rights reserved.