Javascript 画布三角形、五边形、矩形相互碰撞检测?

Javascript 画布三角形、五边形、矩形相互碰撞检测?,javascript,canvas,collision-detection,Javascript,Canvas,Collision Detection,我有一些代码,其中画了一个三角形并返回一个对象,其中包含x1,y1,x2,y2,x3,y3。我还有一个矩形绘图函数,返回x,y,w,h,还有一个五角大楼绘图函数,返回x1,y1,x2,y2,x3,y3,x4,y4,x5,y5。我如何制作一个碰撞检测功能来检测矩形和五边形或三角形和五边形是否发生碰撞?测试三角形的任何一侧(线段)是否拦截矩形的任何一侧 如果有任何边截取,则三角形和矩形发生碰撞 三角形的测试边#1与矩形的每边相对 三角形的测试边#2与矩形的每边相对 三角形的测试边#3与矩形的每边相

我有一些代码,其中画了一个三角形并返回一个对象,其中包含
x1,y1,x2,y2,x3,y3
。我还有一个矩形绘图函数,返回
x,y,w,h
,还有一个五角大楼绘图函数,返回
x1,y1,x2,y2,x3,y3,x4,y4,x5,y5
。我如何制作一个碰撞检测功能来检测矩形和五边形或三角形和五边形是否发生碰撞?

测试三角形的任何一侧(线段)是否拦截矩形的任何一侧

如果有任何边截取,则三角形和矩形发生碰撞

  • 三角形的测试边#1与矩形的每边相对
  • 三角形的测试边#2与矩形的每边相对
  • 三角形的测试边#3与矩形的每边相对
  • 如果您在测试时发现拦截,您可以停止,因为形状确实发生碰撞
有关“两条线段是否截取”的详细信息,请参见下文

对任何其他多边形执行相同的侧面拦截测试,以查看它们是否发生碰撞

此处重现了两行截取测试:

// point object: {x:, y:}
// p0 & p1 form one segment, p2 & p3 form the second segment
// Returns true if lines segments are intercepting
var lineSegmentsIntercept = (function(){ // function as singleton so that closure can be used

    var v1, v2, v3, cross, u1, u2;  // working variable are closed over so they do not need creation 
                               // each time the function is called. This gives a significant performance boost.
    v1 = {x : null, y : null}; // line p0, p1 as vector
    v2 = {x : null, y : null}; // line p2, p3 as vector
    v3 = {x : null, y : null}; // the line from p0 to p2 as vector

    function lineSegmentsIntercept (p0, p1, p2, p3) {
        v1.x = p1.x - p0.x; // line p0, p1 as vector
        v1.y = p1.y - p0.y; 
        v2.x = p3.x - p2.x; // line p2, p3 as vector
        v2.y = p3.y - p2.y; 
        if((cross = v1.x * v2.y - v1.y * v2.x) === 0){  // cross prod 0 if lines parallel
            return false; // no intercept
        }
        v3 = {x : p0.x - p2.x, y : p0.y - p2.y};  // the line from p0 to p2 as vector
        u2 = (v1.x * v3.y - v1.y * v3.x) / cross; // get unit distance along line p2 p3 
        // code point B
        if (u2 >= 0 && u2 <= 1){                   // is intercept on line p2, p3
            u1 = (v2.x * v3.y - v2.y * v3.x) / cross; // get unit distance on line p0, p1;
            // code point A
            return (u1 >= 0 && u1 <= 1);           // return true if on line else false.
            // code point A end
        }
        return false; // no intercept;
        // code point B end
    }
    return lineSegmentsIntercept;  // return function with closure for optimisation.
})();
```

用法示例

var p1 = {x: 100, y: 0};   // line 1
var p2 = {x: 120, y: 200};
var p3 = {x: 0,   y: 100}; // line 2
var p4 = {x: 100, y: 120};
var areIntersepting = lineSegmentsIntercept (p1, p2, p3, p4); // true
该示例很容易修改以返回截距点。将
代码点A
A端之间的代码替换为

if(u1 >= 0 && u1 <= 1){
    return {
        x : p0.x + v1.x * u1,
        y : p0.y + v1.y * u1,
    };
}
return {
    x : p2.x + v2.x * u2,
    y : p2.y + v2.y * u2,
};
如果没有截距,两个修改都将返回false,或者将截距点返回为
{x:xCoord,y:yCoord}

测试三角形的任何一侧(线段)是否截距矩形的任何一侧

如果有任何边截取,则三角形和矩形发生碰撞

  • 三角形的测试边#1与矩形的每边相对
  • 三角形的测试边#2与矩形的每边相对
  • 三角形的测试边#3与矩形的每边相对
  • 如果您在测试时发现拦截,您可以停止,因为形状确实发生碰撞
有关“两条线段是否截取”的详细信息,请参见下文

对任何其他多边形执行相同的侧面拦截测试,以查看它们是否发生碰撞

此处重现了两行截取测试:

// point object: {x:, y:}
// p0 & p1 form one segment, p2 & p3 form the second segment
// Returns true if lines segments are intercepting
var lineSegmentsIntercept = (function(){ // function as singleton so that closure can be used

    var v1, v2, v3, cross, u1, u2;  // working variable are closed over so they do not need creation 
                               // each time the function is called. This gives a significant performance boost.
    v1 = {x : null, y : null}; // line p0, p1 as vector
    v2 = {x : null, y : null}; // line p2, p3 as vector
    v3 = {x : null, y : null}; // the line from p0 to p2 as vector

    function lineSegmentsIntercept (p0, p1, p2, p3) {
        v1.x = p1.x - p0.x; // line p0, p1 as vector
        v1.y = p1.y - p0.y; 
        v2.x = p3.x - p2.x; // line p2, p3 as vector
        v2.y = p3.y - p2.y; 
        if((cross = v1.x * v2.y - v1.y * v2.x) === 0){  // cross prod 0 if lines parallel
            return false; // no intercept
        }
        v3 = {x : p0.x - p2.x, y : p0.y - p2.y};  // the line from p0 to p2 as vector
        u2 = (v1.x * v3.y - v1.y * v3.x) / cross; // get unit distance along line p2 p3 
        // code point B
        if (u2 >= 0 && u2 <= 1){                   // is intercept on line p2, p3
            u1 = (v2.x * v3.y - v2.y * v3.x) / cross; // get unit distance on line p0, p1;
            // code point A
            return (u1 >= 0 && u1 <= 1);           // return true if on line else false.
            // code point A end
        }
        return false; // no intercept;
        // code point B end
    }
    return lineSegmentsIntercept;  // return function with closure for optimisation.
})();
```

用法示例

var p1 = {x: 100, y: 0};   // line 1
var p2 = {x: 120, y: 200};
var p3 = {x: 0,   y: 100}; // line 2
var p4 = {x: 100, y: 120};
var areIntersepting = lineSegmentsIntercept (p1, p2, p3, p4); // true
该示例很容易修改以返回截距点。将
代码点A
A端之间的代码替换为

if(u1 >= 0 && u1 <= 1){
    return {
        x : p0.x + v1.x * u1,
        y : p0.y + v1.y * u1,
    };
}
return {
    x : p2.x + v2.x * u2,
    y : p2.y + v2.y * u2,
};

如果没有截取,这两个修改都将返回false,或者将截取点返回为
{x:xCoord,y:yCoord}

有一个方便的函数可以用来实现碰撞检测。这是一篇很好的文章。@AaditMShah
isPointInPath
测试[x,y]点是否在路径(三角形,矩形)内。它不会测试三角形和矩形是否冲突。@markE当然可以。但是,您可以做的是测试一个形状的任何顶点是否位于另一个形状的内部,反之亦然。它不像直线相交那样复杂,但是如果你正在制作一个动画,其中两个形状不能相互交错,那么这是一个快速而肮脏的解决方案。有一个叫做的方便函数,可以用来实现碰撞检测。这是一篇很好的文章。@AaditMShah
isPointInPath
测试[x,y]点是否在路径(三角形,矩形)内。它不会测试三角形和矩形是否冲突。@markE当然可以。但是,您可以做的是测试一个形状的任何顶点是否位于另一个形状的内部,反之亦然。这并不像直线相交那个样复杂,但若你们在制作一个动画,其中两个形状不能相互交错,那个么这是一个快速而肮脏的解决方案。这对椭圆有效吗?现在我说,我刚刚意识到我的笑声有多蠢。。。我也有这样的时刻。:-)无论如何,一种测试物体是否与椭圆碰撞的近似方法是获取椭圆的边界框并将其视为矩形。然后测试该边界矩形与其他对象。您可以通过碰撞测试边界矩形的三角形角来优化此测试,但碰撞测试通常是“足够好”和边界框测试就足够了。无需担心。我自己做了
if(obj1.x>obj2.x&&obj1.y>obj2.y&&obj1.x
。我只测试过一次,如果我在任何地方都错了,你可以纠正我:)我更新了我的绘图函数,只返回x,y,width,height,而不是每个点,这对椭圆有效吗?现在我说,我刚刚意识到我听起来有多傻。。。我也有这样的时刻。:-)无论如何,一种测试物体是否与椭圆碰撞的近似方法是获取椭圆的边界框并将其视为矩形。然后测试该边界矩形与其他对象。您可以通过碰撞测试边界矩形的三角形角来优化此测试,但碰撞测试通常是“足够好”和边界框测试就足够了。无需担心。我自己做了
if(obj1.x>obj2.x&&obj1.y>obj2.y&&obj1.x
。我只测试过一次,如果我在任何地方出错,你都可以纠正我:)我更新了绘图函数,只返回x,y,width,height,而不是每个点