Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Is there a standard technique for managing input in large games. Currently, in my project, all input handling is done in the game loop, like so:

while(SDL_PollEvent(&event)){
            switch(event.type){
                case SDL_QUIT:
                    exit = 1;
                    break;
                case SDL_KEYDOWN:
                    switch(event.key.keysym.sym){
                        case SDLK_c:
                            //do stuff
                            break;
                    }
                    break;
                case SDL_MOUSEBUTTONDOWN:
                    switch(event.button.button){
                        case SDL_BUTTON_MIDDLE:
                                //do stuff
                                break;
                            }
                    }
                    break;
            }

(I am using SDL, but I expect the main practice applies libraries and frameworks as well). For a large project this doesn't seem the best solution. I may have several objects all wanting to know what the user has pressed, so it would make more sense for those objects to handle input. However, they can't all be handling input, as after one gets an event, it will be pushed off the event buffer, so another object won't receive that input. What method is most commonly used to counteract this?

share|improve this question
    
With an event manager, you could fire event in input and let all other parts of your game register to them. –  danijar Jul 22 '13 at 17:11
    
@danijar what exactly do you mean by an event manager, is it possible if you could provide some skeleton pseudo code to show what kind of thing you are talking about? –  handuel Jul 22 '13 at 17:14
2  
1  
I wrote an answer to elaborate on event managers, which are the way to go for input handling for me. –  danijar Jul 23 '13 at 8:57

2 Answers 2

up vote 8 down vote accepted

As wished by the thread starter, I elaborate on event managers. They are a good way to handle input I think.

An event manager is a global class which allows to both register callback functions to keys and to fire keys. The manager stores registered functions in a private list under their key. Each time a key gets fired, all registered callbacks are executed.

The callbacks could be std::fuction objects which can hold lambdas. The key could be a string. Since the manager is global, components of your application can register to keys fired from other components.

// in character controller
// at initialization time
Events->Register("Jump", [=]{
    // perform the movement
});

// in input controller
// inside the game loop
// note that I took the code structure from the question
case SDL_KEYDOWN:
    switch(event.key.keysym.sym) {
    case SDLK_c:
        Events->Fire("Jump");
        break;
    }
    break;

You could even write a more advanced event manager which allows you to pass values as additional argument. C++ templates are great for this. You could use such a system to, say for a "WindowResize" event pass the new window size, so that listening component don't need to fetch it theirselves. That could hugely reduce dependencies which is almost always what you want.

Events->Register<int>("LevelUp", [=](int NewLevel){ ... });

I've implemented such an event manger for my game. If you are interested, I'll post the link to the code here.

I think, event managers are the way to go for input handling. Using them, you can easily spread input information around in your whole application. Moreover, input mapping becomes trivial. What I mean is when you want the player to choose his key bindings. When you use contentual key names ("PlayerJump" instead of "KeyPressedSpace"), you only have to modify the input controller.

share|improve this answer
1  
Great answer, thanks. Although I'd love to see the code, I don't want to copy it, so I won't ask you to post it until I've implemented my own, as I'll learn more that way. –  handuel Jul 23 '13 at 10:12
    
I just thought of something, can I pass any member function like this, or won't the register function have to take AClass::func, limiting it to one classes member functions –  handuel Jul 23 '13 at 11:24
    
That's the great thing about lambda expressions in C++, you can specify a capture clause [=] and references to all local variables accessed from the lambda will be copied over. So you don't have to pass a this pointer or something like this. But note that you can't store lambdas with capture clause in old C function pointers. However, the C++ std::function works fine. –  danijar Jul 23 '13 at 17:45

Split this into several layers.

At the lowest layer you have raw input events from the OS. SDL keyboard input, mouse input, joystick input, etc. You might have several platforms (SDL is a least-common-denominator lacking several input forms, for instance, which you might later care about).

You can abstract these with a very low-level custom event type, like "keyboard button down" or the like. When your platform layer (SDL game loop) receives input, it should create these low-level events and then forward them on to an input manager. It can do these with simple method calls, callback functions, a complicated event system, whatever you like best.

The input system now has the job of translating low-level input into high-level logical events. Game logic does not at all care that SPACE was pressed. It cares that JUMP was pressed. The input manager's job is to collect these low-level input events and generate high-level input events. It is responsible for knowing that the spacebar and the 'A' gamepad button both map to the logical command Jump. It deals with gamepad vs mouse look controls and so on. It emits high-level logical events that are as abstract as possible from the low-level controls (there are some limitations here, but you can abstract things away completely in the common case).

Your character controller then receives these events and processes these high-level input events to actually respond. The platform layer sent the event "Key down spacebar." The input system received that, looks at its mapping tables/logic, and then sends the event "Pressed jump." The game logic / character controller receives that event, checks that the player is actually allowed to jump, and then emits the "Player jumped" event (or just directly causes a jump to happen), which the rest of game logic uses to do whatever.

Anything dependent on game logic goes into the player controller. Anything OS dependent goes in the platform layer. All the rest goes into the input management layer.

Here's some amateurish ASCII art to describe this:

-----------------------------------------------------------------------
Platform Abstraction | Collect and forward OS input events
-----------------------------------------------------------------------
                          | |
                          | |
                         \   /
                          \_/
-----------------------------------------------------------------------
    Input Manager    | Translate OS input events into logical events
-----------------------------------------------------------------------
                          | |
                          | |
                         \   /
                          \_/
-----------------------------------------------------------------------
Character Controller | React to logical events and affect game play
-----------------------------------------------------------------------
                          | |
                          | |
                         \   /
                          \_/
-----------------------------------------------------------------------
      Game Logic     | React to player actions and provides feedback
-----------------------------------------------------------------------
share|improve this answer
    
Cool ASCII art, but not that necessary, I'm sorry. I suggest using a numbered list instead. Anyway a good answer! –  danijar Jul 23 '13 at 9:03
    
@danijar: Eh, I was experimenting, had never tried drawing an answer out before. More work than it was worth, but a lot less work than dealing with a paint program. :) –  Sean Middleditch Jul 23 '13 at 16:09
    
Alright, understandable :-) –  danijar Jul 23 '13 at 17:33
1  
Personally, I prefer the ASCII art way more than a boring numbered list. –  Jesse Emond Jul 23 '13 at 21:26
    
@JesseEmond Hey, here for art? –  danijar Jul 27 '13 at 22:57

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.