Monday, November 15, 2010

C++ Project - Final Fantasy Battle System pt.4 - Input Handling

So, I've been continuing to slowly work on this project in my spare time. I've completed a simple scene management system as well as re-factored some of the base Game class into an Application class which contains most of the high-level engine components such as rendering and window setup.

Also, I've put together an input system which I think should be somewhat easy to deal with as I continue to add more functionality.

I decided to use a combination of the Observer pattern and the Command pattern so that I could have one central object that actually deals with the raw inputs and then passes friendly commands to interested parties.

Here's how it should all work:

1. InputController listens each frame for any new keys that we are particularly interested in.

2. InputController then notifies any interested controllers observering on the keys that were pressed.
3. The interested observers then decide which keys it is interested in and then creates ICommand objects on each one.

It should be that any object that wishes to implement a particular control scheme need only add the appropriate controller as a member variable.

Now, let's see some code.

The interface for InputController:

 class InputController : public IGameComponent
{
private:
CL_InputDevice m_keyboard;
vector m_keysThisFrame;
vector; m_commandObservers;
virtual void Initialize();
void notifyObservers();
public:
~InputController();
void Initialize(CL_InputDevice);
virtual void Update(unsigned int);
virtual void Draw(CL_GraphicContext& graphicsContext);
void registerObserver(ICommandController*);
void removeObserver(const ICommandController&);
};

Here are the interfaces for a high-level command system (ie. exiting the game, etc.)

 class Game;
class SystemCommandController : public ICommandController
{
public:
SystemCommandController(Game&);
~SystemCommandController();
void Notify(vector);
private:
Game& m_gameObject;
};
 class Game;
class SystemCommand : public ICommand
{
public:
enum SystemCommands {EXITGAME};
SystemCommand(Game&, SystemCommands);
~SystemCommand();
void Execute();
private:
Game& m_gameObject;
SystemCommands m_commandToExecute;
};
And the actual implementation of the SystemCommand class so you can see how the commands are handled:

 #include "SystemCommand.h"
SystemCommand::SystemCommand(Game& gameObj, SystemCommand::SystemCommands command) : m_gameObject(gameObj)
{
m_commandToExecute = command;
}
SystemCommand::~SystemCommand()
{
}
void SystemCommand::Execute()
{
switch (m_commandToExecute)
{
case EXITGAME:
m_gameObject.ExitGame();
break;
}
}

So, there you have it! A nice and clean input handling system. There will be slightly more work involved setting up the classes, but it is very easy to reuse across multiple objects.

This project seems to be moving slowly, but it is nice to really engineer something rather than just hacking and reacting! I've got the GUI system going, so hopefully next time there might be some screenshots of my programmer art screens!

No comments: