Hi Everyone,
I could use some help putting together some psudo code for an input system that supports multiple keys/controller buttons pressed at the same time as well as delay and repeat. At first I checked for the keydown events and then set a command based on the keypress, but this only captures the last key pressed. I then added a command queue which works a little better but still only sends a command on a keypress. I would like this input system to handle key repeats as well.
Currently I have something that is fairly elementary. Can everyone help me learn how to put this together better?
//pollEvents is called in every iteration of the game loop.
ley::Command ley::Input::pollEvents(
bool& fullscreen,
ley::KeyBindings* bindings,
std::queue<ley::Command>* commandQueuePtr,
ley::TextEntry* te,
const std::function<void(ley::Command c)>& function //function pointer for handling textentry.
)
{
SDL_Event event;
ley::Command command = ley::Command::none; //direction for this frame;
while(SDL_PollEvent(&event)) { //SDL_PollEvent calls pumpevents.
const Uint8 *state = SDL_GetKeyboardState(NULL);
switch (event.type) {
case SDL_QUIT:
command = ley::Command::quit;
break;
case SDL_TEXTINPUT:
/* Add new text onto the end of our text */
te->onTextInput(event.text.text);
break;
case SDL_TEXTEDITING:
break;
case SDL_KEYDOWN:
//anyInputsMatch will handle cases where multiple keys can be used for a single command
if (anyInputsMatch(state, &bindings->debugkeystoggle.second)) {
command = bindings->debugkeystoggle.first;
SDL_Log(SDL_GetScancodeName(SDL_SCANCODE_F12));
commandQueuePtr->push(command);
}
if (state[SDL_SCANCODE_C]) {
command = ley::Command::debugclear;
commandQueuePtr->push(command);
}
if (state[SDL_SCANCODE_F]) {
command = ley::Command::debugfill;
commandQueuePtr->push(command);
}
//Full screen mode
if ((state[SDL_SCANCODE_LALT] && state[SDL_SCANCODE_RETURN])
||(state[SDL_SCANCODE_RALT] && state[SDL_SCANCODE_RETURN])) {
fullscreen = !fullscreen;
}
//Rotate Block counter clockwise
if (anyInputsMatch(state, &bindings->cclockwise.second)) {
command = bindings->cclockwise.first;
commandQueuePtr->push(command);
}
if(state[SDL_SCANCODE_RETURN] && !(state[SDL_SCANCODE_LALT] || state[SDL_SCANCODE_RALT])) {
command = ley::Command::enter;
commandQueuePtr->push(command);
}
// etc ...
function(command); //handles text entry.
break;
case SDL_KEYUP :
break;
case SDL_CONTROLLERBUTTONDOWN :
switch (event.cbutton.button) {
case SDL_CONTROLLER_BUTTON_A:
command = ley::Command::enter;
break;
case SDL_CONTROLLER_BUTTON_START:
command = ley::Command::pause;
break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
command = ley::Command::left;
break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
command = ley::Command::right;
break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
command = ley::Command::down;
break;
case SDL_CONTROLLER_BUTTON_DPAD_UP:
command = ley::Command::cclockwise;
break;
case SDL_CONTROLLER_BUTTON_X:
command = ley::Command::clockwise;
break;
case SDL_CONTROLLER_BUTTON_Y:
command = ley::Command::cclockwise;
break;
case SDL_CONTROLLER_BUTTON_B:
command = ley::Command::space;
break;
case SDL_CONTROLLER_BUTTON_BACK:
command = ley::Command::quit;
break;
// Add more cases for other buttons...
}
SDL_Log("Controller was pressed");
break;
default:
break;
}
}
return command; //not really used anymore now that there is a command queue.
}
Thanks for your help,
Electrosys.
p.s. if your interested in seeing this in its full contextual glory you can look at my project on github. I have a tetromino game on steam. sdl2-blocks/Input.cpp at master Ā· electrosy/sdl2-blocks Ā· GitHub