7
\$\begingroup\$

Say for a game with irregular hotspots (say Risk, or a strategy game like Paradox's Hearts of Iron or Crusader Kings), how do you

  1. Define a non-rectangular hotspot of irregular shape (much like a territory on a map?), in code?

  2. What tool can you use to trace out the hotspot and import into your game?

  3. What is the algorithm for detecting if someone has clicked within such a hotspot?

\$\endgroup\$

4 Answers 4

9
\$\begingroup\$

Besides the vector/polygon approach, another way to do this is to use a bitmap.

If each "color" in the bitmap represents a territory (France, Belgium etc.), then it's simply a matter of figuring out which pixel in the bitmap was clicked, looking up the color and determining if that color represents the territory of interest. You can even represent overlapping territories with specific colors, or treat your colors as a bitmask of territories.

In terms of tools, have your artists/content producer author the bitmap in any pixel editing tool. For example if you use Photoshop or the Gimp, you could represent different territories (France, Belgium etc.) as either named layers or as 1 layer but distinguishing the territories based on colors. You would then write a tool to convert the image/layers into a format that is suitable for game-internal purposes.

The game internal format would very likely be per-row run-length compressed (see: http://en.wikipedia.org/wiki/Run-length_encoding). You should be able to achieve very good compression ratios this way, as adjacent pixels on rows will very often belong to the same territory. The algorithm then becomes, for the current y coordinate of the mouse, traverse that row and figure out which run it belongs to, and therefore which corresponding territory.

\$\endgroup\$
5
  • \$\begingroup\$ Was about to write something similar, this is way easier than playing with polygons. \$\endgroup\$ Dec 10, 2010 at 21:02
  • \$\begingroup\$ Yeah, you also get pixel perfect precision. Messing with polygons is just a mess. \$\endgroup\$ Dec 11, 2010 at 3:38
  • 2
    \$\begingroup\$ +1 (because it's an easy and fast solution), although it will use more data and might not be as resolution-independent as the polygon approach. \$\endgroup\$
    – bummzack
    Dec 11, 2010 at 8:53
  • \$\begingroup\$ here's an exact explanation of technique: xnaresources.com/default.asp?page=Tutorial:ColorKeyMap \$\endgroup\$ Mar 25, 2012 at 14:06
  • \$\begingroup\$ You could use a vector program like inkscape to create the mask. This gives you the advantage of being able to create/edit the map from/with polygons & layers while providing easy export to e.g. *.bmp \$\endgroup\$
    – Exilyth
    Jan 27, 2014 at 8:45
7
\$\begingroup\$

You'll need to define the hotspots as a series of polygons that overlay your image. Then, when a user clicks on the map, go through the list of polygons (clickable hotspots) and see which (if any) the click point is inside of.

Also, you might look into how imagemaps in HTML are done. Not that you will be working with HTML, but basically they are essentially what you want to implement. They allow for defining hotspots as rectangles, circles, and polygons (which is what you want).

Here's a webpage describing HTML image maps that might give you some ideas: http://www.javascriptkit.com/howto/imagemap.shtml

Here's a Wikipedia article on algorithms to tell if a point is in a polygon: http://en.wikipedia.org/wiki/Point_in_polygon

\$\endgroup\$
2
\$\begingroup\$

You can define an arbitrary shape as just a series of points that are turned into line segments.

The collision test for "am I inside this arbitrary shape" is given by my answer here: In Cocos2D, how do I check for collisions against an arbitrary user-drawn shape?

\$\endgroup\$
1
\$\begingroup\$

For this kind of thing we use an image used as a mask, with transparent/opaque or black/white pixels. The masks aren't drawn, but are conceptually "placed" over the map region they cover.

When you get a click, first check the bounding box of the image. If it's outside, the player didn't click the region. If it's inside, check the pixel. If it's transparent/black, the player didn't click the region. Otherwise, he did.

If memory usage is a serious concern, you can use half-sized images and apply the appropriate screen to image coordinate conversion. You won't get pixel-perfect detection but you probably don't need it in this case.

Also, if you go transparent/opaque, either save the masks as PNG (or any other lossless compression scheme) or use a high threshold (alpha > 128 instead of alpha > 0). Otherwise, JPEG artifacts may cause some of the transparent pixels to appear not so transparent (say alpha = 1 or 2 instead of alpha = 0)

\$\endgroup\$
2
  • \$\begingroup\$ -1, this is just a considerably more wasteful version of jpaver's method. \$\endgroup\$
    – user744
    Dec 19, 2010 at 12:14
  • 1
    \$\begingroup\$ Depends on the details. We usually reuse the button images as the masks so this method ends up using less memory than jpaver's method. \$\endgroup\$
    – ggambetta
    Dec 19, 2010 at 13:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .