cocos2dx检测与多边形精灵的交集

时间:2016-01-30 10:26:54

标签: c++ c++11 cocos2d-iphone cocos2d-x cocos2d-x-3.0

我正在使用cocos2d-x 3.8。 我尝试使用以下代码创建两个多边形精灵。

我知道我们可以检测到与BoundingBox的交叉但是太粗糙了。 另外,我知道我们可以使用Cocos2d-x C ++物理引擎来检测碰撞,但是它不会浪费移动设备的大量资源吗?我正在开发的游戏不需要物理引擎。

有没有办法检测多边形精灵的交叉? 谢谢。

auto pinfoTree = AutoPolygon::generatePolygon("Tree.png");
auto treeSprite= Sprite::create(pinfoTree);
treeSprite-> setPosition(width / 4 * 3 - 30 , height / 2 - 200);
this->addChild(treeSprite);

auto pinfoBird = AutoPolygon::generatePolygon("Bird.png");
auto Bird= Sprite::create(pinfoTree);
Bird->setPosition(width / 4 * 3, height / 2);
this->addChild(Bird)

2 个答案:

答案 0 :(得分:0)

我曾经不得不编写一个碰撞检测算法,其中一个球与一个旋转的多边形障碍物发生碰撞。在我的情况下,弧线具有一定厚度的障碍物。在原点附近移动的地方。基本上它是在轨道上旋转。球也围绕同一起源的轨道旋转。它可以在轨道之间移动。为了检查碰撞,我必须检查相对于原点的球角是否在弧形障碍物的下限和上限之间,并检查球和障碍物是否在同一轨道上。

换句话说,我使用碰撞中涉及的对象的各种约束和属性来提高它的效率。因此,使用对象的属性来导致碰撞。根据您的对象尝试使用类似的方法

答案 1 :(得分:-1)

这有点复杂:AutoPolygon为您提供了一堆三角形 - PhysicsBody :: createPolygon需要一个顺时针缠绕的凸多边形......所以这些是两个不同的东西。顶点数甚至可能是有限的。我认为Box2d的1个多边形的最大计数是8。

如果你想尝试这个,你必须合并三角形以形成多边形。一个选项是从一个三角形开始,只要整个东西保持凸起,就可以添加更多。如果无法再添加三角形,请启动一个新的多边形。将所有多边形作为PhysicsShapes添加到物理实体中以形成复合对象。

我建议您不要遵循此路径,因为

  1. Autopolygon针对渲染进行了优化 - 不是为了最佳拟合 物理学 - 这是一个区别。使用Autopolygon跟踪的多边形将始终大于原始精灵 - 否则您将看到渲染工件。
  2. 您几乎无法控制生成的多边形
  3. 在应用中跟踪形状会增加启动时间
  4. 三角网格和物理轮廓是两个不同的东西
  5. 我会尝试一些不同的方法:离线生成碰撞形状。这为您提供了许多优势:

    1. 您可以在可视化编辑器中生成和调整多边形,例如通过 使用PhysicsEditor
    2. 加载准备多边形的速度更快
    3. 您可以设置其他参数,例如质量等
    4. 该解决方案经过战斗验证,开箱即用
    5. 但是如果你想知道多边形如何交叉工作。你可以查看这段代码。

          // Calculate the projection of a polygon on an axis
          // and returns it as a [min, max] interval
          public void ProjectPolygon(Vector axis, Polygon polygon, ref float min, ref float max) {
              // To project a point on an axis use the dot product
              float dotProduct = axis.DotProduct(polygon.Points[0]);
              min = dotProduct;
              max = dotProduct;
              for (int i = 0; i < polygon.Points.Count; i++) {
                  flaot d = polygon.Points[i].DotProduct(axis);
                  if (d < min) {
                      min = dotProduct;
                  } else {
                      if (dotProduct> max) {
                          max = dotProduct;
                      }
                  }
              }
          }
      
          // Calculate the distance between [minA, maxA] and [minB, maxB]
          // The distance will be negative if the intervals overlap
          public float IntervalDistance(float minA, float maxA, float minB, float maxB) {
              if (minA < minB) {
                  return minB - maxA;
              } else {
                  return minA - maxB;
              }
          }
      
          // Check if polygon A is going to collide with polygon B.
          public boolean PolygonCollision(Polygon polygonA, Polygon polygonB) {
      
              boolean result = true;
              int edgeCountA = polygonA.Edges.Count;
              int edgeCountB = polygonB.Edges.Count;
              float minIntervalDistance = float.PositiveInfinity;
      
              Vector edge;
      
              // Loop through all the edges of both polygons
              for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++) {
                  if (edgeIndex < edgeCountA) {
                      edge = polygonA.Edges[edgeIndex];
                  } else {
                      edge = polygonB.Edges[edgeIndex - edgeCountA];
                  }
      
                  // ===== Find if the polygons are currently intersecting =====
      
                  // Find the axis perpendicular to the current edge
                  Vector axis = new Vector(-edge.Y, edge.X);
                  axis.Normalize();
      
                  // Find the projection of the polygon on the current axis
                  float minA = 0; float minB = 0; float maxA = 0; float maxB = 0;
                  ProjectPolygon(axis, polygonA, ref minA, ref maxA);
                  ProjectPolygon(axis, polygonB, ref minB, ref maxB);
      
                  // Check if the polygon projections are currentlty intersecting
                  if (IntervalDistance(minA, maxA, minB, maxB) > 0)
                      result = false;
      
              return result;
            }
          }
      

      该功能可以这种方式使用

          boolean result = PolygonCollision(polygonA, polygonB);