Reputation: 115
I'm not very good at C++ (but I'm familiar with OOP/Java), but I have to create a game for my C++ class. I want to setup a kind of game engine like that used for Flash games written in ActionScript.
I wrote this two classes, where Actor
is meant as a base class (probably will be abstract) and Player
should actually implement it.
The problem is that I want to avoid duplicate code in the functions addEventListener
and handle
and re-declaring _handlerMap
, since I want to achieve data hiding and such things.
The problem, I guess, is that _eventMap
should contain handler
values that can change class Actor::*handler
and Player::*handler
. Is it possible?
class Actor {
protected:
typedef void(Actor::*handler)(Event);
map<int, handler> _handlerMap;
public:
virtual void addEventListener(int ID, handler h) {
_handlerMap.insert(std::make_pair(ID, h));
};
virtual void handle(int ID) {
handler h = _handlerMap[ID];
Event e;
if (h)
(this->*h)(e);
}
virtual void onUpdate(Event e) {
cout << "Actor::onUpdate()" << endl;
};
};
class Player : public Actor {
typedef void(Player::*handler)(Event);
map<int, handler> _handlerMap;
public:
void addEventListener(int ID, handler h) {
_handlerMap.insert(std::make_pair(ID, h));
};
void handle(int ID) {
handler h = _handlerMap[ID];
Event e;
if (h)
(this->*h)(e);
}
void onKeydown(Event e) {
cout << "Player::onKeyDown()" << endl;
};
};
I wish it was possible to declare Player as:
class Player : public Actor {
typedef void(Player::*handler)(Event);
public:
void onWhateverEvent(Event e);
}
I hope you understand.
Upvotes: 5
Views: 664
Reputation: 115
What do you think of this? (Dispatcher is the same as DispatcherImpl above)
template <class T>
class Entity {
T *_instance;
Dispatcher<T> *_dispatcher;
public:
Entity() {
_instance = new T();
_dispatcher = new Dispatcher<T>(_instance);
}
};
class Actor {
//attirbutes and methods
};
class Player : public Actor {
//attirbutes and methods
};
To use it just:
Entity<Actor> *actor = new Entity<Actor>();
Entity<Player> *player = new Entity<Player>();
actor->getDispatcher()->addEventListener(0, &Actor::foo);
player->getDispatcher()->addEventListener(1, &Player::bar);
player->getDispatcher()->addEventListener(0, &Actor::foo); //inheritance
Upvotes: 0
Reputation: 120079
You need something like this (not tested):
class Dispatcher {
public:
virtual void dispatchEvent(Event*) = 0;
};
template <class C>
class DispatcherImpl : public Dispatcher
{
typedef void(C::*handler)(Event* e);
std::map<int, handler> _handlerMap;
C* _owner;
public:
DispatcherImpl (C* c) : _owner(c) {}
addEventListener(int ID, handler h) {
_handlerMap.insert(std::make_pair(ID, h));
}
void dispatchEvent(Event*)
{
handler h = handlerMap[e->id];
if (h) (_owner->*h)(e);
}
}
Now let each type T
of actor own a DispatcherImpl<T>
, and you are all set. You may also have e.g. Player
inherit from DispatcherImpl<Player>
.
Upvotes: 2