Is there a better way to make an EventManager - c++

I made a little code for my EventManager, it works correctly, but the thing is, I created it with a lot of copy-paste, and I think that every time you start doing copy-paste on a few lines, your code is badly designed.
So, having done a lot of copy-paste on that EventManager, I think it's time to find out if there is another way to make it (and there probably is, and probably better).
What I achieved is that when an Event happens (window.pollEvent(event)), it calls the onEvent(sf::Event, sf::RenderWindow*) method of the EventManager class, and for every event I need to listen, I call all instances of the listener.
Here's the class :
public:
void registerKeyPressed(std::shared_ptr<KeyPressedEventListener> listener);
void registerWindowResized(std::shared_ptr<WindowResizedEventListener> listener);
void registerWindowFrameUpdate(std::shared_ptr<WindowFrameUpdateEventListener> listener);
private:
std::vector<std::shared_ptr<KeyPressedEventListener>> m_keyPressedListeners;
std::vector<std::shared_ptr<WindowResizedEventListener>> m_windowResizedListeners;
std::vector<std::shared_ptr<WindowFrameUpdateEventListener>> m_windowFrameUpdateListeners;
So, the thing is, it is a lot of code for only 3 listeners (I currently have 6, but it's not useful to show them as the code is always similar).
My problem is that I want a class to be able to listen to one, two or more events at a time, so all my listeners have a different function that's called when the event happens. For example, these three listeners have the functions onKeypressed(sf::Event);, onWindowResized(sf::Event, sf::RenderWindow* window); and onFrameUpdate(sf::RenderWindow* window);. That's the only way I found to make this code work.
It actually works, but I'd like to make something better, because it's a lot of code for every event :
void EventManager::onEvent(sf::Event event, sf::RenderWindow* window) { // The window argument is used further, but it's not useful to show it here as the code is quite the same
switch (event.type) {
case sf::Event::Resized:
for (unsigned int i = 0; i < m_windowResizedListeners.size(); i++) {
if (m_windowResizedListeners.at(i)->onWindowResized(event)) break; // The events return a bool value : True if the loop has to stop (for an error, for example), false otherwise. I always return false unless an error happen, but it's in case I need to stop it.
}
break;
}
}
void EventManager::registerWindowResized(std::shared_ptr<WindowResizedEventListener> listener) {
m_windowResizedListeners.push_back(listener);
}
And I have to duplicate this code for every event. If there's a bug, you understand it'll be a lot of work to correct it, so I hoped you could help me find a better way to achieve it.
Thank you for your help.

You could use a common class:
class EventHandler{
public:
virtual void handle(sf::RenderWindow &window) = 0;
};
class EventManager {
public:
void registerKeyPressed(std::shared_ptr<EventHandler> listener);
void registerWindowResized(std::shared_ptr<EventHandler> listener);
void registerWindowFrameUpdate(std::shared_ptr<EventHandler> listener);
private:
std::vector<std::shared_ptr<EventHandler>> m_keyPressedListeners;
std::vector<std::shared_ptr<EventHandler>> m_windowResizedListeners;
std::vector<std::shared_ptr<EventHandler>> m_windowFrameUpdateListeners;
}
You can now define a map in the class, the key is the event type and the value is his listener's vector.
std::map<int,std::vector<std::shared_ptr<EventHandler>>*> eventType;
}
//...
EventManager::EventManager(){
eventType[sf::EventType::Resized] = &m_windowResizedListeners;
eventType[sf::EventType::KeyPressed] = &m_keyPressedListeners;
//Keep going...
}
So now, the onEvent function is pretty straightforward:
void EventManager::onEvent(sf::Event event, sf::RenderWindow* window) {
std::vector<std::shared_ptr<EventHandler>>* ptr = eventType[event.type];
for (int i = 0;i < ptr->size();i++)
(*ptr)[i]->handle(window);
}
Let's put an example:
class SettingsSaver : public EventHandler{
public:
void handle(sf::RenderWindow &window) override {
std::cout << "I am saving the state in the hardrive before of exit" << std::endl;
}
}
class MoveHero : public EventHandler{
public:
void handle(sf::RenderWindow &window) override {
std::cout << "I am moving the character" << std::endl;
}
}
// Main
std::shared_ptr<EventHandler> settingsSaver(new SettingsSaver);
std::shared_ptr<EventHandler> moveHero(new MoveHero);
EventManager manager;
manager.registerWindowClosed(settingsSaver);
manager.registerKeyPressed(moveHero);

Related

C++ States: Sequence of Events is not very object orientated

I am struggling to make my code more object orientated.
I have a small program that wishes to accomplish 2 very simple states: An input state, and a result state.
The input state seems simple to resolve as although it is graphical it is "self-updating." The user drops sprites and removes sprites on to the screen to produce an input.
The result state is annoying me because I have produced some very ugly code for it, that is not at all Object Orientated.
This state is required to do things sequentially and I am struggling to find examples of how that is done with Objects. It's basically some animation with the same object: here is some Pseudo-Code.
Static int objectx = 120, object y = 120;
Static int state=0
switch(state)
{
Case 0:
//....move object right
//....once object is far enough right
state = 1;
Case 1:
//....move object down
//....once object is far enough down
state = 2;
...etc
So I am guessing it needs to move to having some sort of state engine, but I am struggling to see how to accomplish sequential events using states. These states are always the same, and so can be hard coded, they will not change based upon the input given.
Any help will be most gratefully recieved.
UPDATE
Maybe we could think about this second state as a cut-scene in a 2d game. We want a character to walk on to the screen, say something and then walk off.
So the way I'm doing it at the moment is managing this part of the programs state via the switch statement. This function is called every time we are in the "result" part of our program, and we are using the switch statement to update the positions of our sprites. Once we have reached the end of the first set of movements we move to the next switch statement and keep doing that until it is completed. It works but I was hoping to use a " gamestate " Class, that could take ownership of the graphics and sound, and move things as appropriate.
Note: making some assumptions here because I don't have any context.
It sounds like each sprite should have its own cycle, rather than the entire game logic moving about the sprites.
Adapting this into an object-orientated design, you can wrap each sprite in some
class:
class NPC : Sprite {
private:
Position CurrentPosition;
int CurrentState;
public:
virtual void Think() = 0;
virtual void Render() = 0;
};
Then you can inherit from this class for specific sprites:
class GobbledyGook : NPC {
private:
const int FinalState = 10;
public:
bool Completed = false;
void Think() override {
if(Completed)
return;
switch(CurrentState) {
// ... repeating logic here ...
}
CurrentState++;
if(CurrentState == FinalState)
Completed = true;
}
void Render() override {
// ... draw the sprite ...
}
}
From the main game logic you can then update every sprite:
// Spawn a GobbledyGook into existence.
my_npcs.insert(new GobbledyGook());
// In frame logic.
bool finished = true;
for( NPC* n : my_npcs )
{
n->Think();
if(!n->Completed)
finished = false;
}
if(finished) {
// Result state.
}
// In render logic.
for( NPC* n : my_npcs )
{
n->Render();
}
You can naturally adopt this logic for entire scenes too:
class Intro : Cutscene {
private:
vector<NPC*> SceneSprites;
public:
void Think() override {
switch(CurrentState) {
...
}
for( NPC* n : SceneSprites ) {
n->Think();
}
}
...
};
As for whether you should be removing or changing the use of states, what do you intend to gain from doing that?
It's hard to recommend a different approach without knowing all the flaws of the current approach.

Qt How to kill a timer started using startTimer() API?

I update a count down timer using timerEvent(QTimerEvent *e) once I am done I call the killTimer(timerID) but the timerEvent() is still being called.
So what's the proper way to kill it?
The Code:
void MainWindow::timerEvent(QTimerEvent *e)
{
Q_UNUSED(e);
static uint16_t u16RemTime = MAX_WARMUP_TIME_IN_SECS;
if((true == isWarmUpStarted) && (u16RemTime > 0))
{
u16RemTime--;
objptrSplashScreen->SetTime(u16RemTime);
}
else
{
//Still running
qWarning("\n\n\n\n\n WARM UP TIMER RUNNING \n\n\n\n\n");
killTimer(warmUpTimerID);
}
}
If it helps. I have two such timers running in two different classes in the same GUI thread. How would I go about killing it?
timerEvent receives all timers' events. In order to differ them QTimerEvent class have int timerId() const method. So your event should look like this:
void MainWindow::timerEvent(QTimerEvent *e)
{
if (e->timerId() != warmUpTimerID)
return;
static uint16_t u16RemTime = MAX_WARMUP_TIME_IN_SECS;
if((true == isWarmUpStarted) && (u16RemTime > 0))
{
u16RemTime--;
objptrSplashScreen->SetTime(u16RemTime);
}
else
{
//Still running
qWarning("\n\n\n\n\n WARM UP TIMER RUNNING \n\n\n\n\n");
killTimer(warmUpTimerID);
}
}
If you use a QTimer or QBasicTimer, you can call the stop() on one of those.
You need to make sure that a particular timerEvent invocation is related to your timer.
QBasicTimer is a nice convenience wrapper around a timer id, you could use it instead of the raw id.
Static variables in members of classes that can be potentially reused are a source of nasty bugs.
isWarmupStarted is redundant, its value is identical to m_warmupRemaining > 0.
You're not saving anything by explicitly using a 16 bit unsigned integer for the remaining time counter. Just use an int.
The style that explicitly mentions types in variable names is, well, if your employer isn't forcing you to use it, don't use it. It's the compiler's job to keep track of such things, not yours, and it's not C and winapi where things sometimes got hairy if you didn't do that.
Thus:
class MainWindow : public QMainWindow {
Q_OBJECT
QSplashScreen * m_splashScreen;
QBasicTimer m_warmupTimer;
int m_warmupRemaining;
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() != m_warmupTimer.timerId()) return;
// No need to call the empty QMainWindow::timerEvent(ev).
// All timerEvent implementations in public Qt classes are empty,
// to make your life easier.
if (m_warmupRemaining > 0) {
m_warmupRemaining --;
m_splashScreen->SetTime(m_warmupRemaining);
} else {
m_warmupTimer.stop();
}
}
};

Handling events raised from a lower level object

I'm writing a C++ programm using GTK+3.0. Anyway, I think this question may apply to any framework that uses events / signals.
I have a container class, say containerClass and a child class, say childClass. A childClass object child is contained inside a containerClass object container.
The child object is written to modify properties of something. To this aim, it has GtkEntry, GtkButton and so on. When I click the "save button", an event is raised.
This event must be handled by the container object, because the container is interfaced with a database in someway.
Hereafter, you find the solution I'm using to do the job:
// Child class
class childClass {
void setClickHandler_External(void (*extFun)(string property), void *);
void (*clickHandler_External)(string, void *);
void *clickHandler_External_Data;
static void buttonClicked(GtkWidget *widget, void *data);
}
void childClass::setClickHandler_External(void (*extFun)(string), void *data) {
// Set the external event handler
clickHandler_External = extFun;
clickHandler_External_Data = data;
}
void childClass::buttonClicked(GtkWidget *widget, void *data) {
childClass *m = (childClass *)data;
// Call the external event handler
m->clickHandler_External(property, m->clickHandler_External_Data);
}
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, void *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External((void(*)(string))&(this->clickHandler), (void *)this);
}
void containerClass::clickHandler(string property, void *data) {
// Event handler in the upper class
containerClass *m = (containerClass *)data;
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
This works well and does the job. Anyway, I was wondering if there is a smarter and cleaner way to achieve the same aim, maybe without using pointers to static functions, or by defining some kind of pattern to be reused everytime I need to have the same mechanism.
Thanks in advance
Gtkmm uses the sigc++ library to take care of all of this for you. There is no need to write it yourself.
Documentation links:
Signals overview
Appendix with detailed information
So, in this case, I would use something like
button.signal_clicked().connect(sigc::mem_fun(container, &containerClass::clickHandler));
while making sure that containerClass::clickHander has the appropriate number of arguments.
My first suggestion would be to use use templates to improve the type safety of what you are doing:
template< class ParamType >
void childClass::setClickHandler_External(void (*extFun)(string, ParamType *),
ParamType *data)
{
// Set the external event handler
clickHandler_External = (void ()(string,void*))extFun;
clickHandler_External_Data = (void*)data;
}
Then you can simplify the containerClass implementation as such:
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, containerClass *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External(&containerClass::clickHandler, this);
}
void containerClass::clickHandler(string property, containerClass *data) {
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
While it's great that this cleans up the implementation, removing the explicit casting from all the container implementors, that's not really the point. The point is to prevent you from passing wrong pointers into setClickHandler_External, causing crashes on the back end when events get dispatched.
My next step would take us further from your implementation, but would require more details about what you are actually doing. Depending on your needs that would be looking into:
Inheritance: should containerClass derive from childClass? That would provide access to a virtual function table that we could override.
Functors: look at boost::function and boost::bind to implement functors, eliminating the intermediate static function call.
Lambda Functions: bleeding edge (C++11 or later), but may be a good fit for this kind of forwarding function.

Maintaining signal connections over instance swap Qt5

In my Qt5 program I have an interface with some signals.
An implementation of this interface is instanciated at start up and the signals are connected to from different parts of the program (many places).
Now I want to delete that instance and create a new instance, possibly from another implementation, and somehow maintain the signal connections so that all the places that receive the signals does not need to care that the implementation changed.
Is there any way to do this elegantly or do I have to change the architecture of program to keep control over all signal connections in one location (a lot of work)?
Example:
//PS: To be regarded as pseudocode at best, as lots of Qt boilerplate
// and error handling code has been left out, and lots of bugs are left in :-)
struct MyInterface{
virtual void doStuff()=0;
signals:
void someSignal();
}
struct MyImpX:public MyInterface{
void doStuff(){
qDebug()<<"MyImpX";
if((random()%100)<5){
emit someSignal();
}
}
}
struct MyImpY:public MyInterface{
void doStuff(){
qDebug()<<"MyImpY";
if((random()%100)<10){
emit someSignal();
}
}
}
struct MyWorker{
QTimer t;
MyInterface *inst=0;
MyWorker(MyInterface *inst):
inst(inst)
{
connect(&t,SIGNAL(timeout()),this,SLOT(doStuff()));
t.start(100);
}
void setNewInstance(MyInterface *inst){
this->inst=inst;
}
void doStuff(){
if(0!=inst){
inst->doStuff();
}
}
}
struct MyConsumer{
public slots:
void handleIt(){
qDebug()<<"Handling signal";
}
}
void main(){
QApplication app;
MyInterface *inst=new MyImpX();
MyWorker con(inst);
MyConsumer i,j,k,l;
//In this example all the connects are in one place, but
//in reality they are called from several locations that
//Are hard to control.
connect(inst,SIGNAL(someSignal()),&i,SLOT(handleIt()));
connect(inst,SIGNAL(someSignal()),&j,SLOT(handleIt()));
connect(inst,SIGNAL(someSignal()),&k,SLOT(handleIt()));
connect(inst,SIGNAL(someSignal()),&l,SLOT(handleIt()));
//[ ... At this point some time passes where the signal is working ]
//Now the instance changes, so the old connections are lost.
con.setNewInstance(new MyImpY());
delete inst;
inst=0;
//[ ... At this point some time passes where the signal is NOT working ]
app.exec();
}
You could try to implement something based on this question, but I think that'll be hacky at best.
So, instead, you could have a proxy object, which does not get changed, and which can change its connections when the actual object changes. For this, you should probably use signal-signal connections, though you could also write slots which emit signals. Question has pseudocode, so here's some pseudocode as well, to demonstrate the principle.
class MyInterfaceSignalProxy : public MyInterface {
//...
public:
void reconnect(MyInterface *newObj, MyInterface *oldObj=0) {
if(oldObj) disconnect(oldObj, 0, this, 0); // disconnect old connections
connect(newObj, SIGNAL(someSignal()), this, SIGNAL(someSignal()));
}
signals:
void someSignal();
}
Of course you could remove the oldObj parameter, and for example store the currently connected object as private variable, or just not care about disconnection earlier connectios (for example if oldObj will be deleted or otherwise disconnected elsewhere).
And then your main would start something like:
void main(){
QApplication app;
MyInterfaceSignalProxy proxy;
MyConsumer i,j,k,l;
connect(&proxy,SIGNAL(someSignal()),&i,SLOT(handleIt()));
connect(&proxy,SIGNAL(someSignal()),&j,SLOT(handleIt()));
connect(&proxy,SIGNAL(someSignal()),&k,SLOT(handleIt()));
connect(&proxy,SIGNAL(someSignal()),&l,SLOT(handleIt()));
MyInterface *inst=new MyImpX();
proxy.reconnect(inst);
//....
MyInterface *inst2=new MyImpY();
proxy.reconnect(inst2, inst);
delete inst; // whatever

how to call a function to refresh GUI

I am refactoring some code to decouple GUI from some state.
#include <StateObject>
Class GUI{
...
StateObject A;
void doSomething() { A->hullaballoo();}
**void ReFreshMyGui() { //take state A and redraw }**
};
State object is being shared by multiple classes to update the state but this Gui Object specializes in displaying the state. So I would like to call the Refresh function via StateObject whenever its modified.
I am not sure how or if signals will provide the solution. Any hints?
In order to decouple GUI and Data you could use the MVC pattern. This means your GUI should register to your model's (data) object(s) and whenever the data changes the GUI will be notified and it will be the GUI to redraw itself.
But careful, the model should not have the notion of a concrete GUI, instead the GUI should implement an observer interface containing a method (e.g. void Update()) that will be called whenever changes occur (notification handler).
Just look for the MVC-pattern on google. You'll find thousands of useful tutorials.
You may also take in consideration the MVP and the MVVM patterns.
Example:
class Observer
{
virtual void Update(void* data) = 0;
}
class GUI : public Observer
{
public:
virtual void Update(void* data)
{
//Redraw method and some other things you may
//want to do with the new data
}
}
class Model
{
private:
int m_iData;
List<Observer> observers;
public:
void SetData(int iData)
{
m_iData = iData;
for(int i = 0; i < observers.Length; i++)
{
observers[i].Update(NULL);
}
}
}