callegro5

Use polygons as clickable zones, instead of rectangles


I'm creating a 2D game using the allegro library and I need to create polygonal territories on a map that the player can click on to move his units.

Am I forced to use some sort of point in polygon detection algorithm or is there a simpler solution using the polygon I drew already?

So far I managed to draw a polygon such as:

ALLEGRO_VERTEX v[] =
            {
                { .x = 0, .y = 0, .z = 0, .color = al_map_rgb_f(1, 0, 0) },
                { .x = 0, .y = 48, .z = 0, .color = al_map_rgb_f(1, 0, 0) },
                { .x = 32, .y = 64, .z = 0, .color = al_map_rgb_f(1, 0, 0) },
                { .x = 80, .y = 32, .z = 0, .color = al_map_rgb_f(1, 0, 0) },
                { .x = 112, .y = 0, .z = 0, .color = al_map_rgb_f(1, 0, 0) }
            };
al_draw_prim(v, NULL, NULL, 0, 5, ALLEGRO_PRIM_TRIANGLE_FAN);

EDIT: Ok I figured I can detect if the mouse is in a polygon using this algorithm still I feel this is not the right way to do this. I still need to call the function for every different polygon, that doesn't sound right.


Solution

  • You found an algorithm that does point-in-polygon for all your polygons and tells you which polygon the user clicked on. Good job you can use that. You wanted a built-in API call to do it and didn't get it. Since nobody else posted a contrary answer, I presume you won't. You should use what you've got.

    I will now address why this should feel right rather than not feel right.

    If the library itself had implemented it for you, it would still be constrained by the underlying OS primitives, which are in turn constrained by the algorithmic complexity of the problem, which is point-in-polygon per polygon. Thus, you may project all the polygons in your application, use one mouse hit box for the whole screen, and test them in turn. This is what the API would have had to do if there was an API for this.

    I project a significant chance you coded it and found it too slow. An easy solution that almost always works is to do an axis-oriented bounding box test first, which is fast.

    BugSquasher suggests an alternate solution. Render twice, with the second to an offscreen buffer with one color per polygon, and point-test the color. This also works, and is a good speedup if hit-testing is much more common than polygon moving. It does cost memory though.