2012-11-01 86 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