Click here to Skip to main content
15,879,326 members
Articles / Programming Languages / C#

Hexagonal Maps – Part IV: Highlighting a Selected A Tile\Hexagon

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
5 Jul 2017CPOL15 min read 11.7K   7   1
This piece is actually an addendum to the prior paper on hexagonal maps based on the MonoGame Framework, Hexagonal Maps – Part III, as the subject matter presented here could have or should have been included in that paper as well

Image 1

Author’s Notes

The author wishes to thank Jjagg of the Monogame forums for his assistance in confirming the specific process that allows for the placing of multiple images into a single area on a displayed screen.

Corel’s PaintShop software is used for the graphic design of images. The discussion offers several options that a developer can obtain to do this type of work such as GIMP.

With this article, the author may not produce another piece on the subject matter for a little while as project development of the game that the author has in mind has now reached a point where the design of the actual map-board must commence. Considering that the author is not a graphic artist and has attempted this task twice before, it may take longer than expected to devise a method in which various graphic tiles can be designed that allow for structural continuations such as roads and rivers.

Please note that the version of the project source code that is provided with this piece has been substantially altered from the version that is downloadable with the previous article due to some refactoring and refinement. In addition, the single image object (texture2d) that has been the basis for the drawing methods has been moved into the array/array-list format, which is one standard for such a design. Thus, a collection is now used to supply the images to the drawing methods.

When a successful design technique has been implemented, a new piece will be written demonstrating it so that others with the same lack of artistic skill may take advantage of it.

Overview

This piece is actually an addendum to the prior paper on hexagonal maps based on the MonoGame Framework, Hexagonal Maps – Part III, as the subject matter presented here could have or should have been included in that paper as well. However, lacking definitive information on the process at the time, it was decided to make this additional piece a separate publication.

The rather simplistic process by which multiple images can be displayed in a single area on the display screen at the same time is rather straightforward. However, people not familiar enough with game development engines such as MonoGame or earlier, XNA, would most likely have a difficult time looking up such a technique on the Internet or inferring it from a text on the subject.

I tried a number of search terms on the Internet such as “overlaying images xna” and the like and did begin to come across several documents that supplied a basis for understanding how this technique was performed but nothing I found was succinct enough to explain simply as to how to make a stack of pancaked images that all appeared as one, single image. Most often, the information is out there but it is a lack of knowledge of the proper search terms to be used that provides the greatest impediment to resolving an issue.

As I mention in my notes above, Jjagg on the MonoGame Forums, was kind enough to answer my questions, which confirmed what I was starting to find in my own research.

So let’s get to it.

Tools of the Trade

For those of you who have just begun delving into the details of game development, you may have just begun to realize that you will have to become somewhat proficient with a graphic design tool. If you are using an environment such as Unity to develop your first project, you can be protected from such a necessity by the fact that such environments often offer kits that provide a lot of the graphic content you require.

However, if you plan on doing anything original and\or you are working with a development framework such as MonoGame instead, you will have to learn to use a competent graphic design tool in order to make the graphic content you want to present. For 3D game developers, Blender, is usually the popular choice due to the fact that it is completely free of charge. For those who already work in the 3D environments or are a professional, Maya, may be your cup of tea since you probably already purchased a personal version for your own use.

However, if you are interested in strategy gaming that is not going to reflect one of the latest trends in such development whereby icons and terrain hexagons reflect more of a 3D effect along with the subsequent animations, then you will require one of the image design tools that can afford quality 2D development for which most such strategy games are still based upon.

The most popular tool in this venue would of course be Gimp, which can be freely downloaded from the following link https://www.gimp.org/.

Gimp is a very powerful image editing tool and is very popular across a broad range of graphic project development. For learning to draw hexagons with Gimp, you may want to review the following video link https://www.youtube.com/watch?v=dHYTjFNSb9w.

Adobe Photoshop is probably also a very popular tool considering that it is a standard with professional graphic designers. However, it forces a user into a monthly subscription-based rental format, which costs approximately $300.00 USD a year, for use of the software that is quite complex to learn with probably the same learning curve as Blender. Nonetheless, if you have access to this tool and know how to use it, it will do the job just fine for you.

For me, I took a middle road a number of years ago when I first purchased a copy of Corel’s Paintshop Pro; a tool that has quite a bit of the power of PhotoShop but at a fraction of the cost while also having a somewhat easier learning curve. The support from Corel is excellent and yes, if you want to do image design without the hassles of the complexities of Photoshop, I highly recommend that you give Corel’s product line a try. The company has been around as long as Adobe if not longer and the products are being constantly refined. You can see the product line at the following link http://www.corel.com/en/.

You may wonder why take the time now to bring up such tools with this being the fourth article in a series I started months ago. Well, up until now, any graphic tool that was capable of drawing a hexagon with a transparent background would have sufficed for tinkering with the project source code I have been making available.

Yet, as we move into the more complex areas of terrain and unit design for an entire strategy map-board display, it may be worth your while to use one of the tools mentioned if you are not already doing so.

Image Layering (Creating the Images for Your MonoGame Project)

All of the noted tools above provide the ability to create image layers.

If you are just getting started with image design, this is an area that may take you a little while to absorb. At least it did for me.

The layering of images allows you to manually create multiple images of different sizes if desired and then provides for the ability to overlay them on top of a base image to produce one final image.

To accomplish this, you must follow the basic steps below, which uses Corel’s Paintshop Pro to demonstrate the processes.

1. Create a New Base Image

In your tool of choice, select File, and then New for a new base image as shown below:

Image 2

Select your image dimensions, which for our purposes would be 72×72.

Image 3

Select OK to create your new image. 

Note: The dark gray outline in the images shown is just the work-space background the images reside on.

Image 4

At 72×72 pixels, you will get a rather small base image with a transparent background in Corel’s PaintShop.

If the tool you are using does not provide a transparent background, you will have to replace the background with a transparency, which your tool’s eraser should provide.

2. Create a Hexagon Image

The next step is to create a hexagon outline using PaintShop’s preset symmetrical shape option as shown from the toolbar below.

Image 5

If your tool does not have such an option, then making a perfect hexagon will be quite difficult. As a result, you should procure a tool that does have this capability or find an image that has a 72×72 square with a hexagon already made within it.

Once you have selected the “Symmetric Shape” option, PaintShop will provide you with a number of options at the top toolbar, the most important one being, “Sides”. Enter “6” for this option, which will provide you with the capability to make a symmetrical hexagon. It should be noted that with PaintShop, the resulting hexagon will be a “pointy top” one so you will have to rotate it until you get the “flat topped” hexagon, which is what the project uses.

Changing the size of your tile image to anything other than 72×72 pixels or reversing the style of the hexagon will incur quite a number of serious changes to the source code. Such reliance on image sizes and hexagon orientation is one of the factors that makes generic programming of such environments very difficult.

When you are done creating your hexagon image, it should look similar to the image below:

Image 6

Notice that with PaintShop, the resultant hexagon will not have its inner area set to transparency but a default color; in this case, white.

Refill this inner area of the hexagon with any terrain style coloring of your choosing in order to represent a base terrain that you plan on using.

In my case, I have used dark green to represent meadow lands.

Image 7

In your MonoGame application, this image will be used as the primary image to be displayed on your screen. It will be the first image you draw to the screen to a specified set of coordinates.

3. Create a Border Image

Now, we need to create a secondary image that will be the border highlight that will correspond to each hexagon displayed on the screen. As a result, only one such image needs be created.

Before doing this, it should be noted that there are graphical techniques by which you can color the border of any displayed image as well as return the colored border back to its original color. However, this does add some complexity to the process and the one being discussed here is about the layering of images.

So create another hexagon image as described previously. Again, you will get another image as the first hexagon image shown above.

This time, you will have to carefully erase the inner area of the hexagon which will provide you with the transparency setting, leaving only the outermost border of the hexagon intact. You will most likely have to use both the foreground eraser as well as the background one to ensure that all areas within the hexagon have been made transparent. DO NOT use the background eraser in a way that expects only the background of the image to be replaced with the transparency. You will find that using it in such a manner will also erase parts of the hexagon border as well.

When you have completed your erasing, recolor the border to a bright yellow or another highlighting color you prefer. This will have to be done at the pixel level.

When you are done, you should have an image that looks like the one below:

Image 8

Though it may be difficult to see, the yellowed outline of the hexagon is there residing on a transparent background.

To test the veracity of your image, copy it and then Paste as New Layer to your original, base image. Your subsequent image should now appear as the one below:

Image 9

To see that the entire border of the hexagon has been highlighted, you may need to Zoom In with the graphic tool you are using.

Now before we rush into the coding, you will first have to inspect your newly combined image for any speckling in the inner area of the hexagon. Speckling will appear as slightly lighter, colored, individual pixels. This means that certain areas of your border image have not been cleared to complete transparency. To rectify this, simply note the coordinates of these pixels by using the rulers on the side and to the top of your work area for the image and then ensure that you erase them to transparency in your border image. Again, you may have to use both the foreground and background erasers to eliminate any speckling by making these areas transparent.

When you have done this, Undo the pasting of your border image over your base image, re-copy your border image and re-paste it as a new layer over your base image to verify that the area you targeted is now fully transparent.

When you have done this for all the noted speckled areas in the combined image, you should find after combining your border image with your base image that the entire inner area displays as it should.

What we have done here is the manual form of layering images. Now we will turn to performing this process with the MonoGame Engine in code.

Getting Into the Source Code

If you review the code below, you will notice that this method (which resides in the MainGame.cs class) is quite a bit different than the same method in the previous version of the source code. Here, the content data is now being loaded into an array-list in the Global.cs structure.

C#
private void Process_LoadContent()
{
   HexMapEngine.Classes.HexTileMapLoad loHexTileMapLoad = new
                HexMapEngine.Classes.HexTileMapLoad();

   // create a new SpriteBatch, which can be used to draw textures.
   coSpriteBatch = new SpriteBatch(GraphicsDevice);

   // ---
   // load tile content items into global array-list
   // ---
   HexMapEngine.Structures.Global.TEXTURE2D_ARRAY_LIST =
                loHexTileMapLoad.Load_Textured2DArrayList(this);

   // ---
   // Myra UI code
   // ---
   base.LoadContent();

   HexMapEngine.Structures.Global.MYRAUI_DEFAULT_SPRITE_FONT =
                loHexTileMapLoad.Load_MyraUIDefaultSpriteFont(this);

   Myra.MyraEnvironment.Game = this;
   Window.AllowUserResizing = false;
  		
   coBitmapFont = Myra.DefaultAssets.Font;
}

Each of the two tiles currently being loaded (the base image and the highlighted border image) are assigned a numeric id code for later extraction. You can see this in the Load_Textured2DArrayList() method (which is called in the above code) that resides in the HexTileMapLoad.cs class.

The MAP_HEX_TILE_ARRAY, a property of the Global.cs structure, will always be checked for loading when the HexTileMap.cs class is instantiated as an object in the Process_DrawEvent() method in the MainGame.cs class. This array will only be loaded once when it is first found to be null.

The MAP_HEX_TILE_ARRAY contains all of the hex-tile information that would be required on a per tile basis. At this point, some of this information is generated in the load process. As the application develops, this information will become more static and most likely be loaded from a database table.

The Find_MouseSelectedHex() Event

This event has now become crucial in terms of our ability to highlight a hexagon image’s border within the application.

This event, which is found both in the MainGame.cs (called from) and HexTileMap.cs (defined) classes is responsible for finding the actual hexagon, which has been selected.

In the method within the HexTileMap.cs class, a call is made to the actual algorithmic method in the HexTileMath.cs class, IsPoint_InsideHexagon(),which determines if the selected X,Y pixel coordinate has been found within the hexagon structure that has been passed to it.

If so, the structure property, HEX_TILE_SELECTED, is set to true. This property then is now responsible for telling the Draw_HexTile() method, found in the HexTileMap.cs class to whether it should perform a programmatic layering of the highlight border image or not.

The Draw_HexTile() Method

It is within this method that the actual layering of images takes place, which is surprisingly easy to accomplish.

By using both the SpriteBatch.Begin() and SpriteBatch.End() methods, you effectively set up the equivalent of a database transaction. However, in this case, instead of setting up of a buffer where all the results of your database calls are maintained, we are now doing this for all SpriteBatch.Draw calls that are between these two methods in a sequential manner.

By doing this in the prescribed manner, you may either update images at the specified coordinates or effectively pancake multiple images on top of each other if they are designed to be layered in such a manner.

Image 10

Again, the bottom-most image will be your base image with the succeeding images being your image layers as described in the above sections regarding the development of such images. Your images will be laid down in the order that you draw them. However, SpriteBatch.Begin() does provide you with a sort parameter, which can assist you with the order of the drawing of your images. However, for our purposes here, this will be unnecessary.

The code for Draw_HexTile() method is below:

C#
private void Draw_HexTile(HexMapEngine.Structures.HexTile poHexTile,
                          int piCalculatedMapTileX,
                          int piCalculatedMapTileY,
                          int piMapTileHexWidthInPixels,
                          int piMapTileHexHeightInPixels)
{
   Microsoft.Xna.Framework.Graphics.Texture2D  loTexture2DTile;

   loTexture2DTile = Get_TileTextureFromArrayListById(poHexTile.BASE_HEX_TEXTURE_ID);

   coSpriteBatch.Begin();

      coSpriteBatch.Draw(
                         loTexture2DTile,
                         new Rectangle(piCalculatedMapTileX, 
                            piCalculatedMapTileY, 
                            piMapTileHexWidthInPixels, 
                            piMapTileHexHeightInPixels),  // destination
                         new Rectangle(0, 0, 
                            piMapTileHexWidthInPixels, 
                            piMapTileHexHeightInPixels),  // source
                                                         
                         Color.White
                        );

      // hex-border overlay test (if hexagon is marked as selected)
      if (poHexTile.HEX_TILE_SELECTED) 
      {
         loTexture2DTile = Get_TileTextureFromArrayListById(2);

         coSpriteBatch.Draw(
                            loTexture2DTile,
                            new Rectangle(piCalculatedMapTileX, 
                                   piCalculatedMapTileY, 
                                   piMapTileHexWidthInPixels, 
                                   piMapTileHexHeightInPixels),  // destination
                            new Rectangle(0, 0, 
                                   piMapTileHexWidthInPixels, 
                                   piMapTileHexHeightInPixels),  // source
                                            Color.White
                                          );
                    }

   coSpriteBatch.End();

   // update hex tile in array pixel positions on map board
   Update_HexTileArrayPixelPositions(poHexTile, piCalculatedMapTileX, piCalculatedMapTileY);
}

The overlaying of the border highlight image occurs within the if statement, which tests the passed structure’s HEX_TILE_SELECTED property for true, and if found to be so will then retrieve the border highlight image from the global array-list and then draw it to the same screen location as the base image was just drawn to.

If you run the project provided at the download link at the end of this piece, you will now be able to see your selected hexagons by the yellow borders in each as shown below:

Image 11

The current version of this software’s source-code is freely available for download at the following link:

Since Myra.UI is used in this project, the version of this library that my project is using is also included in the download for your convenience. The Myra.UI library is also offered freely through the MonoGame forums.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Black Falcon Software, Inc.
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
SuggestionGreat article - but can you also include links to the previous series posts. Pin
Simon Jackson7-Jul-17 1:08
Simon Jackson7-Jul-17 1:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.