3
\$\begingroup\$

I am toying around with a Boogaloopers clone (http://www.youtube.com/watch?v=zuaRi_fhdlQ).

I have a small problem with the lassoing.

Here's my current naive algorithm. The problem with this is that the player can swipe a U-shaped pattern with the mouse, and it is detected as a polygon, since the isPointInPolygon-method connects the first and last points together. I wonder if there's a simple way to fix this?

private void collisionDetection() {

    Player p = Player.getPlayer();

    Array<Beam> beams = p.getBeams();

    if (beams.size < 3)
        return;

    for (int i = 0; i < beams.size; i++) {

        Beam b1 = beams.get(i);

        for (int k = i + 1; k < beams.size; k++) {

            Beam b2 = beams.get(k);

            // Don't do collision detection with adjacent beams
            if (p.areConnected(b1, b2))
                continue;

                if (Intersector.intersectSegments(b1.getStart(), b1.getEnd(), b2.getStart(), b2.getEnd(), null)) {

                Array<Vector2> path = p.getPath();
                if (path.size < 3)
                    continue;

                boolean destroyed = false;

                // Destroy any monsters inside the polygon
                for (int j = 0; j < entities.size; j++) {
                    Entity e = entities.get(j);

                    if (e instanceof Player)
                        continue;

                    if (Intersector.isPointInPolygon(path, e.getPosition())) {
                        destroyed = true;
                        e.destroy();
                    }
                }

                if (destroyed) {
                    SFX.play("sfx-destroy");
                }

                return;
            }
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ What do you want it to do? If the start and end don't cross then don't lasso? \$\endgroup\$ – jzx Jul 29 '14 at 19:54
5
\$\begingroup\$

The problem is you need to close the loop, to make sure the lasso is complete (based on the behavior of the video).

You do that by testing if one of the segments intersect with another segment, thus closing the loop.

enter image description here

It might look something like this (note I don't use libgdx, so this is untested):

Array<Vector2> path = p.getPath();
// Look for an intersection point
for (int i=0; i<path.size-1; ++i)
{
    for (int j=i+2; j<path.size-1; ++j)
    {
        Vector intersection;
        if (Intersection.intersectSegments(path[i], path[i+1], path[j], path[j+1], intersection))
        {
            Array<Vector2> loop = new Array<Vector2>();
            loop.add(intersection);
            loop.addAll(path, i+1, j-i);

            // Destroy any monsters inside the polygon
            for (int j = 0; j < entities.size; j++)
            // ....

            // exit loop, restart path
        }
    }
}

What's happening there is we start at the beginning, and test each segment with subsequent segments in the path (note j starts at i+2). If there is an intersection, we've found a loop, so we use the returned intersection point and test for containment.

If you find that the intersection criteria is too restrictive, you can extend the first and last segment, so the loop doesn't have to be closed exactly. You can add an extra "fake" point at the beginning and other at the end, following the same direction of the segment at a configurable distance (see picture).

enter image description here

\$\endgroup\$
  • \$\begingroup\$ I would I like to add that the outter loop should be left out and the inner loop performed whenever a line is added - this will allow instant feedback needed for lasso ingame. \$\endgroup\$ – wondra Jul 30 '14 at 12:31
  • \$\begingroup\$ Got it working just fine with this method. Thanks! \$\endgroup\$ – user2499946 Jul 30 '14 at 14:21
0
\$\begingroup\$

If performance isnt a problem for you and you want simple solution, just draw a thick line and check color under your cursor. If at any point the color was equal to the line color, you know the polygon was closed.
This can be even improved by checking color of all pixels between last and current mouse position.
Other option would be to perform MANY line segment intersections.

\$\endgroup\$
  • \$\begingroup\$ Unfortunately your solution doesn't work, you are asking for almost 100% closed polygon,if you check the video the game automatically closes the curve, your solution require the player to have pixel acuracy in closing the curve which almost doesn't work in real scenarios. \$\endgroup\$ – concept3d Jul 30 '14 at 0:34
  • \$\begingroup\$ @concept3d read the improved version - simply read all pixels in between, if the line width is 2 or more pixels, there is now way to miss it. This solution may be naive, but 100% working for all shapes. \$\endgroup\$ – wondra Jul 30 '14 at 10:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.