Cpp:Building A Simple Tile Engine:Part 1

From GPWiki

Files:GUITutorial_warn.gif The Game Programming Wiki has moved! Files:GUITutorial_warn.gif

The wiki is now hosted by GameDev.NET at wiki.gamedev.net. All gpwiki.org content has been moved to the new server.

However, the GPWiki forums are still active! Come say hello.

Part 1: Defining the interfaces

Sequence diagram
Sequence diagram

In this first part of the tutorial we are going to define the general interfaces that will be used by the classes we create later on.

We need to define a base interface that exposes functions to the engine, and everything we stuff into the engine needs to implement this. The following diagram shows the processes that happen in our game engine from start till end.

  • CEngine::Init() [Loading]
  • CEngine::Start() [Main loop]
    • CEngine::HandleInput() [Handle user control input]
    • CEngine::DoThink() [Updating]
    • CEngine::DoRender() [Rendering]
  • [Repeat loop until quit]

The engine makes heavy use of virtual functions. The way it works, is that you make an engine class that inherit the CEngine class and overload some or all of its virtual functions. Thus, when the engine calls its virtual functions (e.g. Render()), the overloaded function is called instead.

We are going to make our custom implementation of the engine called CTileEngine, that will inherit the following virtual functions from CEngine:

  • void AdditionalInit();
  • void Think();
  • void Render();
  • void KeyUp();
  • void KeyDown();
  • void End();
  • void MouseMoved();
  • void MouseButtonUp();
  • void MouseButtonDown();


In our game engine we need two types of classes; tiles to represent the map or board, and units to represent figures. We need to be able to update (think) and draw (render) both of these classes. Furthermore we need to be able to load and save the classes from a file. We'll start by making a base class called CEntity that both classes with inherit some shared functionality from.

In any game there will be a number of tiles and units, and it would be convenient to have a class to wrap those classes. We'll create a "manager" class for each type; CTileManager and CUnitManger. Both classes will also need the same functions as the classes they contain - that is VLoad(), VGetSaveData(), VThink() and VRender().

To wrap up the classes even more we're going to create yet another class. This one will be called CGame and will contain CTileManager and CUnitManager, and will also use the same interface.

This is what our interface looks like:

File: Interfaces.h

#include "SDL.h"
#include "../Libs/TinyXML/tinyxml.h"
 
#include <string>
using std::string;
 
class IBaseEntity
{
public:
	virtual void		VThink	( const int& iElapsedTime )		= 0;
	virtual void		VRender( SDL_Surface* pDestSurface	)	= 0;
 
	virtual bool		VLoad	( TiXmlElement* pXMLData )		= 0;
	virtual TiXmlElement*	VGetSaveData	()				= 0;
};

Don't be scared about TiXmlElement class - we'll get to that in due time! Other than that, it's not that bad, is it? We include the SDL, TinyXML and C++ string header and just define the interface like we've discussed.

Complete engine structure

We've now added a lot of functionality that extends the functionality of the original engine. We're still yet to define and implement the classes we've discussed in this article, but we've already defined the interface that we will use for communication. So, using that information, here is a complete diagram of what will happen inside the engine we're building:

  • CEngine::Init() [Loading]
    • CTileEngine::AdditionalInit()
      • CGame::VLoad()
        • CTileManager::VLoad()
          • CTile::VLoad()
            • CEntity::VLoad()
        • CUnitManager::VLoad()
          • CUnit::VLoad()
            • CEntity::VLoad()
  • CEngine::Start() [Main loop]
    • CEngine::HandleInput() [Handle user control input]
      • CTileEngine::KeyDown()
      • CTileEngine::KeyUp()
      • CTileEngine::WindowActive()
      • CTileEngine::WindowInactive()
      • CTileEngine::MouseMoved()
      • CTileEngine::MouseButtonDown()
      • CTileEngine::MouseButtonUp()
    • CEngine::DoThink() [Updating]
      • CTileEngine::Think()
        • CGame::VThink()
          • CTileManager::VThink()
            • CTile::VThink()
              • CEntity::VThink()
          • CUnitManager::VThink()
            • CUnit::VThink()
              • CEntity::VThink()
    • CEngine::DoRender() [Rendering]
      • CTileEngine::VRender()
        • CGame::VRender()
          • CTileManager::VRender()
            • CTile::VRender()
              • CEntity::VRender()
          • CUnitManager::VRender()
            • CUnit::VRender()
              • CEntity::VRender()
  • [Repeat loop until quit]
  • CTileEngine::End() [Unloading]

Extended sequence diagram


Does it look intimidating? It is actually pretty easy, and we'll take it one step at a time. You've just taken the first one. To take the next step, jump to part 2 where we'll be creating our base entity class.

Proceed to Part 2: Creating the base entity


Table of Content - Part 1 - Part 2 - Part 3 - Part 4 - Part 5 - Part 6 - Part 7 - Part 8 - Part X