【问题标题】:Detecting collision of rectangle with circle检测矩形与圆的碰撞
【发布时间】:2017-10-29 07:01:54
【问题描述】:

实际上,我正在尝试在以下代码中检测矩形与圆的碰撞:-

function checkCollision() {
     //checking of the Collision
     if (ry + rh > cy - radius && rx + rw > cx - radius && rx + rw < cx + radius ) {
          dy = -dy;
     }
}

这也是我代码的一部分:-

var rx = 50; //distance from the x-axis of the Rect. 
var ry = 50; //distance from the y-axis of the Rect.
var rw = 80; //width of the Rect
var rh = 30; //Height of the Rect.

// Distance to moved of the Rect.
var dx = 2;
var dy = 2;

// Center of the circle from the x-axis and y-axis.
var cx = 105;
var cy = 135;
var radius = 16;
var cx1 = 6;
var cy1 = 6;

谁能帮我找出问题所在?

【问题讨论】:

    标签: javascript canvas collision-detection


    【解决方案1】:

    检测圆-矩形碰撞并非易事(但也没有那么复杂)。

    @kuroi neko 的解决方案是正确的,并且与代码一样简单。

    幸运的是,您无需完全理解数学理论即可使用命中测试功能。

    如果您确实想了解有关该函数如何工作的更多详细信息,这里有一个描述,使用 4 个步骤来测试圆形和矩形是否发生碰撞:

    演示:http://jsfiddle.net/m1erickson/n6U8D/

    首先,定义一个圆和一个矩形

    var circle={x:100,y:290,r:10};
    var rect={x:100,y:100,w:40,h:100};
    

    步骤#1:找出圆心和矩形中心之间的垂直和水平(distX/distY)距离

        var distX = Math.abs(circle.x - rect.x-rect.w/2);
        var distY = Math.abs(circle.y - rect.y-rect.h/2);
    

    步骤#2:如果距离大于halfCircle + halfRect,那么它们相距太远而不会发生碰撞

        if (distX > (rect.w/2 + circle.r)) { return false; }
        if (distY > (rect.h/2 + circle.r)) { return false; }
    

    步骤#3:如果距离小于halfRect,那么它们肯定会发生碰撞

        if (distX <= (rect.w/2)) { return true; } 
        if (distY <= (rect.h/2)) { return true; }
    

    步骤#4:测试矩形角的碰撞。

    • 想想从矩形中心到任何矩形角的线
    • 现在将该线延长圆的半径
    • 如果圆的中心在该直线上,则它们恰好在该矩形角处发生碰撞

    使用毕达哥拉斯公式比较圆心和矩形中心的距离。

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

    完整代码如下:

    var circle={x:100,y:290,r:10};
    var rect={x:100,y:100,w:40,h:100};
    
    // return true if the rectangle and circle are colliding
    function RectCircleColliding(circle,rect){
        var distX = Math.abs(circle.x - rect.x-rect.w/2);
        var distY = Math.abs(circle.y - rect.y-rect.h/2);
    
        if (distX > (rect.w/2 + circle.r)) { return false; }
        if (distY > (rect.h/2 + circle.r)) { return false; }
    
        if (distX <= (rect.w/2)) { return true; } 
        if (distY <= (rect.h/2)) { return true; }
    
        var dx=distX-rect.w/2;
        var dy=distY-rect.h/2;
        return (dx*dx+dy*dy<=(circle.r*circle.r));
    }
    

    【讨论】:

    • 我知道这个解决方案非常好,,,我看过小提琴文件,非常感谢@markE,但实际上我刚刚开始使用html5画布,它并不难代码,,,但我都不需要,,,我实际上有一种乒乓球游戏,我必须检测圆圈(桨)和矩形(obj充当球)之间的碰撞就是这样..!!!希望你能得到一个简单的溶胶..!!
    • @markE 如果您认为矩形是“实心的”(圆在矩形内时被认为是碰撞的),这个版本会更加精简。我通过我的test fiddle 运行它,它就像一个魅力。
    • ,是的,工作很棒,,我会在不久的将来查看,,现在很忙,,,但是感谢和出色的工作@kuroi neko..!!!
    • 警告 此代码期望圆的xy 是中心,但矩形的xy左上角。希望这可以节省我刚刚调试碰撞代码的时间和痛苦。
    • 更具体地说,rect.xrect.y 实际上是 rect.topLeftXrect.topLeftY。就我而言,在Rectangle 对象xy 中,矩形的中心坐标的中心。这取决于您如何构建对象,并且如上所述,您需要考虑到这是 Canvas 2d,其中左上角的坐标为 (0,0)。
    【解决方案2】:

    这是一种方法:

    1) 找到距离圆心最近的矩形的角
    2) 查看圆相对于角的位置

    该函数采用第三个参数来区分“实心”矩形和简单轮廓(即完全位于矩形内的圆是否应视为碰撞)

    function collides (rect, circle, collide_inside)
    {
        // compute a center-to-center vector
        var half = { x: rect.w/2, y: rect.h/2 };
        var center = {
            x: circle.x - (rect.x+half.x),
            y: circle.y - (rect.y+half.y)};
    
        // check circle position inside the rectangle quadrant
        var side = {
            x: Math.abs (center.x) - half.x,
            y: Math.abs (center.y) - half.y};
        if (side.x >  circle.r || side.y >  circle.r) // outside
            return false; 
        if (side.x < -circle.r && side.y < -circle.r) // inside
            return collide_inside;
        if (side.x < 0 || side.y < 0) // intersects side or corner
            return true;
    
        // circle is near the corner
        return side.x*side.x + side.y*side.y  < circle.r*circle.r;
    }
    
    var rect = { x:50, y:50, w:80, h:30 };
    var circle = { x:105, y:135, r:16 };
    
    if (collides (rect, circle)) { /* bang! */ }
    

    我有一个计算碰撞法向量的第二个函数,以允许对从矩形反弹的圆进行动画处理。 他们一起作为this fiddle的基础

    function bounces (rect, circle)
    {
        // compute a center-to-center vector
        var half = { x: rect.w/2, y: rect.h/2 };
        var center = {
            x: circle.x - (rect.x+half.x),
            y: circle.y - (rect.y+half.y)};
    
        // check circle position inside the rectangle quadrant
        var side = {
            x: Math.abs (center.x) - half.x,
            y: Math.abs (center.y) - half.y};
        if (side.x >  circle.r || side.y >  circle.r) // outside
            return { bounce: false }; 
        if (side.x < -circle.r && side.y < -circle.r) // inside
            return { bounce: false }; 
        if (side.x < 0 || side.y < 0) // intersects side or corner
        {
            var dx = 0, dy = 0;
            if (Math.abs (side.x) < circle.r && side.y < 0)
            {
                dx = center.x*side.x < 0 ? -1 : 1;
            }
            else if (Math.abs (side.y) < circle.r && side.x < 0)
            {
                dy = center.y*side.y < 0 ? -1 : 1;
            }
    
            return { bounce: true, x:dx, y:dy };
        }
        // circle is near the corner
        bounce = side.x*side.x + side.y*side.y  < circle.r*circle.r;
        if (!bounce) return { bounce:false }
        var norm = Math.sqrt (side.x*side.x+side.y*side.y);
        var dx = center.x < 0 ? -1 : 1;
        var dy = center.y < 0 ? -1 : 1;
        return { bounce:true, x: dx*side.x/norm, y: dy*side.y/norm };   
    }
    

    【讨论】:

    • 能否请您提供一个简单的解决方案,,,,我认为我很难跟进意味着占用我的代码,,但感谢您的努力..!!
    • 您现在有一个工作示例。恐怕你需要一些数学背景来理解细节,但你可以以小提琴为基础,只对幕后发生的事情有一个全局的理解。
    • 我知道这个解决方案并不难,而且我有点能够遵循它@kuroi neko,但实际上我刚刚开始了html5画布,它不是那么难的代码,,,但是我都不需要,,,我实际上有一种乒乓球游戏,我必须检测圆(桨)和矩形(obj充当球)之间的碰撞就是这样..!!!希望你能得到一个简单的溶胶..!!
    • 如果你不介意你可以编辑我的 checkCollision 函数..!!提出溶胶。如果可能的话..??
    • 好吧,据我所知,您的 checkcollision 只能从矩形的一侧反弹。根本不可能将我的代码移植到您的代码中并期望它在不了解发生了什么的情况下工作。坦率地说,我认为您最好尝试了解它是如何在我的小提琴中完成的。
    【解决方案3】:

    我发现我遇到了所选答案的问题。这是我的,我认为效果很好:

    function collisionCheckCircleRect(circle, rect)
    {
        var distx = Math.abs(circle.x - rect.x);
        var disty = Math.abs(circle.y - rect.y);
    
        if (distx > (rect.width/2 + circle.radius)) { return false; }
        if (disty > (rect.height/2 + circle.radius)) { return false; }
    
        if (distx <= (rect.width/2)) { return true; } 
        if (disty <= (rect.height/2)) { return true; }
    
        var hypot = (distx - rect.width/2)*(distx- rect.width/2) +
                             (disty - rect.height/2)*(disty - rect.height/2);
    
    //console.log(hypot <= (circle.radius*circle.radius))
        return (hypot <= (circle.radius*circle.radius));
    }
    

    【讨论】:

      猜你喜欢
      • 2014-09-03
      • 1970-01-01
      • 2014-04-08
      • 2010-09-28
      • 2023-01-26
      • 2014-02-07
      • 1970-01-01
      • 1970-01-01
      • 2014-05-05
      相关资源
      最近更新 更多