2012-11-01 112 views
4

我想寫我自己的分離軸定理的實現,但我有一些麻煩得到它的工作儘可能準確,我想要的。我不能肯定地說,但它看起來像是說當形狀周圍的假想盒子碰到第一個形狀時會發生碰撞。但第二個形狀完美運作。多邊形碰撞檢測實現

這裏的頂點數據進行平方(確切座標):

vertsx = [ 200, 220, 220, 200 ] 
vertsy = [ 220, 220, 200, 200 ] 

下面是測試形狀的頂點數據1(相對於小鼠):

vertsx = [ -10, 0, 10, 10, -10 ] 
vertsy = [ -10, -50, -10, 10, 10 ] 

並且最後,這裏的頂點數據對於測試形狀2(相對於小鼠):

vertsx = [ -10, 0, 10, 10, -10 ] 
vertsy = [ -10, -20, -10, 10, 10 ] 

只是爲了說明翻譯的coo rdinates是被測試的那些,並且這些形狀已經按照所示的座標進行了測試。

enter image description here

這裏的實際功能。

function collisionConvexPolygon (vertsax, vertsay, vertsbx, vertsby) { 
    var alen = vertsax.length; 
    var blen = vertsbx.length; 
    // Loop for axes in Shape A 
    for (var i = 0, j = alen - 1; i < alen; j = i++) { 
     // Get the axis 
     var vx = vertsax[ j ] - vertsax[ i ]; 
     var vy = -(vertsay[ j ] - vertsay[ i ]); 
     var len = Math.sqrt(vx * vx + vy * vy); 

     vx /= len; 
     vy /= len; 

     // Project shape A 
     var max0 = vertsax[ 0 ] * vx + vertsay[ 0 ] * vy, min0 = max0; 
     for (k = 1; k < alen; k++) { 
      var proja = vertsax[ k ] * vx + vertsay[ k ] * vy; 

      if (proja > max0) { 
       max0 = proja; 
      } 
      else if (proja < min0) { 
       min0 = proja; 
      } 
     } 
     // Project shape B 
     var max1 = vertsbx[ 0 ] * vx + vertsby[ 0 ] * vy, min1 = max1; 
     for (var k = 1; k < blen; k++) { 
      var projb = vertsbx[ k ] * vx + vertsby[ k ] * vy; 

      if (projb > max1) { 
       max1 = projb; 
      } 
      else if (projb < min1) { 
       min1 = projb; 
      } 
     } 
     // Test for gaps 
     if (!axisOverlap(min0, max0, min1, max1)) { 
      return false; 
     } 
    } 
    // Loop for axes in Shape B (same as above) 
    for (var i = 0, j = blen - 1; i < blen; j = i++) { 
     var vx = vertsbx[ j ] - vertsbx[ i ]; 
     var vy = -(vertsby[ j ] - vertsby[ i ]); 
     var len = Math.sqrt(vx * vx + vy * vy); 

     vx /= len; 
     vy /= len; 

     var max0 = vertsax[ 0 ] * vx + vertsay[ 0 ] * vy, min0 = max0; 
     for (k = 1; k < alen; k++) { 
      var proja = vertsax[ k ] * vx + vertsay[ k ] * vy; 

      if (proja > max0) { 
       max0 = proja; 
      } 
      else if (proja < min0) { 
       min0 = proja; 
      } 
     } 
     var max1 = vertsbx[ 0 ] * vx + vertsby[ 0 ] * vy, min1 = max1; 
     for (var k = 1; k < blen; k++) { 
      var projb = vertsbx[ k ] * vx + vertsby[ k ] * vy; 

      if (projb > max1) { 
       max1 = projb; 
      } 
      else if (projb < min1) { 
       min1 = projb; 
      } 
     } 
     if (!axisOverlap(min0, max0, min1, max1)) { 
      return false; 
     } 
    } 
    return true; 
} 

我會嘗試其他形狀,如果你需要我。

這是我的axisOverlap函數。

function axisOverlap (a0, a1, b0, b1) { 
    return !(a0 > b1 || b0 > a1); 
} 
+0

您可以發佈您'axisOverlap()'函數嗎? – techfoobar

+0

你能否在不顛倒vy的方向的情況下嘗試一下? –

+0

@Asad是的,不幸的是它沒有改變結果。 – SpaceFace

回答

6

我想通了!

我開始在紙上繪製數字線,並意識到問題是我的座標軸計算不正確。要計算一個垂直向量,你需要交換x和y座標然後反過來,我完全忘了交換座標。

新的代碼

var vx = vertsay[ i ] - vertsay[ j ]; 
var vy = -(vertsax[ i ] - vertsax[ j ]); 
+0

如果你已經解決了你的問題,那麼把你的答案標記爲答案! –

+3

@ A.Webb不能2天。 – SpaceFace