Modular Game Engine Tutorial - 1.0 Setting Up The Projects
To start, we'll need four projects, a Game
project, two Game
Libraries and a Content Extension Library. The first library project we need is to hold a class I'm calling XNAGameEngine
. It will inherit from the DrawableGameComponent
class and hold a SpriteBatch
, GraphicsDevice
and some helper functions. I'm putting it in a separate project, which I'm calling XNAGameEngineData
, because it's such a useful class to have for any XNA project, I like to have it around.
The other library project, I'm calling KrakenEngine
, has all the classes for our modular framework. The Game
project needs a reference to both libraries and the KrakenEngine
library needs reference to the XNAGameEngineData
library.
The last project is the Content Extension Library which we'll get to later. For now, let's add all the references and get that out of the way. The extension library needs a reference to both libraries and the Content Project needs a reference to the extension library.
Let's start with the XNAGameEngineData
library. Add a class called XNAGameEngine
and replace the code inside with this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
namespace XNAGameEngineData
{
public class XNAGameEngine : DrawableGameComponent
{
GraphicsDeviceManager _graphics;
SpriteBatch _spriteBatch;
bool _isInitialized = false;
public GraphicsDeviceManager Graphics
{
get { return _graphics; }
}
public SpriteBatch SpriteBatch
{
get { return _spriteBatch; }
}
public bool IsInitialized
{
get { return _isInitialized; }
}
public XNAGameEngine(Game game)
: base(game)
{
_graphics = new GraphicsDeviceManager(game);
game.Content.RootDirectory = "Content";
}
public override void Initialize()
{
base.Initialize();
_isInitialized = true;
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(_graphics.GraphicsDevice);
base.LoadContent();
}
public override void Draw(GameTime gameTime)
{
_graphics.GraphicsDevice.Clear(Color.DarkBlue);
base.Draw(gameTime);
}
}
}
That's all we need in this class for now. We're going to add two more items to this project. An interface IGameObject
, and a generic class, GameCollection<T>
, where T
is an IGameObject
.
IGameObject
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
namespace XNAGameEngineData
{
public interface IGameObject
{
void LoadContent(ContentManager content);
void Update(GameTime gameTime);
void Draw(SpriteBatch spriteBatch);
}
}
GameCollection
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;
namespace XNAGameEngineData
{
public class GameCollection<O> : IEnumerable<O> where O : IGameObject
{
Dictionary<string, O> _dictionary = new Dictionary<string, O>();
List<O> _list = new List<O>();
public O this[int index]
{
get { return _list[index]; }
}
public O this[string key]
{
get { return _dictionary[key]; }
}
public int Count
{
get { return _list.Count; }
}
public void Add(string key, O item)
{
_dictionary.Add(key, item);
_list.Add(item);
}
public void Insert(string key, O item, int index)
{
_dictionary.Add(key, item);
_list.Insert(index, item);
}
public int IndexOf(O item)
{
return _list.IndexOf(item);
}
public void Remove(O item)
{
_dictionary.Remove(GetKeyForItem(item));
_list.Remove(item);
}
public void Remove(string key)
{
_list.Remove(_dictionary[key]);
_dictionary.Remove(key);
}
public bool Contains(O item)
{
return _list.Contains(item);
}
public bool Contains(string key)
{
return _dictionary.ContainsKey(key);
}
public IEnumerator<O> GetEnumerator()
{
return _list.GetEnumerator();
}
public T GetItem<T>() where T : O
{
foreach (O item in _list)
{
if (item is T)
{
return (T)item;
}
}
return default(T);
}
public T GetItem<T>(string key) where T : O
{
if (_dictionary.ContainsKey(key) &&
_dictionary[key] is T)
{
return (T)_dictionary[key];
}
else
{
return default(T);
}
}
public List<T> GetItems<T>() where T : O
{
List<T> result = new List<T>();
foreach (O item in _list)
{
if (item is T)
{
result.Add((T)item);
}
}
return result;
}
public List<T> GetItems<T>(string searchPattern) where T : O
{
List<T> result = new List<T>();
foreach (O item in _list)
{
if (item is T &&
Regex.IsMatch(GetKeyForItem(item), searchPattern))
{
result.Add((T)item);
}
}
return result;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
string GetKeyForItem(O item)
{
foreach (string key in _dictionary.Keys)
{
if (_dictionary[key].Equals(item))
{
return key;
}
}
throw new ArgumentException();
}
}
}
We have a dictionary
and a list
so we can retrieve items either by name or index. Notice the methods to search through the collection using regular expressions, or search by type.
That's it for this project. In the next tutorial, we'll start on the framework itself.
Post Comment
cG40TE Thank you, I have just been looking for info about this topic for ages and yours is the best I've discovered so far. But, what about the bottom line? Are you sure about the source?
UPbD9O Im grateful for the post. Want more.