画布三角形,五角大楼,相互之间的矩形碰撞检测?

时间:2016-09-23 22:47:22

标签: 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 个答案:

答案 0 :(得分:3)

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

如果有任何一方拦截,那么三角形&矩形正在碰撞。

  • 测试三角形的每一边的三角形#1
  • 在矩形的每一边测试三角形的第二边
  • 测试矩形每一边的三角形的第3侧
  • 如果您在测试时发现拦截,则可以停止因为形状确实发生碰撞。

有关“两个线段是否被拦截?”的详细信息,请参阅下文。

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

此处再现了2行拦截的测试:

// 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.
})();

是否有两个线段拦截?

  

(归属于user blindman67以协助以下示例)

如果两个线段相交,则此示例中的函数返回true,否则返回false

该示例是为性能而设计的,并使用闭包来保存工作变量

```Javascript     //点对象:{x:,y:}     // p0&amp; p1形成一个片段,p2&amp; p3构成第二部分     //如果线段正在拦截,则返回true     var lineSegmentsIntercept =(function(){//作为单身的函数,以便可以使用闭包

    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

该示例很容易修改以返回截距点。使用

替换code point AA end之间的代码
if(u1 >= 0 && u1 <= 1){
    return {
        x : p0.x + v1.x * u1,
        y : p0.y + v1.y * u1,
    };
}

或者,如果您想获得行上的拦截点,忽略行段的开头和结尾会将code point BB end之间的代码替换为

return {
    x : p2.x + v2.x * u2,
    y : p2.y + v2.y * u2,
};

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