Megatron:
To handle the user inputs, I have two classes.
input_map contains maps for mouse and keyboard inputs
std::map<sf::Key::Code, boost::function<void()>> key_bindings;
std::map<sf::Mouse::Button, boost::function1<void, const sf::Input&>> mouse_bindings;
To use this map, I have to bind a key or a button to a function, which is supposed to be called, if the button/key is pressed(boost is very helpful
).
template<class T>
void register_input_id( sf::Key::Code key, void (T::*Func)(), T& obj)
{
key_bindings[key] = boost::bind(Func, boost::ref(obj));
}
template<class T>
void register_input_id( sf::Mouse::Button mouse, void (T::*Func)(const sf::Input&), T& obj)
{
mouse_bindings[mouse] = boost::bind(Func, boost::ref(obj), _1);
}
The scond class is an input-manager, which contains all the input-maps. At each update-step it checks, weather a key of an input-map is pressed and runs the function:
for( std::vector<input_map>::iterator action_it = input_maps_.begin();
action_it != input_maps_.end();
action_it++)
{
for( std::map<sf::Key::Code, boost::function<void()>>::iterator key_it = action_it->key_bindings.begin();
key_it != action_it->key_bindings.end();
key_it++)
{
if(input_.IsKeyDown(key_it->first))
key_it->second();
}
for( std::map<sf::Mouse::Button, boost::function1<void, const sf::Input&>>::iterator mouse_it = action_it->mouse_bindings.begin();
mouse_it != action_it->mouse_bindings.end();
mouse_it++)
{
if( input_.IsMouseButtonDown(mouse_it->first) && !mouse_button_pressed_.at( mouse_it->first ) )
{
mouse_it->second( input_ );
}
}
}
Well to use it, is very easy. An instance of an input-map is created in every class, where it is needed and some key events have to be registered:
input_map_.register_input_id( sf::Key::Back, &gs_game::exit_game, *this );
game_env_.input_manager.register_input_map( input_map_ );
And maybe my system is complicated, too, but it is also very easy to port and to use it with other input-frameworks(a few weeks ago I used it with OIS)
If you want objects to be aware of input, just make the window's input globally accessable via a global variable, a function that returns a reference or pointer to the input, or via passing a reference or pointer to functions.
It's a very simple way indeed, but I wouldn't prefer it. If I got your point right, every single object(which is supposed to check inputs) has to get an input-variable and handle the input by itself. I don't think that this is a very good way, because I don't think that it is the business of every single class to handle their own inputs. And on the one hand you have to copy code and use the same code twice(or even more often) to process input for more than one object. If there is a mistake in your code, you will have to change it a couple of times. On the other hand I think that code, that is used more than once or twice, should be designed in another way, to use the same code for all instances. And this is what an input-manager does
.