2

I am using cocos2d-x 3.8. I try to create two polygon sprites with the following code.

I know we can detect intersect with BoundingBox but is too rough. Also, I know we can use Cocos2d-x C++ Physics engine to detect collisions but doesn't it waste a lot of resource of the mobile device? The game I am developing does not need physics engine.

is there a way to detect the intersect of polygon sprites? Thank you.

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)
Phyerh
  • 21
  • 4
  • As far as I know it's not possible now. I've read somewhere on forums that they want to add collision detection between AutoPolygons. For now I guess you have to use physics. – Makalele Feb 01 '16 at 12:16

2 Answers2

1

This is a bit more complicated: AutoPolygon gives you a bunch of triangles - the PhysicsBody::createPolygon requires a convex polygon with clockwise winding… so these are 2 different things. The vertex count might even be limited. I think Box2d’s maximum count for 1 polygon is 8.

If you want to try this you’ll have to merge the triangles to form polygons. An option would be to start with one triangle and add more as long as the whole thing stays convex. If you can’t add any more triangles start a new polygon. Add all the polygons as PhysicsShapes to your physics body to form a compound object.

I would propose that you don’t follow this path because

  1. Autopolygon is optimized for rendering - not for best fitting physics - that is a difference. A polygon traced with Autopolygon will always be bigger than the original sprite - Otherwise you would see rendering artifacts.
  2. You have close to no control over the generated polygons
  3. Tracing the shape in the app will increase your startup time
  4. Triangle meshes and physics outlines are 2 different things

I would try some different approach: Generate the collision shapes offline. This gives you a bunch of advantages:

  1. You can generate and tweak the polygons in a visual editor e.g. by using PhysicsEditor
  2. Loading the prepares polygons is way faster
  3. You can set additional parameters like mass etc
  4. The solution is battle proven and works out of the box

But if you want to know how polygon intersect work. You can look at this code.

    // 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;
      }
    }

The function can be used this way

    boolean result = PolygonCollision(polygonA, polygonB);
  • A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted.](//stackoverflow.com/help/deleted-answers) – Mogsdad Jan 21 '18 at 03:09
0

I once had to program a collision detection algorithm where a ball was to collide with a rotating polygon obstacle. In my case the obstacles where arcs with certain thickness. and where moving around an origin. Basically it was rotating in an orbit. The ball was also rotating around an orbit about the same origin. It can move between orbits. To check the collision I had to just check if the balls angle with respect to the origin was between the lower and upper bound angles of the arc obstacle and check if the ball and the obstacle where in the same orbit.

In other words I used the various constrains and properties of the objects involved in the collision to make it more efficient. So use properties of your objects to cause the collision. Try using a similar approach depending on your objects

Ratan Senapathy
  • 2,148
  • 2
  • 10
  • 14