Keyboard Input
Let’s start with the keyboard. MonoGame uses the KeyboardState
struct to represent the state of a keyboard. It is essentially a wrapper around an array of bits - one for each key in a standard keyboard. The indices of each key are represented by the Keys
enumeration (you can find a complete listing in the docs).
We get the current state of the keyboard with the static Keyboard
’s GetState()
method, which returns the aforementioned KeyboardState
struct. Thus, if we wanted to have current and prior keyboard states, we’d add fields to hold them:
private KeyboardState priorKeyboardState;
private KeyboardState currentKeyboardState;
And within our Update(GameTime gameTime)
method, we’d first copy the current (but now old) state to the prior variable, and then grab the updated state for the current variable:
public override void Update(GameTime gameTime)
{
priorKeyboardState = currentKeyboardState;
currentKeyboardState = Keyboard.GetState();
// TODO: Your update logic goes here...
base.Update(gameTime);
}
The KeyboardState
struct contains properties:
Keys
- an array of 256 bits, with each bit corresponding to a particular keyCapsLock
- a boolean indicating if the caps lock is onNumLock
- a boolean indicating if the num lock is on
But more often, we’ll use its method IsKeyDown(Keys key)
or IsKeyUp(Keys key)
, both of which take a Keys
value. For example, we can check if the escape key is pressed with:
if(currentKeyboardState.IsKeyDown(Keys.Escape))
{
// Escape key is down
}
And, if we need to determine if a key was just pressed this frame, we would use:
if(currentKeyboardState.IsKeyDown(Keys.I) &&
priorKeyboardState.IsKeyUp(Keys.I))
{
// The I key was just pressed this frame
}
Similarly, to see if a key was just released this frame, we would reverse the current and previous conditions:
if(currentKeyboardState.IsKeyUp(Keys.I) &&
priorKeyboardSate.IsKeyDown(Keys.I))
{
// The I key was just released this frame
}
Note that part of the reason we use a struct
instead of a Class
for our state is that a struct
is a value type, i.e. it allocates exactly the space need to store its data, and when we set it equal to a different struct instance, i.e.:
priorKeyboardState = currentKeyboardState;
What actually happens is we copy the bits from currentKeyboardState
over the top of priorKeyboardState
. This is both a fast operation and it allocates no additional memory - ideal for the needs of a game. This is also why so many of MonoGame’s data types are structs instead of classes.