I have a pretty generic input class. In the main app, I forward an event to the game. The game an input object that manages Keyup and Keydown presses. It stores the keys pressed in a vector<key>
until the keyup function is called. For some reason, the keyup isn't always caught. I will add the relevant code, but let me know if you need more.
input.cpp
void Input::update() {
//iterate held keys vector and perform held functions for them.
for( std::vector<key>::iterator it = HeldKeys.begin(); it != HeldKeys.end(); it++ ) {
std::map<key,std::function<void()>>::iterator func = OnHoldFuncs.find(*it);
if( func != OnHoldFuncs.end() )
func->second();
}
}
void Input::KeyDown(SDL_KeyboardEvent pkey) {
//Check the keyboard event if the key is held and return if it is. We've already dealt with it.
if( pkey.repeat == 1 )
return;
//Create the key object (struct is in header)
key nkey(pkey.keysym.scancode,pkey.keysym.mod);
//Look for registered call back on the keydown event
std::map<key,std::function<void()>>::iterator func = OnDownFuncs.find(nkey);
if( func != OnDownFuncs.end() )
func->second();
else
std::cout << "unknown key " << pkey.keysym.scancode << " is pressed" << std::endl; //just debug message
//look for held key function
func = OnHoldFuncs.find(nkey);
if( func != OnHoldFuncs.end() )
HeldKeys.push_back(nkey); //function exist, store the key in the vector
else {
//to add a debug so I don't have to manually register keys right now for testing.
RegOnKeyHold(pkey.keysym.scancode,pkey.keysym.mod,[=](){
std::cout << "I AM BEING HELD AGAINST MY WILL " << pkey.keysym.scancode << std::endl;
});
HeldKeys.push_back(nkey);
}
return;
}
void Input::KeyUp(SDL_KeyboardEvent pkey) {
//create key object
key nkey(pkey.keysym.scancode,pkey.keysym.mod);
//look for registered call back
std::map<key,std::function<void()>>::iterator func = OnUpFuncs.find(nkey);
if( func != OnUpFuncs.end() )
func->second();
else
std::cout << "unknown key " << pkey.keysym.scancode << " is released" << std::endl; //debug msg
for( std::vector<key>::iterator it = HeldKeys.begin(); it != HeldKeys.end(); it++ ) {
if(*it == nkey) {
HeldKeys.erase(it); //remove it from the vector
break;
}
}
}
And the game.cpp, game is passed all events by default right now.
void Game::Handle(SDL_Event* Event) {
switch(Event->type) {
case SDL_KEYDOWN:
input.KeyDown(Event->key);
break;
case SDL_KEYUP:
input.KeyUp(Event->key);
break;
default:
break;
}
return;
}
EDIT: Polling loop from application forwards all events to application Handle function. Here is the polling loop and handle function and game handle function.
while(GameState == RUNNING) {
while(SDL_PollEvent(&Event)) {
Handle(&Event);
}
Update();
if( SDL_GetTicks() > Time + 100) {
Render();
Time = SDL_GetTicks();
}
else
{
SDL_Delay(1);
}
}
Handle function that forwards to game for all cases but quit. Probably should forward that one too so the game can ask to save first or stop the quit.
void KApp::Handle(SDL_Event* Event) {
switch (Event->type)
{
case SDL_QUIT:
GameState = HALTED;
break;
default:
game.Handle(Event);
break;
}
}
And the game handle function which handles all up and down events.
void Game::Handle(SDL_Event* Event) {
switch(Event->type) {
case SDL_KEYDOWN:
input.KeyDown(Event->key);
break;
case SDL_KEYUP:
input.KeyUp(Event->key);
break;
default:
break;
}
return;
}