首页 > 解决方案 > 圆形和矩形之间的碰撞检测(为什么这不起作用?)

问题描述

我正在尝试了解圆矩形碰撞检测,用于像球和桨的突围这样的游戏。如果圆形和矩形发生碰撞,我有一个函数应该返回 true,否则返回 false。

         function circleRectCollision(circle, rect) {
                let xDistBetweenCenters = Math.abs(circle.xPos - (rect.xPos + rect.width / 2));
                let yDistBetweenCenters = Math.abs(circle.yPos - (rect.yPos + rect.height / 2));
    
                // Exit conditions
                if (xDistBetweenCenters > circle.size + rect.width / 2) {
                    return false;
                }
                if (yDistBetweenCenters > circle.size + rect.height / 2) {
                    return false;
                }

                // If we've made it this far, this means the circle is either touching the rectangle or 
                // "relatively close" to touching it. The circle's center is somewhere inside
                // of a new, expanded rectangle that surrounds the original rectangle. This new rectangle's dimensions are what
                // would result from expanding each edge outward by the radius of the circle)
            }

但是,知道圆的中心位于这个新的外部矩形的内部(或边缘/角上)并不足以确定圆和矩形是否发生碰撞。这个外部矩形的每个角附近都有一个不会导致碰撞的小区域。我们必须圆角,然后外部圆角矩形将代表圆的半径可以驻留的每个点,以便圆与原始矩形之间发生碰撞。

现在,我应该提到我不是特别擅长数学,所以也许我尝试找出矩形中心和矩形角之一之间的距离,然后加上球的半径的解决方案是天真的。这很简单,使用勾股定理/公式。我认为这将给出圆心距矩形中心的最大距离,以便仍然存在碰撞。所以,我在函数的末尾添加了以下几行

                let maxDist = Math.sqrt((paddle.width / 2) ** 2 + (paddle.height / 2) ** 2) + circle.size;
                if (Math.sqrt(xDistBetweenCenters ** 2 + yDistBetweenCenters ** 2) <= maxDist) {
                    console.log("collision");
                }

然而,这并不完全奏效。即使球在角落附近接触空气,我仍然被告知正在发生碰撞。是不是因为圆心到矩形中心的最大距离在仍然接触时不等于圆心到矩形中心之间的距离,当圆接触矩形的角时?这完全是错误的方法吗?我的数学一定是错的。(顺便说一句,我知道使用 Math.sqrt 很昂贵,而将数字平方更好)。

我已经看到其他地方提出的其他解决方案,例如

cornerDistanceSq = Math.sqr(circleDistance.x - rect.width/2) +
                        Math.sqr(circleDistance.y - rect.height/2);
return (cornerDistanceSq <= (Math.sqr(circle.r)));

    var dx=distX-rect.w/2;
    var dy=distY-rect.h/2;
    return (dx*dx+dy*dy<=(circle.r*circle.r));

我不确定我理解为什么这有效,但我的解决方案没有。有人可以用我能理解的方式解释吗?为什么我的数学不成功,为什么这些解决方案有效?谢谢。

标签: javascriptmathcanvas

解决方案


推荐阅读