Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I hope the title makes sense. Basically, I am trying to figure out how the app will know I the input I am sending it is meant for the app and not the player, and vice-versa.
(It is very similar to this question, A pattern for a contextual InputState in a Game State Management architecture)

This is an idea I've had, but it's flawed. Any suggestions?

There will be a class to gather input, called IOManager Another class will register the IOManager, called IOHandler. Various subclasses of the IOHandler will handle the output differently. For example, IOPauseState will handle input differently than IOTitleState or IOPlayer

My problem comes with differentiating between the "GameStates" and the "Player" when handling the IO. I could have two separate HandleInput functions in the IOHandler class; one that accepts a reference to a state and another that accepts a reference to the player, but that does not seem right.

How should I go about handling this, when I can't really subscribe them or pass them through because the player and the gamestates are two completely separate classes?

share|improve this question
    
So, you want to gather input/events and store it all in one class, IOManager, then use(?) these events differently depending on game state such as IOPauseState and IOTitleState. But you also want player-specific event handling. However you're not sure how the player input handler will interface with your other game states, since they are all separate derived classes of IOHandler. Is this correct? I just want to clarify. – Luke San Antonio Jul 5 '13 at 9:29
    
If the inputs only come from internal (no network) then I would chose two classes to handle this. If the IO comes from a network it is a matter of protocol design. – Uwe Plonus Jul 5 '13 at 10:26
    
@LukeSanAntonio, that is correct. Nothing is coming from a network, it's all input from a keyboard / mouse / game controller. – Daniel Martin Jul 5 '13 at 19:37

As described in the question you linked to, there is a great XNA/C# example project that handles this problem elegantly. It is cleanly written, easy to read and very minimal; it may be helpful in inspiring your own c++ system. Game State Management Sample.

The method employed is that each part of the game is a "screen", including all menus, the game view, and any modal popups. The screens are handled like a stack. The screen manager, which is an exercise of the mediator pattern, takes care to flag each screen as being on top of the stack (or transitioning to/from). By doing this, it can toggle a flag in each screen that checks for updates to the input singleton (like your IOManager). If the screen is not on top, it doesn't check the input.

So, no IOHandler is required (still perfectly reasonable to have them), because every screen that needs input keeps a reference to the global input. But they only actually check that reference for updates when they are supposed to. This immediately solves the problem of common input between tiered menus, pause screens, loading screens, and gameplay input. Your app only gets input when it is the top-most screen, the player gets input when the gameplay is on top.

Edit - Why the linked topic is asking the wrong question:

I think you are struggling to define a common IOHandler base class because inheritance is not the right way to do what you want. Inheritance can be mis-used to create a hierarchy of every single class in a system, but doing so creates the kind of problem you are having. It should be used only when a child class is the type it is extending. For menus and players, that's not the case.

The rhetorical example I like best is, "Should Viewport inherit from Rectangle? They're both rectangular." Well no, it shouldn't. Likewise, you are building a variety of objects that all respond to input. But they should not inherit from an IOHandler class. They should contain a reference to IOManager.

If you want your various menu screens to all use IOManager the same way, by all means give them a uniform update function in a parent class. Player should use it in an entirely different way. They should not be part of an inheritance tree.

share|improve this answer
    
I already implement this, I just call them states rather than screens. Only the topmost state on the stack gets drawn / updated / checks for IO. My problem is that I want to have a separate entity handle the IO, and call the appropriate method. But, since the Player and the States are entirely separate classes, I can not effectively create a common IOHandler class to handle the input, and derive from it other classes that would handle the IO depending on what they were. – Daniel Martin Jul 5 '13 at 19:44
    
I guess what I'm truly asking is to be more clarified on the answer for the question I posted in the OP, since I didn't really understand the answer because the States and the Player would be of different classes, so how would you implement it having all of the various IOHandlers be related? gamedev.stackexchange.com/questions/20544/… – Daniel Martin Jul 5 '13 at 19:47
    
Why do you want them to be separate entities; why have an IOHandler at all? You can implement as many different interfaces on your IOManager as you want, and each of your states can sample whichever they require. Using different parts of an interface does not require dedicated classes. Just call them from your state objects. – Seth Battin Jul 5 '13 at 21:07
    
(Continued...) In my opinion, the question you linked solved a problem that the sample itself had already solved. The different screens already react differently to the same input depending on which screen is active. There's no need to do anything extra, like the poster was trying to do. – Seth Battin Jul 5 '13 at 21:09

I have typically handled input specially from the more generic state and event systems.

Input has "controllers" which register themselves. There are implicit priorities where state controllers are run in state stack order. A DOM Events model is used. The input event is delivered to each controller in order until one "consumes" it.

For keyboard and mouse DOWN events (a key/button is pressed), the controller that consumes that input is then recorded for that specific key. The corresponding UP event is delivered directly to that controller and then the registration is cleared. Also cleared during app focus switch to avoid alt-tab bugs. It can also be handy to clear them when the registered controllers change, so e.g. holding the left arrow doesn't keep moving the player when a menu pops up. If a controller is bound to a key and is removed for any reason than an actual UP event, one is synthesized and delivered before the controller is unbound.

For UI elements, a UI controller manages all the complexity of focus, tabbing, etc. UI states like PausedState or whatnot is responsible for taking any input messages and forwarding them to the UI. This allows UI elements to be visible while the UI is inactive, which for instance is handy with a layered UI system (e.g. a state for inventory management might keep drawing while a pause screen is active with a small pause menu in the middle of the screen).

The PlayingState controller is responsible for player game input rather than a particular game object. The state moves the player avatar rather than the avatar moving itself. It is possible and not all daft to have the objects manage input themselves, especially if you use a heavily component-based object system for menus and complex gameplay features, but I've personally felt that input game logic is much easier if all gameplay input handling is in a single place instead of strewn around a variety of objects, plus it ensures that the player avatar ceases to receive input when menu pops up.

This all works for event-based input. Game logic controllers for player avatar handling should be built specifically for polling input; also for key bindings. The playing state might take all raw input messages and deliver them into a PlayerInputController class which looks up keybindings, handles analog vs digital inputs, etc., and then maintains an internal state like IsMovingLeft or whatnot. The actual game logic can then receive events from the input controller, if you prefer that method, or it can poll the input controller every frame with something like if (m_InputController.IsMovingLeft()) move_player_left();

share|improve this answer

I know this is an old question, but I have been doing a lot a game engine design recently and wanted to share some of my thoughts on handling input. To me, a pause state, menu state, and player state are all conceptually the same as far as input goes. If I click something in the menu state, I am requesting to select that menu item. If I click somewhere on the game view, I am requesting the player pawn to move to that location (just as an example). So what I do is utilize a screen stacking system like Seth Battin mentioned in his answer, but instead of having references to the IO controller and a flag as to whether or not that particular screen handles IO, I use the chain of responsability/first responder design pattern. Here is some psuedo-code to give an example of what I mean:

Interface Screen
{
    public:
    void update();
    void render();
    bool handleIO(InputEvent ie); // Returns true if the input was handled and propagation of this event should stop.
    .
    .
    .
}

class InGameMenu implements Screen
{
    public:
    bool handleIO(InputEvent ie)
    {
        if(ie.type == MouseClick && m_menuItem1.intersects(ie.coordinates()))
        {
            // Handle logic for menu item 1 being selected.

            return false;
        }
        .
        .
        .   // Handle other menu items in a similar way.


        return true;    // The menu state always returns true if nothing important took place
                        // since you don't want that input being handled by other screens while
                        // the menu is up.
    }
}

class UIButton implements Screen
{
    public:
    bool handleIO(InputEvent ie)
    {
        if(ie.type == MouseClick && m_btnGraphic.intersects(ie.coordinates()))
        {
            // Handle logic for ui button being interacted with.

            return true;    // Usually true is the right return type if an event is handled, but
                            // if there is a case where you need Screens below to also handle
                            // the event, you have the option of returning false.
        }


        return false;   // The ui button will return false unlike the menu. This is the case
                        // because you want other screens lower in the Screen stack to handle
                        //  the event in the case where nothing interesting happened.
    }

}

class WorldMap implements Screen
{
    public:
    bool handleIO(InputEvent ie)
    {
        if(ie.type == MouseClick && /* Some other condition is met that needs this input  */)
        {
            // Handle logic input on the map.

            return true;
        }


        return false;
    }

}

Then the Screen Manager class might look similar to this:

class ScreenManager
{
    public:
    void pushScreen(Screen s)
    {
        screens.push(s);
    }

    Screen popScreen()
    {
        return screens.pop(s);
    }

    void handleIO(InputEvent ie)
    {
        foreach (Screen s in screens)
        {
            bool eventHandled = s.handleIO(ie);

            if(eventHandled)
            {
                break;
            }
        }
    }
}

So I think the comments help explain the process, but in your setup you would register your screens with the manager. One example using the above might be:

screenManagerInstance.pushScreen(mapScreenInstance);
screenManagerInstance.pushScreen(uiButtonInstance);

So now when you have an input, let's say a mouse click, the ui button get first priority to act on the click. If the click was not on the ui button, then the click event is passed on to the map where something interesting may take place if the click was on say a treasure chest or a bad guy. If the click never hits anything of interest by the time it reaches the bottom Screen, it is tossed off into eternity and should be destoryed or garbage collected.

If the another click happens, the process starts all over again. This time, let's say the click hits the ui button which should trigger the opening of the in game menu. Through some messaging mechanism outside the scope of this question, the ui button requests for the in game menu to open. This request would go to a logic controller or current game state that would do the proper state transitions and in the process push a inGameMenuInstance onto the screenManagerInstance:

screenManagerInstance.pushScreen(inGameMenuInstance);

Now when a click comes in, the inGameMenuInstance gets first priority on the click event and since we designed the in game menu to block all inputs from other Screens until it is closed, the uiButtonInstance and mapScreenInstance never even know that a click event came in. They just sit there until the menu is closed. The closing of the menu or selection of a menu item would probably trigger another state change message like our ui button did earlier. The logic controller or game state would perform the necessary transitions in logic and as part of that, remove the inGameMenuInstance from the screenManagerInstance:

screenManagerInstance.popScreen();

Now we are back to where we started and input can propagate through all Screens again. It is also worth noting that instead of passing an IO event, you could pass your IO manager that each Screen could query for what input is taking place.

Not the only way to handle IO between multiple components, but a way that has worked for me and is pretty flexible in my opinion.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.