2016-09-23 67 views
0

我有一些代码绘制一个三角形并返回一个对象,其中包含x1, y1, x2, y2, x3, y3。我还有一个矩形绘图功能,返回x, y, w, h,以及返回x1, y1, x2, y2, x3, y3, x4, y4, x5, y5的五角形绘图功能。我怎样才能做一个碰撞检测功能,可以检测矩形和五边形或三角形和五边形是否碰撞?画布三角形,五角大楼,与彼此的矩形碰撞检测?

+0

有一个方便的函数称为['isPointInPath'](https:// developer .mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath),可用于实现碰撞检测。 –

+1

[这里](https://www.toptal.com/game/video-game-physics-part-ii-collision-detection-for-solid-objects)是一篇不错的文章。 –

+0

@AaditMShah。 'isPointInPath'测试一个[x,y]点是否在路径(三角形,矩形)内。它不会测试三角形和矩形是否碰撞。 – markE

回答

3

测试如果所述三角形的任何边(线段)截获该矩形

如果任何侧截取,那么三角形&矩形发生碰撞的任何一侧。针对每边三角形的

  • 测试边#针对矩形的每侧的三角形的1,
  • 测试边#针对矩形的每侧的三角形的2,
  • 测试边#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 & P1形成一个段,P2 & P3形成第二分段 //如果线路段被拦截 VAR lineSegmentsIntercept =(函数()返回真{//功能单以便闭合可用于

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 

该示例容易地修改以返回截距的点。与

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

更换code point AA end之间的代码或者,如果你想获得对线路的拦截点,而忽略线段开始和结束与替代code point BB end之间的代码

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

如果没有拦截或返回截获点,这两个修改都会返回false {x : xCoord, y : yCoord}

+0

这将工作椭圆? –

+0

现在我说我刚刚意识到我听起来有多愚蠢 –

+0

咯咯笑......我也有这样的时刻。 :-)无论如何,测试某个东西是否与椭圆碰撞的近似方法是获取椭圆的边界框并将其视为矩形。然后测试该边界矩形与任何。通过对边界矩形的三角形进行碰撞测试,可以完善这个测试,但碰撞测试通常“够好够好”,边界框测试就足够了。 – markE