2016-09-23 105 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