Tuesday, November 30, 2010

DotNetFish Part 1 - Using Gmap.net to create the map image.

Now its time to get down to business and do some actual work. Below is the technology stack I am planning to use for this project.

I have decided to use Gmap.Net to help me build the map. If you havent heard of this great project, you should go check them out. GMap.Net This project makes it very easy to display a map from google, or any number of mapping servers. Getting setup was dead easy. For this tool, I just went with a standard Winform project, This will only be used internally, and no reason to spend time learning WPF right now when I don't need it.

Now then, lets look at what is needed to get Gmap.net Running

  1. Grab the source code of the latest stable branch from the Gmap.Net repository.
  2. Load the source code into visual studio and build the project
  3. You can skip the first two steps, and just grab the binaries, but those don't come with examples, which you'll probably want.
  4. Add the Gmap.Net.Core.Dll and the Gmap.Net.WindowsForms.dll to your references. (Make sure that if you copy the refrences to your project directory, that the System.Data.Sqlite.dll is in the same directory as the two Gmap Dll's
  5. Add the Gmap.WindowsForms.dll to your toolbox, so you can have access to the Gmap map control
Once you have done all of this, you should be able to add a Map control to your form. In the Constructor for your form, you will want to add this code.


// config map 
MainMap.Position = new PointLatLng(35.2276723549358, -97.22351074);
MainMap.MapType = MapType.GoogleMap;
MainMap.MinZoom = 1;
MainMap.MaxZoom = 17;
MainMap.Zoom = 10; 

That should get a basic map up and running on your form. Now for my application I need to do the following

  1. Allow the user to select a lake with a selection tool
  2. After the user has selected a lake, build an image from the tileset.
  3. Do some processing of the image. (Turn the image black and White)
We really don't need to know how the map stuff works, except that the map is divided up into tiles. The way the app will work, is when the user selects a lake, the start and end points longitude and latitude is saved. Gmap already provides a nice selection tool by holding the shift key. This allows us to zoom in on the map using shift. I don't need the zoom ability, but the selection box is perfect. So I modified the Gmap code to not zoom in when using the selection tool. Easy as pie.


Here is the code I am using to get the Tile Coordinates

PureProjection prj = null;
int maxZoom;
int zoom = 15;
GMaps.Instance.AdjustProjection(type, ref prj, out maxZoom);
GMaps.Instance.Mode = AccessMode.ServerOnly;
GMaps.Instance.ImageProxy = new WindowsFormsImageProxy();
//This line converts the LatLng to the Proper TileXY given the level of zoom.
//Remember that each level of zoom has a different TileXY coordinate for a given Lat and Lng
prj.FromPixelToTileXY(prj.FromLatLngToPixel(p.Lat, p.Lng, zoom))


Once we know which tiles we need, it will be very simple to get those tiles and stitch them together into the image.

Here is the code that does the stitching.
using (Bitmap bmp = new Bitmap(tilesWide * 256, tilesHigh * 256))
            {
                for (int x = 0; x < tilesWide; x++)
                {
                    for (int y = 0; y < tilesHigh; y++)
                    {
                        using (Graphics gfx = Graphics.FromImage(bmp))
                        {
                            Exception ex;
                            WindowsFormsImage tile = GMaps.Instance.GetImageFrom(type, new GPoint(startTile.X + x, startTile.Y - y), zoom, out ex) as WindowsFormsImage;

                            if (ex != null)
                            {
                                e.Cancel = true;
                                return;
                            }
                            else if (tile != null)
                            {
                                using (tile)
                                {
                                    gfx.DrawImage(tile.Img, x * 256, (tilesHigh - y - 1) * 256);
                                   
                                }
                            }
                        }
                    }
                }

Tuesday, November 2, 2010

Creating a Game Part 1

I've decided to write a series of posts about creating a game using the .net platform. Why do this? because game development has always fascinated me. Also, getting this out in public is motivation to finish something and ship it. That's the most difficult thing to do in software development, is to ship a product. I've read that if you are overweight, a good way to lose weight it to post online your weight each week or so, as you attempt to lose weight. It's great motivation to do so, and I am hoping that this series of posts will motivate me to produce something tangible.

Now that we have the fancy introduction out of the way, its time to get down to business. For this project, I have chosen WPF as my development platform. It seems like a fairly logical choice over something like Silverlight. After doing a lot of research and thinking, I just came to the conclusion that Silverlight is not the perfect fit as a platform for what I wish to do.

So, what kind of game do you plan to write? Well, I plan to create a fishing game. That's right I said fishing game, big whoop, you wanna fight? In all seriousness, its a subject matter that interest me, and I haven't see any games like the kind of game I want to create. The basic premise of the game, is that you control a fishing boat, and you fish on lakes with other people or just by yourself in a single player mode.

So before we can write a single line of code, we probably should do some planning, and decide on what minimum set of features we need in order to release something that works. In the beginning, I am going to focus on the single player part of the game. Below is the things I need to get working first
  • Create an image that represents a lake. This will be used to build a map/level of a lake that is fishable
  • Take an image that represents a lake, and turn it into a map/level, and save it
  • Load a saved map into the app
  • Get the boat moving around the map.
  • Allow the player to cast for fish.

 I plan to work on the tools to build the levels first, the reason being, is that I plan to add a lot of detail to the maps as we go along, and I want to make it a painless as possible to regenerate new levels as needed.

Thursday, October 28, 2010

Unit Testing - Mocking the Session State in MVC Using Moq

I was working on a unit test this week that required me to mock the session state. I had done this before elsewhere using Moq, but I ran into a problem. Moq is unable to stub the sessions getter and setter. So, if you have a method that writes something to the session, you will be unable to return it using Moq. I found some code online from this stackoverflow post


public class MockHttpSession : HttpSessionStateBase
{
    Dictionary<string, object> m_SessionStorage = new Dictionary<string, object>();

    public override object this[string name]
    {
        get { return m_SessionStorage[name]; }
        set { m_SessionStorage[name] = value; }
    }
}


However, I quickly ran into some problems with it. Can you spot what the problem with this code is? It doesn't handle keys that don't exist! With session, you can use a key that doesn't exist and the session will return null. Using the code above with a dictionary, you will get an exception if you try to access a key that doesn't exist.

There is also a second problem with this code! If I did the following

Session.Add("MyKey", "This is my Key");

and "MyKey" already existed, an exception would be thrown, because the key already existed. So we need to work around both of these problems. Here is some code that addresses both issues

public class MockHttpSession : HttpSessionStateBase
{
    Dictionary<string, object> m_SessionStorage = new Dictionary<string, object>();

    public override object this[string name]
    {
        get
        {
            if (m_SessionStorage.ContainsKey(name))
                return m_SessionStorage[name];

            return null;
        }
        set { m_SessionStorage[name] = value; }
    }

    public override void Add(string name, object value)
    {
        if (m_SessionStorage.ContainsKey(name))
            m_SessionStorage[name] = value;
        else
            m_SessionStorage.Add(name,value);
    }
} 

You can use this method anytime you need to set a value in the session in the method you are testing, and you
don't want that value to be mocked. In my case, I needed to ensure that the correct values were being set as part of the unit test.

Introduction

Hello everyone,

My Name is Aaron, and this is my blog. I created this blog so that I could use it as a tool to share my findings as I explore anything and everything regarding programming on the .Net platform. I currently work for a company full time as a software developer using C# and both Asp.Net and MVC along with browser technologies such as JQuery.


Welcome everyone, and I hope you enjoy the ride