I've been working on an input handler, using SDL2 and C++. Right now I'm testing it with a Pong clone, but I want to be able to use it my next games. Right now it detects if a key is currently down or not, but I start running into issues when I try to see if a key was pressed or released that frame.
I'm using two arrays, one for the current state and another for the state the previous frame. Every update, I use memcpy to copy the new state to the old state, and then use SDL_PumpEvents to update the current array.
The issue is that this actually isn't keeping an array of the old keyboard state. Instead, the old and new arrays are always the same, so the keys are never able to be tagged as "pressed" or "released". (I did some debugging and can confirm that keyboardOld is changing) I'm sure this is an issue with memcpy and constant pointers and all of that fun stuff, I just don't have enough experience with them to figure out what's going wrong.
So, why are keyboardOld and keyboardNew always the same, even though I copy New to Old before updating New, and how can I fix it? Thanks in advance!
Here's the code:
Input.h
#ifndef Input_h
#define Input_h
#include <SDL.h>
#include <cstring>
#include <stdio.h>
class Input{
public:
enum keys{
A = SDL_SCANCODE_A,
B = SDL_SCANCODE_B,
C = SDL_SCANCODE_C,
D = SDL_SCANCODE_D,
E = SDL_SCANCODE_E,
F = SDL_SCANCODE_F,
G = SDL_SCANCODE_G,
H = SDL_SCANCODE_H,
I = SDL_SCANCODE_I,
J = SDL_SCANCODE_J,
K = SDL_SCANCODE_K,
L = SDL_SCANCODE_L,
M = SDL_SCANCODE_M,
N = SDL_SCANCODE_N,
O = SDL_SCANCODE_O,
P = SDL_SCANCODE_P,
Q = SDL_SCANCODE_Q,
R = SDL_SCANCODE_R,
S = SDL_SCANCODE_S,
T = SDL_SCANCODE_T,
U = SDL_SCANCODE_U,
V = SDL_SCANCODE_V,
W = SDL_SCANCODE_W,
X = SDL_SCANCODE_X,
Y = SDL_SCANCODE_Y,
Z = SDL_SCANCODE_Z,
UP = SDL_SCANCODE_UP,
DOWN = SDL_SCANCODE_DOWN,
LEFT = SDL_SCANCODE_LEFT,
RIGHT = SDL_SCANCODE_RIGHT,
};
void init();
void update();
void close();
//True if a key is pressed
bool keyDown(int key);
//True if the key was pressed this frame
bool keyPressed(int key);
//True if the key was released this frame
bool keyReleased(int key);
private:
//Length of keyboard arrays (given by SDL_getKeyboardState)
int length;
//State of keyboard last frame
Uint8* keyboardOld;
//State of keyboard this frame
const Uint8* keyboardNew;
};
#endif
Input.cpp
#include "Input.h"
void Input::init(){
keyboardNew = SDL_GetKeyboardState(&length);
keyboardOld = new Uint8[length];
}
void Input::update(){
std::memcpy(keyboardOld, keyboardNew, length);
SDL_PumpEvents();
}
void Input::close(){
delete keyboardOld;
keyboardOld = nullptr;
}
//Returns true if the key is currently pressed
bool Input::keyDown(int key){
return keyboardNew[key];
}
//Returns true if the key was pressed this frame
bool Input::keyPressed(int key){
return (keyboardNew[key] && !keyboardOld[key]);
}
//Returns true if the key was released this frame
bool Input::keyReleased(int key){
return (!keyboardNew[key] && keyboardOld[key]);
}
And the relevant code from the main program:
//Handle player input
input.update();
if(input.keyPressed(input.UP)){
player->y -=50;
}
if(input.keyReleased(input.UP)){
player->y -=50;
}
if(input.keyDown(input.DOWN)){
player->y +=1;
}
if(input.keyDown(input.LEFT)){
player->x -=1;
}
if(input.keyDown(input.RIGHT)){
player->x +=1;
}