JavaScript 多边形碰撞检测

6
我正在使用HTML的画布和JavaScript制作类似于“小行星”的街机游戏。我目前有一堆随机生成的形状(“小行星”),具有随机数量的点(3、4或5)和随机大小,位于随机位置。
我正在尝试为这些多边形设置碰撞检测系统。我一直在使用SAT.js(https://github.com/jriecken/sat-js)。然而,我似乎无法准确地在屏幕上呈现的实际多边形周围绘制看不见的碰撞多边形。
以下是我在小行星类中渲染小行星的内容。我目前只测试了3个点的形状(三角形)。我关闭了4和5个点的小行星。

ctx.moveTo(0, 0);
ctx.lineTo(10 + size, 20); 
ctx.lineTo(10 + size, 20 + size);  
ctx.closePath();

这里是相应的SAT.js代码。

/**
  * @function createCollisionPolygon
  * Traces the outline of the asteroid to allow it to detect collisions
  * based on the number of points the shape has (3, 4, or 5)
  * @param {asteroid} The asteroid to make collision detectable
  * @return The traced polygon
  */
function createCollisionPolygon(asteroid)
{
  var V = SAT.Vector;
  var P = SAT.Polygon;
  var polygon;
  switch(asteroid.randomNumPoints)
  {
    // 3 point polygon
    case 3:
      polygon = new P(new V(asteroid.position.x, asteroid.position.y), [
      new V(10 + asteroid.size, 0),
      new V(asteroid.position.x,asteroid.position.y),
      new V(10 + asteroid.size, 20 + asteroid.size)
      ]);
      break;
  }
  return polygon;
}

/**
  * @function checkCollision
  * Checks for collisions between any two asteroids
  * @param {polygon1} The first asteroid  
  * @param {polygon2} The next asteroid
  * @return True if there was a collision, false otherwise
  */
function checkCollision(polygon1, polygon2)
{
  var response = new SAT.Response();
  var collided = SAT.testPolygonPolygon(polygon1, polygon2, response);
  return collided;
}

这里稍后会被调用:

 
  for(var i = 0; i < asteroids.length - 1; i++)
  {
    var asteroid1 = asteroids[i];
    var asteroid2 = asteroids[i+1];

    // Trace an invisible outline around each asteroid
    var polygon1 = createCollisionPolygon(asteroid1); 
    var polygon2 = createCollisionPolygon(asteroid2);

    // console.log("Polygon 1: "+ console.log(polygon1.points[0]
    //  + console.log(polygon1.points[1]) + console.log(polygon1.points[2])));
    // console.log("Polygon 2: " + console.log(polygon2.points[0]
    //  + console.log(polygon2.points[1]) + console.log(polygon2.points[2])));

    // Check if there is a collision
    if(checkCollision(polygon1, polygon2))
    {
      asteroid1.color = 'red';
      asteroid2.color = 'red';
      console.log("Collision detected.");
    }
  }

希望能得到帮助 - 我已经试了好几天了还是没弄明白。谢谢!

1个回答

0

因为没有画布剪辑属性来检索交集区域,所以我建议使用下一个解决方案。使用其中一个js库进行多边形交集计算,例如Greiner-Hormann。 使用此库,您可以轻松地相交您的形状并检测碰撞(如果交集结果不为空,则存在碰撞)。

示例:

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

function drawTriangle(trianglePoints, color)
{
  ctx.beginPath();
  ctx.moveTo(trianglePoints[0].x, trianglePoints[0].y);
  ctx.lineTo(trianglePoints[1].x, trianglePoints[1].y); 
  ctx.lineTo(trianglePoints[2].x, trianglePoints[2].y);  
  ctx.closePath();
  ctx.fillStyle = color;
  ctx.fill();
 }

function getTriangle(size, startPointX, startPointY)
{
  return [{x:startPointX,y:startPointY},
          {x:startPointX + size,y:startPointY},
          {x:startPointX,y:startPointY + size},
          {x:startPointX,y:startPointY}];
}

//sample triangles
var triangle1 = getTriangle(50,100,100);
var triangle2 = getTriangle(50,100,90);
var triangle3 = getTriangle(50,200,100);
var triangle4 = getTriangle(50,280,90);

//draw all triangles
drawTriangle(triangle1,'#d3d3d3');
drawTriangle(triangle2,'#e3e3e3');
drawTriangle(triangle3,'red');
drawTriangle(triangle4,'blue');

//intersaction results
console.log("intersection exists");
console.log(greinerHormann.intersection( triangle1 , triangle2));
console.log("intersection not exists result of intersaction - null");
console.log(greinerHormann.intersection( triangle3 , triangle2));
<script src="https://cdn.rawgit.com/w8r/GreinerHormann/master/dist/greiner-hormann.min.js"></script>
<canvas id="myCanvas" width="578" height="200"></canvas>


1
如果我们正在使用库,为什么不使用完整的物理引擎呢? - B''H Bi'ezras -- Boruch Hashem
1
https://cdn.rawgit.com/w8r/GreinerHormann/master/dist/greiner-hormann.min.js 是404错误 :( - Marc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接