This is abit more of a conceptual question, but I figured this was likely the best place to ask. I looking for advice and I was wondering how other people handle input in their games.
For my game, which is primarily an RPG, but it has some action elements where the player will need to time their inputs carefully.
The way I designed mine, at least at the moment, was to have a separate class that's part of the game as a whole. Every Key Event/Joystick Event/Mouse Event is fed into that class, and the class will map the various types of input to ingame actions using maps like below:
std::map<sf::Key::Code, InputActions> KeyMapper;
std::map<sf::Key::Code, InputActions> KeyMapper2;
std::map<unsigned int, InputActions> JoyMapper;
where InputActions is an enum for the various actions in the game (Up, Down, Left, Right, Cancel, Confirm, Start, Select, etc.).
The input class has a bool array bool ActionSet[InputCount];
that is used to indicate what inputs are currently held. I activate the inputs as follows (the below are for keyboard keys, the joysticks use something similar)
//Used when the input module supports only one key active at a time
void HandleSingleKey(sf::Key::Code &key, bool released = false)
{
if (!released)
{
for (int i = 0; i < InputCount; ++i)
{
if (i != sf::Mouse::Button::Left && i != sf::Mouse::Button::Right)
ActionSet[i] = false;
}
}
auto it = KeyMapper.find(key);
if (it != KeyMapper.end())
ActionSet[it->second] = !released;
}
//Used when the input module supports multiple keys at a time
void HandleMultiKey(sf::Key::Code &key, bool released = false)
{
auto it = KeyMapper.find(key);
if (it != KeyMapper.end())
{
ActionSet[it->second] = !released;
}
}
I'm currently only testing with multiple inputs enabled (the HandleMultKey function).
Basically, each object that needs to handle user input will be fed a pointer to this input module, and the current game time at the start of each loop iteration. It is up to the object to determine if it is ready to resample the input and find the changes in user input (like below). InputRes represents how much time needs to elapse between each input sampling
void QTriadGame::UpdateInput(InputModule* module, float time)
{
if (time - LastInputUpdate > InputRes )
{
//Omitted Code Handling inputs by looking up active keys from module
LastInputUpdate = time;
}
}
Here's my concerns about the way I'm doing it:
As you can tell form the earlier, I'm relying on the Released event to tell me when to mark an input as invalid. I noticed while debugging that if the program was paused during input handling, the released event would fail. I'm worried about this happening once the game is running normally, and I'm not entirely sure how to deal with it. Anything involving timeouts could be bad as it's possible the user holds down a button for an extended period of time.
Additionally, I'm likely going to need to know later on when the key became active, so I might change my array from a bool array to an array of bools/float where float indicates the gametime when that input became active
It just feels like I'm making this more complicated then it needs to be, so I was looking for some advice/suggestions or how other people did their use input.
Thanks in advance