0
\$\begingroup\$

I'm writting a game in C++ and I'm struggling with getting events and game states work together.

By game states I mean something like this

class GameState
{ 
public:
    virtual void onPause();
    virtual void draw();
    virtual void update();
};

class PauseScreen : public GameState
{
     //stuff
};

class Game : public GameState
{
     //stuff
};

And I've created dope event observer based system where I have simple EventObserver class which has register function to what Event I want to subscribe and EventManager where I have map of vectors of all possible EventObservers (everything made with templates) and callback functions. No pointers, no inheritance - everything works like charm.

So there is my problem - how to connect these? In my main loop I'm getting current active game state - and then updating and drawing it. But for example when state is not active its still receiving event. This is pretty bad beacuse if I have MainMenu gamestate and for example if escape key is pressed it would just exit the game even if I'm currently in Game.

I could only came with some bool checking - if current state is not more active it would disable all EventListeners but I would need to manually call EventListener::disable in all game states for every EventListeners I have in onPause() methods and I don't like this solution (and since it's my hobby project I would like things that I like). I could store EventListeners in vector in GameState interface class so I wouldn't need to disable it manually and just iterate thought it and disable it 'automatically' but I would have to deal with A LOT of templates and naaah I don't wanna do it (just keep it simple).

On the other hand I could add method to GameState handleEvent(Event* event) (well since this is now dynamic memory I would probably prefer to use smart pointers so I don't need to worry when I have to delete event) but then I would have giant switch statement for every game state that I have and this also doesn't seems like good solution. Now I'm just binding one method per one event so everything is nice divided and simple.

So any tips how to design this? Can event observers (or subscribers) work with game states?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I don't have the luxury to write a full answer, unfortunately, but here it is, at a glance. Note that there seems to be some fundamental architecture differences between what we have and what you have, but here goes.

First, when we enter a game state, we register this as a listener to the events in which the game state is interested; we kind of have a mechanism to auto-de-listen using smart pointers, so when we exit the state (or it's paused), we de-register this for these events. ...and we register the new events for the new state, etc... This takes care of things that if you hit "escape", then only one state will be listening to it.

This is coupled to a special feature for our input manager. Some key events can have a special meaning depending on what's going on. For instance, if you hit "A" during the "normal gameplay", it will interact with the environment, but if there is a pop-up, we need "A" to do something else instead (like close the pop-up), even if we're in the same game state as before. To achieve this, the input manager has a concept of 'context'. At the beginning of the state, we supply the different contexts for that state, like "in game", "pop-up". Each context as a priority, and each context can be enabled or disabled, the "pop-up" one having a higher priority, but being disabled at the beginning of the state.

Once we show the pop-up, we enable the "pop-up" context in the input manager, thus when the user presses "A", it does something related to the pop-up only, because the event is steered there instead of going to the game state. Once we hide the pop-up, we disable the context.

I'm not sure this solves your issue, but I hope it will give you some ideas.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .