<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Spatial Horizons &#187; XNA</title>
	<atom:link href="http://spatialhorizons.com/category/xna/feed/" rel="self" type="application/rss+xml" />
	<link>http://spatialhorizons.com</link>
	<description>Exploring Geographic Technologies with GIS, GPS, C#, XNA, and Open Source Tools</description>
	<lastBuildDate>Thu, 18 Sep 2008 19:00:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Map Tiles (4) &#8211; XNA Program</title>
		<link>http://spatialhorizons.com/2007/08/13/map-tiles-4-xna-program/</link>
		<comments>http://spatialhorizons.com/2007/08/13/map-tiles-4-xna-program/#comments</comments>
		<pubDate>Mon, 13 Aug 2007 22:47:07 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Map Tiles]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://spatialhorizons.com/2007/08/13/map-tiles-4-xna-program/</guid>
		<description><![CDATA[The last three posts discussed map tiles in some detail but without getting into programming. First, we described terminology surrounding map tiles. Then we setup a sample TileMap from an image of the world.  And finally, we covered some &#8220;tile math&#8221; examples. Now we will wrap everything up by developing a mapping program that [...]]]></description>
			<content:encoded><![CDATA[<p>The last three posts discussed map tiles in some detail but without getting into programming. First, we described <a href="http://spatialhorizons.com/2007/07/15/map-tiles-1-introduction/">terminology</a> surrounding map tiles. Then we setup a <a href="http://spatialhorizons.com/2007/07/24/map-tiles-2-sample-tilemap/">sample TileMap</a> from an image of the world.  And finally, we covered some &#8220;<a href="http://spatialhorizons.com/2007/08/06/map-tiles-3-tile-math/">tile math</a>&#8221; examples. Now we will wrap everything up by developing a mapping program that uses map tiles.</p>
<p>The program we created was built off one of our previous projects (see World Mapper parts <a href="http://spatialhorizons.com/2007/02/15/world-mapper-1/">1</a>,<a href="http://spatialhorizons.com/2007/04/02/world-mapper-2/">2</a>,<a href="http://spatialhorizons.com/2007/04/16/world-mapper-3/">3</a>) and, as always, the <a href="http://msdn2.microsoft.com/en-us/xna/default.aspx">XNA framework</a>. This project turned out to be much more complex than any of our previous programs so it would be impossible to cover all the source code in detail. Instead, this post will provide an overview of the program&#8217;s structure and then provide the source code for you to download and explore on your own.<br />
<span id="more-89"></span><br />
<strong>Program Structure</strong></p>
<p>Below is a graphic of all the classes used in the program with our main class named WorldMapper.cs.</p>
<p><img src="http://spatialhorizons.com/wp-content/uploads/2007/08/worldmapper_classes.jpg" alt="World Mapper Classes" /></p>
<p>We designed three classes to handle the maps tiles &#8211; a <strong>TileMap</strong>, <strong>TileSet</strong>, and <strong>Tile</strong> class. The main program only interacts with the TileMap class and the creation of TileSets and Tiles is done automatically.</p>
<p>We also needed a separate class to keep track of where the user is looking on the map. This concept of a &#8220;viewport&#8221; or &#8220;camera&#8221; is commonly used in game programming so the program knows which tiles need to be drawn on-screen. It also tracks which TileSet the user is viewing. The class was named <strong>GeoCamera2D</strong> and contains methods to pan, zoom, and recenter the map. Remembering the <a href="http://spatialhorizons.com/2007/08/06/map-tiles-3-tile-math/">discussion</a> in the last post on tile coordinates versus geographic coordinates, our camera stores all it&#8217;s location information in tile coordinates like 0,0 or 2.4, 1.3 and relies on the current TileSet class to convert the location to longitude/latitude coordinates when needed.</p>
<p>Both the <strong>Keyboard</strong> and <strong>Mouse</strong> classes have been covered in previous posts so we will skip those now.  Some of the code was updated but the main functionality remained the same.</p>
<p><strong>C# Programming</strong></p>
<p>Our map tilling program follows the standard XNA structure but with the addition of our tile mapping classes. Some of the source code is covered below.</p>
<p>We first create several variables to store our new classes and constants to define some pixel parameters:</p>
<p>
<pre lang="csharp">shTileMap _tileMap;
shGeoCamera2D _camera2D;

const int _mapWidth = 800;
const int _mapHeight = 400;

const int _tileWidth = 800;
const int _tileHeight = 400;
</pre>
</p>
<p>In the constructor, we initiate our TileMap class with some general information, including the extent of the entire map (in this case, the entire world). The camera class is also initiated:</p>
<p>
<pre lang="csharp">_tileMap = new shTileMap("WorldMap", _tileWidth, _tileHeight, -180, -90, 180, 90);
_camera2D = new shGeoCamera2D(_mapWidth, _mapHeight, _tileWidth, _tileHeight);</pre>
</p>
<p>Next we have to define each of our three TileSets (see <a href="http://spatialhorizons.com/2007/07/24/map-tiles-2-sample-tilemap/">part 2</a> for more information). We first use the AddTileSet method to create a new TileSet with information on it&#8217;s zoom level (0), and tile coordinate extent (0,0 to 1,1).</p>
<p>
<pre lang="csharp">//--> setup TileSet 0
shTileSet newTileSet = _tileMap.AddTileSet(0, 0, 0, 1, 1, _graphics.GraphicsDevice);</pre>
</p>
<p>We then have to define some conversion parameters (see <a href="http://spatialhorizons.com/2007/08/06/map-tiles-3-tile-math/">part 3</a>) to enable the TileSet to convert between tile coordinates and geographic coordinates.</p>
<p>
<pre lang="csharp">newTileSet.DefineConversionParameters(new Vector2(-180, -90), 360, 180);</pre>
</p>
<p>We repeat the TileSet creation twice more for the other TileSets.</p>
<p>In the Update method, we check for mouse and keyboard clicks.  A mouse click simply shows the user the geographic coordinates of where they clicked on the map.</p>
<p>
<pre lang="csharp">// check if a mouse click has occured
_mouse.Update();
if (_mouse.LeftButton == ButtonState.Pressed)
{
    //--> convert click position to grid position
    Vector2 gridPos = _camera2D.ConvertScreenPos2GridPos(_mouse.X, _mouse.Y);

    //--> convert grid position to real world position
    Vector2 realPos = _tileMap.ActiveTileSet.ConvertGridPos2RealPos(gridPos.X, gridPos.Y);

    //--> update last click position for display on-screen
    _lastClickPos = realPos;
}</pre>
</p>
<p><img src="http://spatialhorizons.com/wp-content/uploads/2007/08/worldmapper_screenshot.jpg" alt="World Mapper Screenshot" /></p>
<p>Arrow keys will pan around the map, the Z key zooms in, and the X key zooms out. One of the keyboard checks looks like this:</p>
<p>
<pre lang="csharp">// check if a key has been pressed
_keyboard.Update(gameTime);
if (_keyboard.IsNewKeyDown(Keys.Left))
{
    _camera2D.PanLeft(_tileMap.ActiveTileSet.MinCol);
}</pre>
</p>
<p>Every time a pan occurs, we send as a parameter the boundary being approached by the pan to ensure the user can&#8217;t go outside the bounding box of the map.</p>
<p>Finally, in the Draw method, displaying the map takes only one line:</p>
<p>
<pre lang="csharp">_tileMap.Draw(_spriteBatch, _camera2D);</pre>
</p>
<p><strong>Conclusion</strong></p>
<p>The code involved in this project is rather complex and represents only one approach to making a tile-based mapping program.  The objective was to create a framework that could easily be applied to other TileMaps of different sizes, extents, and tile counts. There are aspects of the program that would need to be addressed though before it succeeded in that respect. For example, our program pre-loads all 22 map tiles for convenience but this wouldn&#8217;t be practical for a TileMap that has hundreds of tiles. Some form of a &#8220;tile cache&#8221; would need to be implemented that only loaded and stored tiles within the user&#8217;s view. </p>
<p>The source code and compiled program are available to download below.  The source code requires the <a href="http://msdn2.microsoft.com/en-us/xna/aa937795.aspx">XNA Game Studio Express</a> and the program download requires at minimum the <a href="http://www.microsoft.com/downloads/details.aspx?familyid=A7DA4763-6807-4BD5-8D18-18C60C437F93&#038;displaylang=en">XNA runtime redistributable</a> to run.</p>
<p><a href="http://spatialhorizons.com/downloads/WorldMapperMapTiles.zip"><img border="0" alt="Download Source Code" src="http://spatialhorizons.com/downloads/code_download.jpg" /></a><br />
<a href="http://spatialhorizons.com/downloads/WorldMapperMapTiles_EXE.zip"><img border="0" alt="Download Program" src="http://spatialhorizons.com/downloads/program_download.jpg" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://spatialhorizons.com/2007/08/13/map-tiles-4-xna-program/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mapscript and XNA (3)</title>
		<link>http://spatialhorizons.com/2007/07/08/mapscript-and-xna-3/</link>
		<comments>http://spatialhorizons.com/2007/07/08/mapscript-and-xna-3/#comments</comments>
		<pubDate>Sun, 08 Jul 2007 11:46:37 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Mapserver]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://spatialhorizons.com/2007/07/08/mapscript-and-xna-3/</guid>
		<description><![CDATA[Continuing with our program that combines Mapserver (via the Mapscript API) and XNA, we next added functionality to the update method our of XNA program. We check for a mouse click to initiate a map pan and also for key presses to zoom in, out and return to full extent. At the end, if any [...]]]></description>
			<content:encoded><![CDATA[<p>Continuing with our <a href="http://spatialhorizons.com/2007/06/24/mapscript-and-xna-1/">program</a> that combines <a href="http://mapserver.gis.umn.edu/">Mapserver</a> (via the <a href="http://mapserver.gis.umn.edu/docs/reference/mapscript">Mapscript API</a>) and <a href="http://msdn2.microsoft.com/en-us/xna/default.aspx">XNA</a>, we next added functionality to the update method our of XNA program. We check for a mouse click to initiate a map pan and also for key presses to zoom in, out and return to full extent. At the end, if any map event has occurred, the map will be updated. It is in the updating that a new Mapserver image is generated and prepared for displaying on-screen. </p>
<p>
<pre lang="csharp">protected override void Update(GameTime gameTime)
{
    // check if a mouse click has occured
    mouse.Update();
    if (mouse.LeftButton == ButtonState.Pressed)
    {
        mapserver.ZoomMap(1, mouse.X, mouse.Y);
    }

    // check if a key has been pressed
    KeyboardState keyState = Keyboard.GetState();
    if (keyState.IsKeyDown(Keys.F))
    {
        graphics.ToggleFullScreen();
    }
    else if (keyState.IsKeyDown(Keys.Z))
    {
        mapserver.ZoomMap(2, mapserver.MapPixelCenter.X,
                      mapserver.MapPixelCenter.Y);
    }
    else if (keyState.IsKeyDown(Keys.X))
    {
        mapserver.ZoomMap(-2, mapserver.MapPixelCenter.X,
                      mapserver.MapPixelCenter.Y);
    }
    else if (keyState.IsKeyDown(Keys.C))
    {
        mapserver.ZoomMapFullExtent();
    }
    else if (keyState.IsKeyDown(Keys.Escape))
        this.Exit();

    // check if a new mapserver image needs to be generated
    if (mapserver.RefreshMap)
    {
        mapserver.UpdateMap(graphics.GraphicsDevice);
    }

    base.Update(gameTime);
}</pre>
</p>
<p><span id="more-78"></span><br />
Each option relies on our MapserverXNA class discussed in the last <a href="http://spatialhorizons.com/2007/07/01/mapscript-and-xna-2/">post</a>. Since all the functionality is hidden within this class, coding our main program is very straightforward. Additionally, zooming in and out is performed with the help of our Image Swapping class we created in a <a href="http://spatialhorizons.com/2007/06/17/xna-and-gis-4-image-swapping/">previous post</a>. This adds a fading in/out effect but none of this code is even visible in the main program.</p>
<p>As shown above, a mouse click invokes a pan of the map (click <a href="http://spatialhorizons.com/2007/06/09/mapscript-demo-3/">here</a> for more information on zooming and panning with Mapscript). The mouse&#8217;s X/Y click coordinates will become the new center of the map. Within the MapserverXNA class, we added a shift effect when a pan occurs using the previously mentioned <a href="http://spatialhorizons.com/2007/06/17/xna-and-gis-4-image-swapping/">Image Swapping class</a>. Upon the mouse click, the existing image is shifted and then the new image then just replaces it. This sliding effect is an alternative to the fading effect used for zooming b/c it wouldn&#8217;t make sense to pan the map and then fade in the new image.</p>
<p>The last portion of code added is in the draw method. Here we draw our map image, mouse cursor, and some text.</p>
<p>
<pre lang="csharp">protected override void Draw(GameTime gameTime)
{
    graphics.GraphicsDevice.Clear(Color.White);
    spriteBatch.Begin(SpriteBlendMode.AlphaBlend);

    mapserver.DrawMap(spriteBatch, gameTime);

    mouse.Draw(spriteBatch);

    spriteBatch.DrawString(font, "Z = Zoom in", new Vector2(5, 4), Color.Black);
    spriteBatch.DrawString(font, "X = Zoom out", new Vector2(5, 16), Color.Black);
    spriteBatch.DrawString(font, "C = Full Extent", new Vector2(5, 28), Color.Black);
    spriteBatch.DrawString(font, "Click to pan", new Vector2(5, 40), Color.Black);

    spriteBatch.End();

    base.Draw(gameTime);
}</pre>
</p>
<p><strong>Conclusion</strong></p>
<p>This post concludes probably the most complex project we have demonstrated so far. Some of the Mapserver-related code was not discussed because it has been covered in our previous projects (<a href="http://spatialhorizons.com/2007/05/19/mapserver-1-10-minute-tutorial/">Mapserver &#8211; 10 Minute Tutorial</a>, <a href="http://spatialhorizons.com/2007/05/26/mapscript-demo-1/">Mapscript Demo</a>). The entire source code for this project is available to download below. The program&#8217;s requirements (C#, XNA, Mapserver, and a valid Mapserver map file) have all been discussed in our other <a href="http://spatialhorizons.com/projects/">projects</a>. Questions and comments are always welcome at james [at] spatialhorizons.com.</p>
<p><a href="http://spatialhorizons.com/downloads/MapscriptXNA.zip"><img border="0" alt="Download<br />
Source Code" src="http://spatialhorizons.com/downloads/code_download.jpg" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://spatialhorizons.com/2007/07/08/mapscript-and-xna-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mapscript and XNA (2)</title>
		<link>http://spatialhorizons.com/2007/07/01/mapscript-and-xna-2/</link>
		<comments>http://spatialhorizons.com/2007/07/01/mapscript-and-xna-2/#comments</comments>
		<pubDate>Sun, 01 Jul 2007 13:38:00 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Mapserver]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://spatialhorizons.com/2007/07/01/mapscript-and-xna-2/</guid>
		<description><![CDATA[In order to use Mapserver in XNA, we need to create a class that primarily serves as an interface between XNA and Mapscript (Mapserver&#8217;s API).  Our last post discussed in general how to accomplish this but now let&#8217;s add some code.
MapserverXNA Class
We named the class MapserverXNA and the properties and methods look like this:


The [...]]]></description>
			<content:encoded><![CDATA[<p>In order to use Mapserver in XNA, we need to create a class that primarily serves as an interface between XNA and Mapscript (Mapserver&#8217;s API).  Our last <a href="http://spatialhorizons.com/2007/06/24/mapscript-and-xna-1/">post</a> discussed in general how to accomplish this but now let&#8217;s add some code.</p>
<p><strong>MapserverXNA Class</strong></p>
<p>We named the class MapserverXNA and the properties and methods look like this:</p>
<p><img src="http://spatialhorizons.com/wp-content/uploads/2007/07/uml_mapserverxna.jpg" alt="UML MapserverXNA Class" /><br />
<span id="more-77"></span></p>
<p>The properties include information on the map&#8217;s size (height, width, and center), the location of the map file, and a boolean value (RefreshMap) that tracks whether the map needs to be updated.</p>
<p>The methods include the ability to update the map (i.e. generate a new image from Mapserver) and draw the map onscreen. There are also two zoom methods: ZoomMap allows for zooming in, out, and panning while ZoomMapFullExtent returns the map to the full extent.</p>
<p>We won&#8217;t discuss in detail the code inside of this class. It is included in the source code download below so you are welcome to take a look yourself.</p>
<p><strong>Using the MapserverXNA Class</strong></p>
<p>The next step is to setup a XNA program to use the newly designed class. We could start from scratch but instead this project will loosely build off the structure of <a href="http://spatialhorizons.com/2007/04/02/world-mapper-2/">World Mapper</a> project from a while back.  It does follow the standard form of a XNA game application as discussed in a <a href="http://spatialhorizons.com/2007/03/25/xna-and-gis-2/">previous post</a>. We also incorporated what we learned in our <a href="http://spatialhorizons.com/2007/05/26/mapscript-demo-1/">Mapscript Demo</a> and our post on <a href="http://spatialhorizons.com/2007/05/06/xna-and-gis-3/">XNA font</a>.</p>
<p>With our XNA game program setup, we added several more fields (private variables) to the main game class:</p>
<p>
<pre lang="csharp">GraphicsDeviceManager graphics;
ContentManager content;
SpriteBatch spriteBatch;
shMouse mouse;
shMapserver mapserver;
SpriteFont font;</pre>
</p>
<p>In the constructor, we then setup our mouse class and initialized the MapserverXNA class with a valid map file string and size in pixels.</p>
<p>
<pre lang="csharp">public MapscriptXNA()
{
    graphics = new GraphicsDeviceManager(this);
    content = new ContentManager(Services);

    mouse = new shMouse();
    mapserver = new shMapserver(@"C:\ms4w\apps\gmap\htdocs\gmap75.map",
        600, 600);
}</pre>
</p>
<p>In the initialize method, we resize the screen to match the map size:</p>
<p>
<pre lang="csharp">protected override void Initialize()
{
    graphics.PreferredBackBufferWidth = mapserver.MapWidth;
    graphics.PreferredBackBufferHeight = mapserver.MapHeight;
    graphics.ApplyChanges();
    base.Initialize();
}</pre>
</p>
<p>In the load graphics method, we load both the mouse cursor and font from using XNA&#8217;s Content Pipeline:</p>
<p>
<pre lang="csharp">protected override void LoadGraphicsContent(bool loadAllContent)
{
    if (loadAllContent)
    {
        spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
        mouse.Cursor = content.Load<Texture2D>(@"Content\Textures\MouseCursor");
        font = content.Load<SpriteFont>(@"Content\Font\MapFont");
    }
}</pre>
</p>
<p>We will continue in our next post with the rest of the application&#8217;s code but the entire source code can be downloaded below. For new readers, we encourage you to glance over our <a href="http://spatialhorizons.com/projects/">past projects</a> or read the new <a href="http://spatialhorizons.com/faqs/">FAQs page</a>. </p>
<p><a href="http://spatialhorizons.com/downloads/MapscriptXNA.zip"><img border="0" alt="Download Source Code" src="http://spatialhorizons.com/downloads/code_download.jpg" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://spatialhorizons.com/2007/07/01/mapscript-and-xna-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mapscript and XNA (1)</title>
		<link>http://spatialhorizons.com/2007/06/24/mapscript-and-xna-1/</link>
		<comments>http://spatialhorizons.com/2007/06/24/mapscript-and-xna-1/#comments</comments>
		<pubDate>Sun, 24 Jun 2007 13:20:53 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Mapserver]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://spatialhorizons.com/2007/06/24/mapscript-and-xna-1/</guid>
		<description><![CDATA[We&#8217;ve demonstrated a number of smaller projects over the past couple of months showcasing some simple mapping and XNA applications. Now things are starting to get more interesting as we build upon what we&#8217;ve learned in an effort to create more interesting products. This next series of posts combines aspects from several of our projects, [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve demonstrated a number of smaller projects over the past couple of months showcasing some simple mapping and XNA applications. Now things are starting to get more interesting as we build upon what we&#8217;ve learned in an effort to create more interesting products. This next series of posts combines aspects from several of our projects, including <a href="http://spatialhorizons.com/2007/02/15/world-mapper-1/">World Mapper</a>, <a href="http://spatialhorizons.com/2007/05/19/mapserver-1-10-minute-tutorial/">Using Mapserver</a>, <a href="http://spatialhorizons.com/2007/05/26/mapscript-demo-1/">Mapscript Demo</a>, and the <a href="http://spatialhorizons.com/2007/06/17/xna-and-gis-4-image-swapping/">Image Swapping example</a>. Basically, we now have the opportunity to incorporate Mapserver-generated images into an XNA program. </p>
<p><span id="more-71"></span><br />
<strong>Quick Review</strong></p>
<p><a href="http://mapserver.gis.umn.edu/">Mapserver</a> is a map-rendering program mainly used for web mapping applications.  It can also be used for desktop applications via it&#8217;s <a href="http://mapserver.gis.umn.edu/docs/reference/mapscript">Mapscript API</a>. </p>
<p>In our previous Mapserver and Mapscript posts, we used a sample dataset of Canada that can be downloaded <a href="http://www.maptools.org/dl/ms4w/gmap_ms4w_ms410.zip">here</a>. Since it is freely available and easy to use, we will continue to use it in this project. We will cover making your own datasets for Mapserver in a future post.</p>
<p><strong>Adding XNA</strong></p>
<p>We already <a href="http://spatialhorizons.com/2007/05/26/mapscript-demo-1/">created</a> a standard forms-based application for interacting with Mapserver. There were some buttons and the map image just switches upon refreshes. If the project were scored on presentation, it would receive low marks. Nothing stands out, the visual aspects are relatively limited and fail to draw the user in. Fortunately <a href="http://en.wikipedia.org/wiki/Microsoft_XNA">XNA</a>, in addition to being a game development platform, also offers a great set of features for producing mapping applications with some graphical enhancements.</p>
<p><strong>Using Mapserver in XNA</strong></p>
<p>It is actually very easy to use Mapserver map images in XNA. Before we begin coding our project, let&#8217;s think about the steps needed to do so:</p>
<ol>
<li>Our XNA Program requests a new map image. This request will occur upon startup and any time the user interacts with the map via zooming or panning.</li>
<li>Using the Mapscript API, a new map image needs to be generated (see <a href="http://spatialhorizons.com/2007/06/02/mapscript-demo-2/">Mapscript Demo 2</a> for more info). The map image can be returned as a memory stream or saved to a temporary image file in JPEG or PNG format.</li>
<li>The XNA program then loads the map image as a 2D texture and displays it on-screen (see <a href="http://spatialhorizons.com/2007/03/25/xna-and-gis-2/">XNA and GIS 2</a> for more info). Our <a href="http://spatialhorizons.com/2007/06/17/xna-and-gis-4-image-swapping/">image swapping example</a> shows one way to produce fade in/out transitions we could use when switching map images.</li>
</ol>
<p>The map image is displayed until another request is made and the process is repeated. Both the speed of Mapserver and XNA enable this process to take less than a second to complete.</p>
<p>We will start coding in our next post and rely on an object oriented design to create a C# class that completes the steps above automatically. Adhering to this type of approach ensures we can easily add Mapserver functionality to other future XNA projects without much hassle. Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://spatialhorizons.com/2007/06/24/mapscript-and-xna-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XNA and GIS (4) &#8211; Image Swapping</title>
		<link>http://spatialhorizons.com/2007/06/17/xna-and-gis-4-image-swapping/</link>
		<comments>http://spatialhorizons.com/2007/06/17/xna-and-gis-4-image-swapping/#comments</comments>
		<pubDate>Sun, 17 Jun 2007 13:43:08 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://spatialhorizons.com/2007/06/17/xna-and-gis-4-image-swapping/</guid>
		<description><![CDATA[We&#8217;ve already discussed in general how XNA could be used as our graphics engine for building a mapping application. Today we will demonstrate a specific example of XNA in action as it relates to map images.
Let&#8217;s assume that we have a map image already generated by a mapping engine (Mapserver/Mapscript for example).


A user then zooms [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve already <a href="http://spatialhorizons.com/2007/03/17/xna-and-gis-1/">discussed</a> in general how <a href="http://msdn2.microsoft.com/en-us/xna/default.aspx">XNA</a> could be used as our graphics engine for building a mapping application. Today we will demonstrate a specific example of XNA in action as it relates to map images.</p>
<p>Let&#8217;s assume that we have a map image already generated by a mapping engine (<a href="http://spatialhorizons.com/2007/05/26/mapscript-demo-1/">Mapserver/Mapscript</a> for example).</p>
<p><img src="http://spatialhorizons.com/wp-content/uploads/2007/06/imageswap_image1.jpg" alt="Image 1" width="450" /></p>
<p><span id="more-72"></span></p>
<p>A user then zooms in on the map and a second image is generated.</p>
<p><img src="http://spatialhorizons.com/wp-content/uploads/2007/06/imageswap_image2.jpg" alt="Image 2" width="450" /></p>
<p>Displaying the second image could be as simple as switching between the images.  In most desktop applications, each map refresh does just that. Nothing fancy, but when you have a powerful graphical engine at your disposal, there is much more we can do.</p>
<p><strong>Texture Opacity</strong></p>
<p>XNA allows each texture (e.g. map image) to have an opacity (&#8221;<a href="http://msdn2.microsoft.com/en-us/library/bb195887.aspx">alpha</a>&#8220;) value ranging from 0 (transparent) to 255 (opaque). This gives us the ability to simulate an image fading in or out by quickly changing the alpha value. The texture&#8217;s alpha (a) is determined when it is drawn using a sprite batch:</p>
<p>
<pre lang="csharp">spriteBatch.Draw(texture, rectangle, new Color(r, g, b, a));</pre>
</p>
<p><strong>Image Swapping Class Design</strong></p>
<p>The first step is to design and program an &#8220;image swapping&#8221; class that we can use in various applications. This will enable us to easily implement image transitions such as fades or shifts.</p>
<p>The class must accept 2 images, their locations, and how fast the transition will occur. The image fading in is named &#8220;InImage&#8221; and the image fading out is &#8220;OutImage&#8221;. After some testing and revisions, our final object model looks like this:</p>
<p><img src="http://spatialhorizons.com/wp-content/uploads/2007/06/uml_imageswaphelper.jpg" alt="UML Image Swap Helper" /></p>
<p>The TransitionType property and SetShiftDestination method will be used in the future for performing an image swap when the map is recentered. It would be unnecessary to fade between 2 images that are at the same scale.  Instead, the transition would involve shifting the first image and then the second image immediately replaces the first image.</p>
<p><strong>Using the Image Swap Helper Class</strong></p>
<p>We&#8217;ve setup a XNA game application (source code below) that demonstrates how the image swapping class works.  It fades between the 2 images shown above. Here is an overview of how the class was implemented in our application.</p>
<p>Create a private variable (&#8221;field&#8221;) using the object:</p>
<p>
<pre lang="csharp">shImageSwapHelper _imageSwapper;</pre>
</p>
<p>Then create a new instance of the class and define a transition time in milliseconds.</p>
<p>
<pre lang="csharp">_imageSwapper = new shImageSwapHelper();
_imageSwapper.TransitionTime = 5000.0f;</pre>
</p>
<p>Set the incoming image and outgoing image rectangle sizes. In this scenario, they are both the entire size of the map window so:</p>
<p>
<pre lang="csharp">_imageSwapper.InRect = new Rectangle(0, 0,
     _mapWidth, _mapHeight);
_imageSwapper.OutRect = new Rectangle(0, 0,
     _mapWidth, _mapHeight);</pre>
</p>
<p>Load the images into textures from a file name:</p>
<p>
<pre lang="csharp">_imageSwapper.InImage =
     Texture2D.FromFile(graphics.GraphicsDevice, "Image2.jpg");
_imageSwapper.OutImage =
     Texture2D.FromFile(graphics.GraphicsDevice, "Image1.jpg");</pre>
</p>
<p>In the Update method, we see if the image transition is occurring. If it isn&#8217;t, we start the transition:</p>
<p>
<pre lang="csharp">
if (!_imageSwapper.InProgress)
{
    _imageSwapper.StartTransition();
}</pre>
</p>
<p>Finally, in the Draw method, our image transition is drawn with one line of code.  The individual alpha values of each image are controlled internally by the class.</p>
<p>
<pre lang="csharp">_imageSwapper.Draw(spritebatch, gameTime);</pre>
</p>
<p>Upon running the application, the first image will display and over the course of 5000 milliseconds, it will fade out while the second image will fade in. This pattern is repeated until the program is exited.</p>
<p><strong>Conclusion</strong></p>
<p>This is only another building block to our ultimate goal. It does show how easy XNA can be used to improve the graphical quality of an application.  As always, the source code is available to download.</p>
<p><a href="http://spatialhorizons.com/downloads/ImageSwapDemo.zip"><img border="0" alt="Download Source Code" src="http://spatialhorizons.com/downloads/code_download.jpg" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://spatialhorizons.com/2007/06/17/xna-and-gis-4-image-swapping/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Console Demo (1)</title>
		<link>http://spatialhorizons.com/2007/05/13/console-demo-1/</link>
		<comments>http://spatialhorizons.com/2007/05/13/console-demo-1/#comments</comments>
		<pubDate>Sun, 13 May 2007 02:29:23 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://spatialhorizons.com/2007/05/13/console-demo-1/</guid>
		<description><![CDATA[This project demonstrates how to use the new font support in XNA by building a basic console type application. Eventually it could be combined into a more robust program but for now we just want to focus on text input.  For an introduction to the new XNA font support, see our last post.
Our definition [...]]]></description>
			<content:encoded><![CDATA[<p>This project demonstrates how to use the new font support in XNA by building a basic console type application. Eventually it could be combined into a more robust program but for now we just want to focus on text input.  For an introduction to the new XNA font support, see our <a href="http://spatialhorizons.com/2007/05/06/xna-and-gis-3/">last post</a>.</p>
<p>Our definition of a console consists of two parts. First is the command prompt line where the user can enter text, press enter, and something occurs if the user enters a valid command. Below that line are past lines of text that the user has typed or it could be used to display information about the program.</p>
<p><img width="408" height="126" id="image55" alt="Console1" src="http://spatialhorizons.com/wp-content/uploads/2007/05/console1.jpg" /></p>
<p><span id="more-54"></span> <strong><br />
Console Object</strong></p>
<p>We first need to design our console object that will be used to store both the input text and the past lines of text for display purposes.</p>
<p><img alt="dia_shConsole" id="image56" src="http://spatialhorizons.com/wp-content/uploads/2007/05/dia_shconsole.png" /></p>
<p>As you can see, we define how many history lines to remember and the pixel height of each line. We also store the prompt symbol (::) separate from the user-inputed text in case we want to change it in our application. The console&#8217;s methods includes functions to add text, erase text, clear text, and the actual drawing of the console.</p>
<p><strong>Keyboard Object</strong></p>
<p>Having a console object is only half of the solution. We also need a way to tell the console what text the user is typing and when the user presses keys such as ENTER, SPACE, BACKSPACE, etc. So we decided to create a Keyboard object that will encapsulate code needed to find which key the user pressed.</p>
<p><img id="image57" alt="dia_shKeyboard" src="http://spatialhorizons.com/wp-content/uploads/2007/05/dia_shkeyboard.png" /></p>
<p>There is only one public property (LastKeyPressed) and two methods. If you download the source code, you will see that there is also private variable used to store the keyboard state:</p>
<p>
<pre lang="csharp">KeyboardState keyState;</pre>
</p>
<p>When either method is called, this keyState is updated just as any other XNA program would do. But since we are creating a console demonstration, we need to convert the pressed key result (Keys.X, Keys.Enter, etc.) to a string so we can add it to our console.  For example, if the user presses &#8220;S&#8221;, we add &#8220;S&#8221; to the console but if the BACKSPACE key is pressed, we need to remove text from the console. Pressing the space bar should generate a 1 character empty string &#8221; &#8221; to simulate a space. Those examples are why we created a FindPressedKey method.</p>
<p><strong>Using the Objects</strong></p>
<p>We then setup a new XNA game application, add the two new classes for our console and keyboard objects, and develop their code.  Following the steps in our <a href="http://spatialhorizons.com/2007/05/06/xna-and-gis-3/">last post</a>, we also setup a XNA SpriteFont to store the type of text to be displayed in our console. Using the objects in our main program is fairly easy. Below is a quick summary and the full source code is available below.</p>
<p><em>Step 1 &#8211; Define the classes</em></p>
<p>
<pre lang="csharp">shConsole console = new shConsole();
shKeyboard keyboard = new shKeyboard();</pre>
</p>
<p><em>Step 2 &#8211; Check for pressed keys in the Update function</em></p>
<p>
<pre lang="csharp">string keyPress = keyboard.FindPressedKey();
if (keyPress == ">>ESCAPE")
{
  this.Exit();
}
else if (keyPress == ">>ENTER")
{
  if (console.Text == "QUIT") this.Exit();
  console.ClearText();
}
else if (keyPress == ">>BACKSPACE")
{
  console.Backspace(1);
}
else
{
console.AddText(keyPress);
}</pre>
</p>
<p><em>Step 3 &#8211; Draw the console in the Draw function</em></p>
<p>
<pre lang="csharp">console.Draw(spriteBatch, courierNew);</pre>
</p>
<p><strong>Time Delay</strong></p>
<p>The program runs extremely fast so it could potentially be checking for keyboard presses dozens of times per second. This does create a situation where a single key press by the user is picked up several times by program and consequently the console would show the same letter several times. A simple way to avoid this is to add a slight delay between key presses and that is how our program avoids the duplicate letter effect. After a key press, a 50 millisecond delay is enforced where any subsequent key presses are ignored until the time has passed. This isn&#8217;t a perfect solution but does a good enough job for now.</p>
<p>Every XNA game template comes with a GameTime variable already ready to use for both the Update and Draw functions. Finding out how much time has passed since the last frame is easy:</p>
<p>
<pre lang="csharp">gameTime.ElapsedRealTime.Milliseconds;</pre>
</p>
<p>To track when a certain time has elapsed, just add a time counter variable:</p>
<p>
<pre lang="csharp">timeCounter += gameTime.ElapsedRealTime.Milliseconds;</pre>
</p>
<p>And then use it to avoid performing tasks until an amount if time has pass:</p>
<p>
<pre lang="csharp">if (timeCounter >= 50)
{
  // do something
  timeCounter = 0;
}</pre>
</p>
<p><strong>Conclusion</strong></p>
<p>Feel free to download the source code and try it out for yourself. There is a lot of room for improvement but at least we have laid the foundation to include some command-line functionality into our future programs.</p>
<p><a href="http://spatialhorizons.com/downloads/ConsoleDemo_v0.1.zip"><img border="0" alt="Download Source Code" src="http://spatialhorizons.com/downloads/code_download.jpg" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://spatialhorizons.com/2007/05/13/console-demo-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XNA and GIS (3) &#8211; Using Fonts</title>
		<link>http://spatialhorizons.com/2007/05/06/xna-and-gis-3/</link>
		<comments>http://spatialhorizons.com/2007/05/06/xna-and-gis-3/#comments</comments>
		<pubDate>Sun, 06 May 2007 03:36:31 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://spatialhorizons.com/2007/05/06/xna-and-gis-3/</guid>
		<description><![CDATA[The recent release of Microsoft&#8217;s XNA Game Studio Refresh offers one important new feature: font support.  If we want to build any sort of mapping application, text is an absolute necessity. So here is a quick tutorial of how to incorporate font into a XNA program.  For a complete description, check out the [...]]]></description>
			<content:encoded><![CDATA[<p>The recent release of Microsoft&#8217;s XNA Game Studio <a target="_blank" href="http://msdn2.microsoft.com/en-us/xna/aa937795.aspx">Refresh</a> offers one important new feature: font support.  If we want to build any sort of mapping application, text is an absolute necessity. So here is a quick tutorial of how to incorporate font into a XNA program.  For a complete description, check out the Game Studio documentation.</p>
<p style="font-weight: bold">Font Preparation</p>
<p>Font is treated similar to any other 2D sprite in XNA except for the source of the texture.  Instead of relying on graphics, XNA obtains the font from the font files already installed on your computer. Examples include Times New Roman, Courier New, and Arial.</p>
<p>Preparing to use a font is simple. In any XNA program, right-click in the Solution Explorer and select Add New Item. Scroll to the bottom and select the Sprite Font icon:</p>
<p><img width="76" height="67" alt="xna_spritefont" id="image53" src="http://spatialhorizons.com/wp-content/uploads/2007/05/xna_spritefont.jpg" /></p>
<p><span id="more-52"></span><br />
This generates a XML configuration file that provides the information that XNA needs to import that font file into the Content Pipeline and thus have the ability to be drawn in the program. For example, to use Courier New font, the first element should be:</p>
<p>&lt;FontName&gt;Courier New&lt;/FontName&gt;</p>
<p>Other elements in the XML file that contain information on font size, spacing, and style can be changed accordingly.</p>
<p><strong>Using the Font</strong></p>
<p>Several lines of code need to be added once the configuration file is setup. First define a SpriteFont object:</p>
<p>
<pre lang="csharp">SpriteFont courierNew;</pre>
</p>
<p>Then in the LoadGraphicsContent method, create a font object using the asset name of the configuration file:</p>
<p>
<pre lang="csharp">courierNew = content.Load("Content\\Font\\ConsoleFont");</pre>
</p>
<p>Finally, use the DrawString method of a SpriteBatch object to draw the font on screen:</p>
<p>
<pre lang="csharp">spriteBatch.DrawString(courierNew,"Insert Text String", new Vector2(5,5), Color.Red);</pre>
</p>
<p>There are additional parameters that allow for the text to be rotated or scaled but most of the time we just need a string, the location, and a color.</p>
<p>Next time we will demonstrate a simple application using font. Our focus will be on creating a console-type application that will eventually be part of a larger mapping application.</p>
]]></content:encoded>
			<wfw:commentRss>http://spatialhorizons.com/2007/05/06/xna-and-gis-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XNA Game Studio Express Refresh</title>
		<link>http://spatialhorizons.com/2007/04/28/xna-game-studio-express-refresh/</link>
		<comments>http://spatialhorizons.com/2007/04/28/xna-game-studio-express-refresh/#comments</comments>
		<pubDate>Sat, 28 Apr 2007 19:22:18 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://spatialhorizons.com/2007/04/28/xna-game-studio-express-refresh/</guid>
		<description><![CDATA[Microsoft has released an update (&#8221;refresh&#8221;) for the XNA Game Studio Express so I encourage everyone to go and download it. This update includes official support for fonts which we will start using very soon here at Spatial Horizons. Before you can install this 83MB update, you must have the C# Express Service Pack 1 [...]]]></description>
			<content:encoded><![CDATA[<p>Microsoft has released an <a target="_blank" href="http://msdn2.microsoft.com/en-us/xna/aa937795.aspx">update</a> (&#8221;refresh&#8221;) for the XNA Game Studio Express so I encourage everyone to go and download it. This update includes official support for fonts which we will start using very soon here at Spatial Horizons. Before you can install this 83MB update, you must have the <a target="_blank" href="http://msdn.microsoft.com/vstudio/express/downloads/default.aspx">C# Express Service Pack 1</a> installed first.</p>
]]></content:encoded>
			<wfw:commentRss>http://spatialhorizons.com/2007/04/28/xna-game-studio-express-refresh/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>World Mapper (3)</title>
		<link>http://spatialhorizons.com/2007/04/16/world-mapper-3/</link>
		<comments>http://spatialhorizons.com/2007/04/16/world-mapper-3/#comments</comments>
		<pubDate>Mon, 16 Apr 2007 22:13:37 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://spatialhorizons.com/2007/04/16/world-mapper-3/</guid>
		<description><![CDATA[This project continues our initial exploration into creating mapping applications using XNA. Last time we setup the basic application and today we will add some new functionality.
Resizing the Image
I first created a larger background image (800 pixels x 400) to be used for the rest of this project.  Two new variables were added:

int mapWidth [...]]]></description>
			<content:encoded><![CDATA[<p>This project continues our initial exploration into creating mapping applications using XNA. <a href="http://spatialhorizons.com/2007/04/02/world-mapper-2/">Last time</a> we setup the basic application and today we will add some new functionality.</p>
<p><strong>Resizing the Image</strong></p>
<p>I first created a larger background image (800 pixels x 400) to be used for the rest of this project.  Two new variables were added:</p>
<p>
<pre lang="csharp">int mapWidth = 800;
int mapHeight = 400;</pre>
</p>
<p>&#8230;and used in the Initialize Function:</p>
<p>
<pre lang="csharp">graphics.PreferredBackBufferWidth = mapWidth;
graphics.PreferredBackBufferHeight = mapHeight;</pre>
</p>
<p><span id="more-37"></span><br />
<span style="font-weight: bold"><span style="font-weight: bold">Mouse Object Creation<br />
</span></span></p>
<p>As discussed in our <a href="http://spatialhorizons.com/2007/04/14/modeling-a-gis-1/">previous post</a>, we will now start adding objects in our source code. The simple example shown was that of a Mouse object used to store the mouse&#8217;s cursor location and button states. So a new file (shMouse.cs) has been added to the project and used in the code to manage the mouse input.</p>
<p><span style="font-weight: bold">Full Screen</span></p>
<p>Another benefit to programming with XNA is how easy it is to switch into full screen mode. I added some code in Update function to switch the program into full screen mode when the F key is pressed:</p>
<p>
<pre lang="csharp">else if (keyState.IsKeyDown(Keys.F))
{
  graphics.ToggleFullScreen();
}</pre>
</p>
<p>Pressing F again will switch back to windowed mode. Yes, it is that simple.</p>
<p><strong>Summary</strong></p>
<p>Today&#8217;s changes were relatively minimal but did introduce several new concepts that are important to our future objectives. Below is a link to download the updated source code.  The download also includes the Mouse object model created using Dia.</p>
<p><a href="http://spatialhorizons.com/downloads/WorldMapper_v0.2.zip"><img border="0" alt="Download Source Code" src="http://spatialhorizons.com/downloads/code_download.jpg" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://spatialhorizons.com/2007/04/16/world-mapper-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>World Mapper (2)</title>
		<link>http://spatialhorizons.com/2007/04/02/world-mapper-2/</link>
		<comments>http://spatialhorizons.com/2007/04/02/world-mapper-2/#comments</comments>
		<pubDate>Mon, 02 Apr 2007 22:42:14 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://spatialhorizons.com/2007/04/02/world-mapper-2/</guid>
		<description><![CDATA[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&#8217;ve added the option to download the source code at the bottom of this page. [...]]]></description>
			<content:encoded><![CDATA[<p>We will now create a simple XNA program that uses some of the functionality discussed in our last 2 posts (XNA and GIS [<a href="http://spatialhorizons.com/2007/03/17/xna-and-gis-1/">1</a>][<a href="http://spatialhorizons.com/2007/03/25/xna-and-gis-2/">2</a>]). It will also introduce how to include input from the keyboard and mouse.</p>
<p>For the first time, we&#8217;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.</p>
<p><span id="more-36"></span></p>
<p>Our objective in this project is to rebuild our previous <a href="http://spatialhorizons.com/2007/02/15/world-mapper-1/">World Mapper project</a> using XNA with some differences. Since official support for text in XNA won&#8217;t be available until <a target="_blank" href="http://blogs.msdn.com/xna/archive/2007/03/08/announcing-the-xna-game-studio-express-update.aspx">later this month</a>, the user won&#8217;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&#8217;s mode switches from adding points to deleting points. Clicking on top of an existing point will then remove it from the map.</p>
<p>So let&#8217;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).</p>
<p>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.</p>
<p>The class variables I added for the images look like this:</p>
<p>
<pre lang="csharp">Texture2D t2dWorldMap;
Texture2D td2Point;
Texture2D td2Delete;</pre>
</p>
<p>To keep track of the user-added points, I created a List collection of Point variables:</p>
<p>
<pre lang="csharp">List<Point> mapPoints;</pre>
</p>
<p>In the Initialize function, I resized the window size to match the dimensions of the world map image:</p>
<p>
<pre lang="csharp">graphics.PreferredBackBufferWidth = 400;
graphics.PreferredBackBufferHeight = 200;
graphics.ApplyChanges();</pre>
</p>
<p>In the LoadGraphicsContent function, I load the textures into the program using their Content Pipeline names:</p>
<p>
<pre lang="csharp">t2dWorldMap = content.Load<Texture2D>;(@"Content\Textures\WorldMap");
td2Point = content.Load<Texture2D>(@"Content\Textures\point");
td2Delete = content.Load<Texture2D>(@"Content\Textures\delete");</pre>
</p>
<p>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.</p>
<p>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:</p>
<p>
<pre lang="csharp">foreach (Point p in mapPoints)
{
  spriteBatch.Draw(td2Point, new Rectangle(p.X - 2, p.Y - 2, 4, 4), Color.White);
}</pre>
</p>
<p>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.</p>
<p>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:</p>
<p>
<pre lang="csharp">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) &#038;&#038;
        (Math.Abs(p.Y - y) <= bufferTolerance))
      matchPoint = p;
  }
  return matchPoint;
}</pre>
</p>
<p>Those are the main points involved in creating this project. Click on the link below to download the source code.</p>
<p><a href="http://spatialhorizons.com/downloads/WorldMapper_v0.1.zip"><img border="0" alt="Download Source Code" src="http://spatialhorizons.com/downloads/code_download.jpg" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://spatialhorizons.com/2007/04/02/world-mapper-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
