我正在开发一个碰撞检测系统,其中移动矩形(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)
};
}
它使元素向正确的方向偏移,但偏移量总是太大。
您需要找到移动矩形以防止重叠所需的最小距离。最简单的方法是找到解决碰撞所需的每个基本向量,然后选择其中最小的
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
};