Easy Update Code

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
abraker95
Posts: 10
Joined: Thu Sep 05, 2013 3:34 pm

Easy Update Code

Post by abraker95 »

Hi! Just wanted to share a snippet I made for easy event handling. I thought the necessity of having to use a single event class per device a little too messy, and unorganized in cases where the mouse events end up in the same class as the keyboard events or maybe even worse. This allows to define an "action" per class you make. However, it involves having some variables static. While it's not a problem, it bothers me a little bit.

Example Usage:

Code: Select all

 
/*****************main.cpp*********************/
#include "include/IEventUpdater.h"
using namespace blah blah blah  // <-- Error? You actually copied and compiled this?
 
int main()
{
 IrrlichtDevice *device = createDevice(EDT_SOFTWARE, dimension2d<u32>(640, 480), 16, false, false, false, &Updater); // The Updater is used like any other event class
 
 Keyboard *keybrd = new Keyboard();
 Updater.addAction(keybrd->update);
 }
 
/*****************Keyboard.h*********************/
static void update(const SEvent& event); // The update function must be void(const SEvent& event)
static bool KeyIsDown[KEY_KEY_CODES_COUNT]; // Static variable
 
/*****************Keyboard.cpp*********************/
void Keyboard::update(const SEvent& event)
{
 // Remember whether each key is down or up
 if(event.EventType == irr::EET_KEY_INPUT_EVENT)
    KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
}
 
bool Keyboard::KeyIsDown[KEY_KEY_CODES_COUNT] = {0};
 

IEventUpdater.h:

Code: Select all

 
#ifndef IEVENTUPDATER_H
#define IEVENTUPDATER_H
 
#include <irrlicht.h>
#include <vector>
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
  
class IEventUpdater: public IEventReceiver
{
    public:
        IEventUpdater();
        virtual ~IEventUpdater();
        virtual bool OnEvent(const SEvent& _event);
 
        void addAction(Func* _Action);
 
    protected:
    private:
        vector<Func*> Action;
} extern Updater;
 
#endif // IEVENTUPDATER_H
 
IEventUpdater.cpp:

Code: Select all

 
#include "../include/IEventUpdater.h"
 
IEventUpdater::IEventUpdater()
{
 Action.resize(0);
}
 
IEventUpdater::~IEventUpdater()
{
 Action.resize(0);
}
 
// Add the action to the list
void IEventUpdater::addAction(Func* _Action)
{
 Action.push_back(_Action);
}
 
// Do updates
bool IEventUpdater::OnEvent(const SEvent& _event)
{ 
 // Go through each action
 for(int action=0; action<Action.size(); action++)
     Action.at(action)(_event);
 
 return false;
}
 
IEventUpdater Updater; // Global; You should have only 1 updater
 
Last edited by abraker95 on Sun Feb 09, 2014 6:46 am, edited 2 times in total.
abraker95
Posts: 10
Joined: Thu Sep 05, 2013 3:34 pm

Re: Easy Update Code

Post by abraker95 »

Ok, updated the code! I got rid of the static requirement.

Example Usage:

Code: Select all

 
 
/*****************main.cpp*********************/
#include "include/IEventUpdater.h"
using namespace blah blah blah  // <-- Error? You actually copied and compiled this?
 
int main()
{
 IrrlichtDevice *device = createDevice(EDT_SOFTWARE, dimension2d<u32>(640, 480), 16, false, false, false, &Updater); // The Updater is used like any other event class
 
 Keyboard *keybrd = new Keyboard();
 Updater.addAction(keybrd);  // NOTICE that there is no need for the update function. As long as it extends the Action class, it can be put into the updater.
 }
 
/*****************Keyboard.h*********************/
class Keyboard: public Action
{
 void update(const SEvent& event); // The update function must be void(const SEvent& event)
 bool KeyIsDown[KEY_KEY_CODES_COUNT];
}
 
/*****************Keyboard.cpp*********************/
void Keyboard::update(const SEvent& event)
{
 // Remember whether each key is down or up
 if(event.EventType == irr::EET_KEY_INPUT_EVENT)
    KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
} 
 
IEventUpdater.h:

Code: Select all

 
#ifndef IEVENTUPDATER_H
#define IEVENTUPDATER_H
 
#include <irrlicht.h>
#include <vector>
#include "Action.h"
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
 
typedef void(Func)(const SEvent&);
 
class IEventUpdater: public IEventReceiver
{
    public:
        IEventUpdater();
        virtual ~IEventUpdater();
        virtual bool OnEvent(const SEvent& _event);
 
        void addAction(Action* _Action);
 
    protected:
    private:
        vector<Action*> actions;
} extern Updater;
 
#endif // IEVENTUPDATER_H
 
IEventUpdater.cpp:

Code: Select all

 
#include "../include/IEventUpdater.h"
 
IEventUpdater::IEventUpdater(){ actions.resize(0); }
IEventUpdater::~IEventUpdater(){ actions.resize(0); }
 
void IEventUpdater::addAction(Action* _action){ actions.push_back(_action); }
 
bool IEventUpdater::OnEvent(const SEvent& _event)
{
 for(int action=0; action<actions.size(); action++)
     actions.at(action)->update(_event);
 
 return true;
}
 
IEventUpdater Updater;
 
Action.h:

Code: Select all

 
#ifndef ACTION_H
#define ACTION_H
 
#include <irrlicht.h>
using namespace irr;
 
class Action
{
    public:
        Action();
        virtual ~Action();
 
        virtual void update(const SEvent& event) = 0;
    protected:
    private:
};
 
#endif // ACTION_H
 
Action.cpp:

Code: Select all

 
#include "../include/Action.h"
 
Action::Action(){}
Action::~Action(){}
 
abraker95
Posts: 10
Joined: Thu Sep 05, 2013 3:34 pm

Re: Easy Update Code

Post by abraker95 »

So I was using my code when I ran into a problem using this synchronously. This code works best asynchronous (meaning it executes whenever it executes, which is when any event occurs), but what if I wanted to do synchronous actions? You can't use this to, say, draw stuff on the screen because the action would execute before or after the beginScene function. While it is possible to get the index of the action you want to execute, that involves, yet again, some more messy code. So I implemented a tag system to the Action class as well as the ability to search and/or execute any desired action so long it has that tag.

EDIT: The interaction as a means to call an object in the code, avoiding the including of it on the parameter list. However, you can't use it to assign classes a variable in the constructor. For example, you can't have a variable that is assigned in the constructor; the class needs to add the interaction to another class first in order to have a pointer to the instance of that class to assign to the variable in the first place. I would stick to passing it through the parameter list if you want to assign the pointer in the constructor.


Example Usage:

Code: Select all

 
/*****************main.cpp*********************/
#include "include/IEventUpdater.h"
using namespace blah blah blah  // <-- Error? You actually copied and compiled this?
 
int main()
{
 IrrlichtDevice *device = createDevice(EDT_SOFTWARE, dimension2d<u32>(640, 480), 16, false, false, false, &Updater); // The Updater is used like any other event class
 IVideoDriver* driver = device->getVideoDriver();
 
 Sprite *sprite = new Sprite(driver, dimension2d<u32>(32, 32), position2d<int>(200, 200));
 Updater.addAction(sprite, "sprite");  // NOTICE that there is no need for the update function. As long as it extends the Action class, it can be put into the updater. Also it has a tag: "Sprite".
 
 while(device->run())
   {
    driver->beginScene(true, true, SColor(0,0,0,0));
         event.runAction("sprite");  // Search by tag and execute
    driver->endScene();
   }
 
  delete sprite;
}
 
/*****************Sprite.h*********************/
class Sprite: public Action
{
 Sprite(IVideoDriver* _driver, dimension2d<u32> _dim, position2d<int> _pos);
 
 void update(const SEvent& event); // The update function must be void(const SEvent& event);
 ITexture* sprite;
 dimension2d<u32> dim;
 position2d<int> pos;
 IVideoDriver* driver;
}
 
/*****************Sprite.cpp*********************/
// Let's skip the init code; It should be obvious what it contains
 
void Sprite::update(const SEvent& event)
{
 driver->draw2DImage(sprite, pos);
} 
 

IEventUpdater.h:

Code: Select all

 
#ifndef IEVENTUPDATER_H
#define IEVENTUPDATER_H
 
#include <irrlicht.h>
#include <vector>
#include <string>
#include "Action.h"
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace std;
 
class IEventUpdater: public IEventReceiver
{
    public:
        IEventUpdater();
        virtual ~IEventUpdater();
        virtual bool OnEvent(const SEvent& _event);
 
        void addAction(Action* _Action, std::string _name = "n/a");
        Action* findAction(std::string _name);
        void runAction(std::string _name);
 
    protected:
    private:
        vector<Action*> actions;
} extern Updater;
 
#endif // IEVENTUPDATER_H
 

IEventUpdater.cpp:

Code: Select all

 
#include "../include/IEventUpdater.h"
 
IEventUpdater::IEventUpdater()
{
 actions.resize(0);
}
 
IEventUpdater::~IEventUpdater()
{
 actions.resize(0);
}
 
void IEventUpdater::addAction(Action* _action, std::string _name)
{
 _action->setName(_name);
 actions.push_back(_action);
}
 
bool IEventUpdater::OnEvent(const SEvent& _event)
{
 for(int action=0; action<actions.size(); action++)
     actions.at(action)->update(_event);
 
 return true;
}
 
Action* IEventUpdater::findAction(std::string _name)
{
 for(int action=0; action<actions.size(); action++)
     if(actions.at(action)->getName() == _name) return actions.at(action);
}
 
void IEventUpdater::runAction(std::string _name)
{
 findAction(_name)->update();
}
 
IEventUpdater Updater;
 

Action.h:

Code: Select all

 
#ifndef ACTION_H
#define ACTION_H
 
#include <irrlicht.h>
#include <string>
 
using namespace irr;
using namespace std;
 
class Action
{
    public:
        Action();
        virtual ~Action();
 
        virtual void update(const SEvent& event) = 0;
        void update();
 
        void setName(string _name);
        string getName() const;
 
    protected:
    private:
        string name;
};
 
#endif // ACTION_H
 

Action.cpp:

Code: Select all

 
#include "../include/Action.h"
 
Action::Action(){}
Action::~Action(){}
 
void Action::update()
{
 update(SEvent());  // Just create a(n) SEvent to bypass the required argument... idk how safe this is, but it works
}
 
void Action::setName(string _name)
{
 name = _name;
}
 
string Action::getName() const
{
 return name;
}
 
Post Reply