Tuesday, February 2, 2016

architecture - Keyboard input system handling


Note: I have to poll, rather than do callbacks because of API limitations (SFML). I also apologize for the lack of a 'decent' title.


I think I have two questions here; how to register the input I'm receiving, and what to do with it.



Handling Input


I'm talking about after the fact you've registered that the 'A' key has been pressed, for example, and how to do it from there.


I've seen an array of the whole keyboard, something like:


bool keyboard[256]; //And each input loop check the state of every key on the keyboard


But this seems inefficient. Not only are you coupling the key 'A' to 'player moving left', for example, but it checks every key, 30-60 times a second.


I then tried another system which just looked for keys it wanted.


std::map< unsigned char, Key> keyMap; //Key stores the keycode, and whether it's been pressed. Then, I declare a load of const unsigned char called 'Quit' or 'PlayerLeft'.
input->BindKey(Keys::PlayerLeft, KeyCode::A); //so now you can check if PlayerLeft, rather than if A.


However, the problem with this is I cannot now type a name, for example, without having to bind every single key.


Then, I have the second problem, which I cannot really think of a good solution for:



Sending Input


I now know that the A key has been pressed or that playerLeft is true. But how do I go from here?


I thought about just checking if(input->IsKeyDown(Key::PlayerLeft) { player.MoveLeft(); }
This couples the input greatly to the entities, and I find it rather messy. I'd prefer the player to handle its own movement when it gets updated. I thought some kind of event system could work, but I do not know how to go with it. (I heard signals and slots was good for this kind of work, but it's apparently very slow and I cannot see how it'd fit).


Thanks.



Answer



What I'd do is use the observer pattern and have an input class that maintains a list of callbacks or input handling objects. Other objects can register themselves with the input system to be notified when certain things happen. There are different types of callbacks you could register, based on the type of input events observers would like to be notified about. This could be as low level as 'key x is down/up' or more game-specific like 'a jump/shooting/movement event happened'.


Generally game objects have an input handling component that is responsible for registering itself with the input class and providing methods to handle the events it is interested in. For movement, I have an input mover component that has a move(x, y) method. It registers itself with the input system and gets notified on movement events (where x and y would be -1 and 0 to signify moving left), the mover component then changes its parent game object coordinates based on movement direction and object velocity.


I don't know if this is a good solution but it works for me so far. In particular it allows me to provide different kinds of input system that map to the same logical game events so that gamepad button x and keyboard space both generate a jump event for example (it's a bit more complicated than that, allowing the user to reassign key mappings).


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...