Skip to main content
gamedev.net
🔒 Locked

Input remapping

Started by Wavesonics Apr 1, 2007 at 7:30 PM 6 replies 900+ views
Original Post
Wavesonics
Wavesonics
Currently I have a switch statement, one case for each key that does something and the corresponding actions is inside that case. But I want to be able to change the key that triggers the action on the fly, how do most of you do this?
jouley
jouley
[Edit: I spewed forth some filth, and it luckily didn't get through unchecked. Version 2.0...]

At the most basic level, a common way of doing this is to have an array for each action to occur that holds the keys each action is mapped to. (The word map here may inspire you to find another implementation than the one presented below...)

For example, let's say you want a character on the screen to be able to move left, right, jump, and crouch. Your array would be set up as follows:
enum eActions { LEFT, RIGHT, JUMP, CROUCH, NUM_ACTIONS };key array[NUM_ACTIONS];array = LEFT_ARROW;array = RIGHT_ARROW;array[JUMP] = UP_ARROW;array[CROUCH] = DOWN_ARROW;


Then, your loop would simply deal with the array, rather than the keys themselves:
<strike>switch (input){  case array:    // move left    break;  case array:    // move right    break;    //...}</strike>if (input == array)  // move leftelse if (input == array)  // move right//...


To update this on the fly, so that, say, a user can input their own keymappings, you could do something like the following:
// user has indicated they want to change the jump key// they are about to press a key...key thatTheUserPressed = getInput( );array[JUMP] = thatTheUserPressed;

Magically, the jump key is changed, automatically handled in the switch statement if/else tree, and you can rest easy, knowing your users are having a great time finding new ways to arrange their fingers on the keyboard.

Best of luck!
-jouley

[Edited by - jouley on April 1, 2007 9:09:40 PM]
Zakwayda
Zakwayda
Quote:
Original post by Wavesonics
Currently I have a switch statement, one case for each key that does something and the corresponding actions is inside that case.

But I want to be able to change the key that triggers the action on the fly, how do most of you do this?
I use a 'command binding' mechanism, similar to that used in Quake-ish console systems.

Each key has a binding associated with it, where a binding constitutes either an enumerated value or a string, and a delegate that is invoked when the key is pressed and/or released (the delegate can be e.g. a global or static function, or a member function bound to an object). The bindings can be changed on the fly from the console or from within the application (e.g. in response to menu events).

This is very flexible, but might be overkill for some applications.

A simpler solution would be to use a simple if-else-if sequence, which would allow you to use a variable to represent the key currently assigned to an action.

There are plenty of in-between solutions as well, such as mapping keys to function objects directly via a map or vector. It might be worth taking a look at Boost.Function and Boost.Bind if you want to go this route.
Zakwayda
Zakwayda
Quote:
Original post by jouley
switch (input){  case array:    // move left    break;  case array:    // move right    break;    //...}
Hm, don't case labels have to be constant expressions?
Wavesonics
Wavesonics
Aaaahhhh...

That was my first instinct but I was pretty sure the cases couldn't be variables in C++.

This binding idea you are talking about though,
would you implement this with function pointers essentially?

something like:

struct KeyBinding {
string key;
void *binding;
};

Sorry if thats not the correct syntax for function pointers, I have very very limited experience with them, but that is the general idea correct?
jouley
jouley
Quote:
Original post by jyk
Quote:
Original post by jouley
switch (input){  case array:    // move left    break;  case array:    // move right    break;    //...}
Hm, don't case labels have to be constant expressions?


Yikes. As usual, you're quite right -- thanks for the catch. This would work for if/else trees, but certainly not switches.
King Mir
King Mir
Function pointers have their own type for each combination of arguements and return values. Function pointers cannot be converted to void *s however. They are a solution to this, but in C++ it usually better to use functors.

Functors are objects that act like function pointers, but have inherretence. This allows for unrelated functors that happen to have the same properties to have different types.

A family of functors would have a single parrent, used refer to all of them, and contain a virtual opperator(). Each functor contains a different overload of opperator(). Opperator() can take any paramitters you want it to, and return anything you want it to.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.