I'm teaching myself 3D graphics with OpenGL and SDL in C++. I'm at a point where I need to be able to query states of individual keys, like so:
if (InputManager::justPressed(SDLK_UP)) {}
if (InputManager::pressed(SDLK_UP)) {}
if (InputManager::justReleased(SDLK_UP) {}
I'm not sure if I should be using SDL_GetKeyboardState or bool arrays for SDL_Keycode/SDL_Scancode, using states seems to me to be the more correct way. I've implemented this previously using states in C# with XNA (see that here). But I've been unsuccessful trying to replicate that with SDL.
Method 1 - Using SDL_GetKeyboardState
// InputManager stores
Uint8* _curKeys, _oldKeys;
void InputManager::init() {
_curKeys = SDL_GetKeyboardState(NULL);
_oldKeys = new Uint8[sizeof(_curKeys)/sizeof(Uint8)];
}
void InputManager::update() {
memcpy(_oldKeys, _curKeys, sizeof(_curKeys)/sizeof(Uint8)); // this seems to work
std::copy(std::begin(_curKeys), std::end(_oldKeys), std::begin(_curKeys));
}
bool InputManager::pressed(SDL_Keycode code) {
return _curKeys[code];
}
bool InputManager::justPressed(SDL_Keycode code) {
return _curKeys[code] && !_oldKeys[code];
}
bool InputManager::justReleased(SDL_Keycode code) {
return !_curKeys[code] && _oldKeys[code];
}
In the main loop I update the InputManager instance by copying the current keyboard state and updating the current state. Since I'm relatively new to C++ I'm unsure of exactly the best way to copy the values from _curKeys to _oldKeys without using a for-loop. I can't just set _oldKeys=_curKeys because that just makes _oldKeys point to _curKeys. But memcpy seemed to work.
With this implementation justReleased is constantly true, no matter what key is pressed, and justPressed and pressed are always false.
Method 2 -Array of bools
// SDL_PollEvent() loop
case SDL_KEYDOWN: InputManager::keyDown(//event keycode);
case SDL_KEYUP: InputManager::keyUp(//event keycode);
The keyDown and keyUp functions just set keyArray[keycode] to true and false. In the InputManager update function I once again duplicate of the array, simulating "states". But with this implementation all three functions are always false.
Anyway
I hope that this question wasn't too incoherent, I tried to explain it as best as I could. I've found some forums where people had similar problems, the criticism always was that this kind of functionality isn't needed. I would disagree, a good use case for this would be, for example, a charge-up weapon in a game. At justPressed you start the charge, increment a charge counter while pressed is true, and at justReleased you fire the weapon.
If anyone has any pointers for me (no pun intended :P) that would be awesome.
std::copy(std::begin(_curKeys), std::end(_oldKeys), std::begin(_curKeys));
has wrong arguments. On top of that, only one of memcpy or std::copy is needed - after fixing, they should do exactly the same in this case. \$\endgroup\$