World Mapper (2)

April 2nd, 2007

We will now create a simple XNA program that uses some of the functionality discussed in our last 2 posts (XNA and GIS [1][2]). It will also introduce how to include input from the keyboard and mouse.

For the first time, we’ve added the option to download the source code at the bottom of this page. The primary reason for doing this is because our projects are becoming too complex to list the entire source code in the post itself. Instead, we will now try to highlight only the new and most important code snippets.

Our objective in this project is to rebuild our previous World Mapper project using XNA with some differences. Since official support for text in XNA won’t be available until later this month, the user won’t be available to enter latitude/longitude coordinates. Instead, the mouse can be used to click on the map and add a point. Additionally, by pressing the M key, the program’s mode switches from adding points to deleting points. Clicking on top of an existing point will then remove it from the map.

So let’s begin by creating a new XNA Windows Game as discussed in our previous posts. In our projects, I always first change the default names of files, folders, namespaces, etc. (see the source code for examples of this).

We will use 3 textures in this project: a world map image for the background, a point image, and a delete point image. To add the images to the project, simply right-click in the Solution Explorer and add an existing item. Be sure to set the file type to Content Pipeline Files and then import the images.

The class variables I added for the images look like this:

 

Texture2D t2dWorldMap;
Texture2D td2Point;
Texture2D td2Delete;

 

To keep track of the user-added points, I created a List collection of Point variables:

 

List mapPoints;

 

In the Initialize function, I resized the window size to match the dimensions of the world map image:

 

graphics.PreferredBackBufferWidth = 400;
graphics.PreferredBackBufferHeight = 200;
graphics.ApplyChanges();

 

In the LoadGraphicsContent function, I load the textures into the program using their Content Pipeline names:

 

t2dWorldMap = content.Load;(@"Content\Textures\WorldMap");
td2Point = content.Load(@"Content\Textures\point");
td2Delete = content.Load(@"Content\Textures\delete");

 

In the Update function, I check for mouse clicks and keyboard input. If the left mouse button is pressed, a point is either added or deleted depending on the map mode. If the M key is pressed, the mode switches. If the ESC key is pressed, the program ends.

In the Draw function, the textures are drawn in order of lowest to highest on the screen. The background map is drawn first, then any points, and finally the mouse cursor. For example, here is how the points are drawn:

 

foreach (Point p in mapPoints)
{
  spriteBatch.Draw(td2Point, new Rectangle(p.X - 2, p.Y - 2, 4, 4), Color.White);
}

 

Again, note how the texture locations are offset by half their size to ensure they are placed at the exact center of the mouse click.

When the user attempts to delete a point, the mouse coordinates are sent to this function and the nearest point within a set tolerance is returned to be removed:

 

protected Point FindNearestPoint(int x, int y)
{
  int bufferTolerance = 5;
  Point matchPoint = new Point();
  foreach (Point p in mapPoints)
  {
    if ((Math.Abs(p.X - x) <= bufferTolerance) &&
        (Math.Abs(p.Y - y) <= bufferTolerance))
      matchPoint = p;
  }
  return matchPoint;
}

 

Those are the main points involved in creating this project. Click on the link below to download the source code.

Download Source Code

Continue to part 3