Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

The Game Development Framework

4.70/5 (11 votes)
21 May 2010GPL34 min read 49.6K   2.3K  
Simple Game Dev Fx in C# (Maps, Graphics, Path-finding AI)

VS 2008 Solution, all code is thoroughly documented with XML comments for intellisense. All variables, methods, and types are described in detail.

Introduction

The Game Development Framework (GameFX) is simply a set of libraries to be used as the foundation for any simple 2D tile-based game. It can be used to build games such as PacMan, Snake, Tetris, and even Chess.

Click here if you wish to review a complete tutorial where we will go through the step-by-step development of this project. We will start with the idea, after that we will go through the process of designing the program, thinking through all of the important details that all programmers must think about. Finally, we will hammer out all of the necessary code to make it work.

Background

Building and reusing a framework greatly simplifies the task of actually developing the game. You don't have to think about all of the tedium of mapping, graphics, and AI because it has been separated and encapsulated.

It is like building a box with buttons, knobs, and switches. We are going build a box that has all of the mechanisms inside that deal with the logic of handling maps, drawing map graphics, and finding paths. On the outside of that box, we will have the hypothetical buttons, switches, and knobs to manipulate the maps, pathfinder, and graphics engine. Doing it that way makes it much simpler and easier to use. If we didn't do it, we would be tinkering around inside of it for every game that we build.

Using the Code

GameFX will handle tile-based maps, graphics, and pathfinding, so we can divide GameFX into those three main categories.

Let's start with tile-mapping. The highest-level functioning unit of tile-mapping is of course the TileMap. The basic unit of a TileMap is a Tile which uses Coordinates.

Good, we have broken down the first category (tile-mapping) into three functional components that can be put together to perform the functions of tile-mapping.

  • Tile (the basic unit of a tile map)
  • TileMap (a 2D map of Tiles that can be operated on)
  • Coordinate (a simple data type that represents X,Y values on a TileMap)

Here we have the Graphics Engine.

  • GraphicsEngine (the mechanism that graphically renders a TileMap)

We can break down the pathfinding category into these three components.

  • Node (an interesting mechanism used in finding a path from one coordinate to another)
  • NodeHeap (a sorted storage mechanism that is key to the A* pathfinding algorithm)
  • SimplePathFinder (the mechanism that finds the path from one coordinate to another on a TileMap)

Here is the simplest working example of GameFX. The code simply creates a 10x10 map of Tiles of type Byte. 0 represents the floor, 1 represents the path, and 2 represents a wall. The Graphics Engine will draw the map to Form1, all changes to the map will be rendered in real-time. There is a wall in the middle of the map. The Pathfinder will find the path from the upper left corner to the bottom right corner.

C#
using HenizeSoftware.GameFX.PathFinding;
using HenizeSoftware.GameFX.TileMap;

namespace WindowsFormsApplication1
{
  public partial class Form1 : Form
  {
    TileMap<byte> myMap;
    GraphicsEngine<byte> gfx;
    SimplePathFinder<byte> path;
  
    public Form1()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      myMap = new TileMap<byte>(10, 10);
      gfx = new GraphicsEngine<byte>(myMap, this.CreateGraphics(), 
		10, 10, RenderMode.OnChanged);
      path = new SimplePathFinder<byte>(myMap);

      path.ResistanceDictionary.Add(2, 255);
      
      path.Start = new Coordinate(0, 0);
      path.End = new Coordinate(9, 9);

      gfx.ColorDictionary.Add(0, Color.Black);
      gfx.ColorDictionary.Add(1, Color.Pink);
      gfx.ColorDictionary.Add(2, Color.White);

      gfx.DrawAllTiles();

      for (ushort i = 8; i > 0; i--) //draw wall down the middle
        myMap[4, i].Value = 2;
    }

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
      if(gfx != null)
        gfx.DrawAllTiles();
    }

    private void button2_Click(object sender, EventArgs e)
    {
      foreach (Coordinate c in path.GetFullPath())
        myMap[c].Value = 1;
    }
  }
}

Points of Interest

There may be some minor bugs in the code that I have not yet discovered. However I have developed a test program that allows you to create maps of any size, and drop as many snakes as your computer can handle onto the map. The snakes run around on the map in competition for food. You can draw on the map while it's running. It also allows you to use bitmapped graphics if you choose to draw them. The speed can also be adjusted.

First you must click New Map before you can do anything. You also cannot remove the last snake.

The code is pretty self explanatory, however I will go over the core of the sample program, the part that makes it all tick.

C#
//Each snake has its own pathfinder. For each snake on the map, 
//find the path to the food and increment the snake toward it.
private void timer_Tick(object sender, EventArgs e)
{
//Go through all of the snakes that are currently on the map
  for (int i = 0; i < snakeList.Count; i++)
  {
    //If the snake being processed has eaten the food then find a 
    //new place to drop food, and then tell all the other snakes
    //the new location of the food.
    if (snakeList[i].HeadCoordinate == pathFinderList[i].End)
    {
      //Drop new food on clear area of map
      while (true)
      {
        food = new Coordinate((ushort)rnd.Next(0, map.Width - 1), 
		(ushort)rnd.Next(0, map.Height - 1));
        if (map[food].Value == SLThTile.Floor) break;
      }
      
      //Tell the other snakes the new location of the food.
      foreach(SimplePathFinder<SLThTile> p in pathFinderList)
        p.End = food;
      
      map[food].Value = SLThTile.Food;
      
      if (btnAutoGrow.Checked == true)
        snakeList[i].Grow(1);
   }
   
    Coordinate next = new Coordinate(); //default 0,0 incase Snake is trapped.
    
    //Try to find the path to the food.
    try
    {
      next = pathFinderList[i].GetNextMove();
    }
    catch (PathNotFoundException)
    {
      snakeList[i].Reverse(); //if no path found then make the snake reverse.
    }
    
    //Figure out the general direction the snake needs to go.
    if (next.X == snakeList[i].HeadCoordinate.X && 
		next.Y < snakeList[i].HeadCoordinate.Y)
      snakeList[i].Direction = SnakeDirection.Up;
    else if (next.X == snakeList[i].HeadCoordinate.X && 
		next.Y > snakeList[i].HeadCoordinate.Y)
      snakeList[i].Direction = SnakeDirection.Down;
    else if (next.X > snakeList[i].HeadCoordinate.X && 
		next.Y == snakeList[i].HeadCoordinate.Y)
      snakeList[i].Direction = SnakeDirection.Right;
    else if (next.X < snakeList[i].HeadCoordinate.X && 
		next.Y == snakeList[i].HeadCoordinate.Y)
      snakeList[i].Direction = SnakeDirection.Left;
      
    snakeList[i].IncrementForward();
    
    pathFinderList[i].Start = snakeList[i].HeadCoordinate;
  }

The capabilities of GameFX far exceed the example shown here. Bitmapped graphics, and many configurations are available by simply initiating and configuring properties. Don't be afraid to check it out, it might be useful for one of your projects.

If you would like a more detailed article, click here.

Here is a class diagram for GameFX.

ClassDiagram1.jpg - Click to enlarge image

History

  • Thursday, May 20, 2010: First public release

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)