Skip to main content
GameDev.net gamedev.net
🔒 Locked

Input system independance

Started by Trillian Apr 1, 2007 at 6:06 PM 4 replies 800+ views
Original Post
Trillian
Trillian
Hello I'm working on my game engine and I want to acheive independance on the input system. I mean I can use an InputDevice which can abstract Win32 input or DirectInput input etc. Now I have a problem. Win32 and DirectInput do not use the same keycodes (VK_ versus DIK_). How am I going to unify that for any input system? Thanks!
ApochPiQ
ApochPiQ
My stock solution:

enum InputSourceID{  InputSource_Win32Keyboard,  InputSource_Win32MouseButtons,  InputSource_DIJoystickButtons};struct InputID{  InputSourceID source;  int code;  // For convenience  InputID(inputsource, inputcode)   : source(inputsource), code(inputcode)  { }};enum ActionID{  Action_FireGuns,  Action_Whatever,  Action_Example};// Configurable input mappingstd::map<InputID, ActionID> InputMap;


When you retrieve input from some source, you attach a source ID and the low-level code. For instance, the mouse buttons source might use 0, 1, 2 to identify left, middle, right mouse buttons, respectively; the joystick buttons source might use 0, 1, 2... to identify joystick buttons (shock!).

Then, instead of doing a comparison on just the VK_*, DIK_*, etc., you compare on both the source and the raw code. In this way, every input source can use its own internal IDs, without causing conflicts. Effectively it's just a namespacing solution.

Once you collect all input codes, you just pass them through the input map to get a set of actions, and there you go.
Trillian
Trillian
That does not answer my question but
- It is a good idea, I will use it
and
- I found the answer to my question myself :D

So thanks a lot!
Zakwayda
Zakwayda
Quote:
Original post by Trillian
- I found the answer to my question myself :D
You should post it - others might find the solution to be useful as well :)
Trillian
Trillian
Quote:
Original post by jyk
Quote:
Original post by Trillian
- I found the answer to my question myself :D
You should post it - others might find the solution to be useful as well :)


Good idea!

First of all I have enumerated the so-called standard keys :
enum StandardKey { STANDARDKEY_MOUSELEFT, STANDARDKEY_ESCAPE ... }

Each of my input devices have been standarised in an interface suprisingly called "InputDevice". Each device can be queried it's number of buttons and then each button state, given an index. I've added a virtual function to this device class called "getStandardKeyIndex". This function takes a "StandardKey" and returns the implementation-dependant index (such as VK_SUMTHIN or DIK_ANOTHERTHING), or -1 if this device has not this standard key (for example a joystick has no STANDARDKEY_ESCAPE).

Once you've queried the implementation-dependant index, you can use it to access the actual button state.
ApochPiQ
ApochPiQ
The goal of my approach is to eliminate the need for the "StandardKey" enum concept. Instead of having a giant list of keys that you look up per device, you simply let the raw device use its natural key codes.

This is made practical by the fact that the raw input codes (qualified by their source ID) are mapped directly to actions; actions are fully independent of input method. You can completely ignore the raw input codes in the system once this is in place; they just automatically work.

This eliminates a very nasty set of problems where you have an input device that is missing certain sets of keys - for instance, a laptop keyboard which doesn't have a numpad. By going directly to a completely abstract "action" rather than having any notion of "buttons" or "keys" in the code, we avoid a serious issue where you poll the state of, say, the STANDARD_NUMPAD_ZERO key, but that key doesn't exist. These kinds of problems also come up very often when people have differing keyboard layouts (and there are many different standard keyboard layouts in use around the world).

The only case where you need to worry about raw input codes is when you construct the mapping data, that is, when you specify what buttons link to what actions. Typically I just have a data file on disk that specifies the mappings, linking raw codes to the actual action IDs. A reasonable default set of mappings can be constructed easily, and then your control remapping interface can take care of devices or scenarios that your defaults don't account for.


Note that it is also trivially simple to extend this to allow for state queries: instead of polling the raw button state, you map the raw button to a virtual state (such as State_FiringWeapon). Then your game logic polls the virtual state and remains completely agnostic of how the input system works.

Incidentally, this also allows for a rather elegant AI integration where you can use the same actions as part of a state machine - but that's wandering off topic a bit [smile]

Topic Locked

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

Sign in to reply to this topic.