5 min read

Basic Keyboard Input

Overview

Player input in a game is essential. Without it, our game is simply an animation. In this tutorial, we will look at the basics of getting player input from the keyboard. There is more to this than we will cover in this tutorial, but this will cover the basics of keyboard input.

Keyboard Input

Keyboard input is actually quite easy to do. It should be fairly easy to add it into any code that you are working on. For the purposes of this tutorial, I am going to start with a new project for simplicity. In your case, it might be easier to add it to one of your own projects–maybe one where you want player input!

Usually the best place to check for player input is in the Update() method of your game. So for starters, let’s go there and add the following line of code:

KeyboardState state = Keyboard.GetState();

The Keyboard class has a method that returns the current state of the keyboard whenever it is called. The current state of the keyboard is stored in a KeyboardState object. In this line of code, we are calling our current state state.

So now that our state variable contains the current state of the keyboard, let’s look at how we could use it. To determine whether a key is pressed down or not, we can use the method IsKeyDown() in the KeyboardState class, as shown below:

bool leftArrowKeyDown = state.IsKeyDown(Keys.Left);

Or we could use it as part of an if-statement, to do something if the key is pressed down:

if(state.IsKeyDown(Keys.Left))
{
    // do something here
}

We can see in these two examples that IsKeyDown() returns a bool (true or false). For its parameter, we pass in something in the Keys enumeration. This enumeration has lots of keys available. Sometimes you have to hunt around for the key you are looking for, but it is almost guaranteed to be there.

Checking for Key Presses

We’ve now seen how to do the most basic form of keyboard input. However, you may have noticed that the code we used before:

if(state.IsKeyDown(Keys.Left))
{
    // do something here
}

will return true at every update that the key was pressed, which is going to be something like 60 times per second, for as long as the user has the key down. If you are trying to do something like fire a bullet when a key is pressed, the person could press the key for half a second, and 30 bullets would be fired.

To avoid this, we can do something a little bit more advanced. We will save the old keyboard state, temporarily, and use it to help us decide whether to actually fire or not. We can fire (or anything else) only when the key was up in the old state and pressed in the new state–that is, only when the key is first pressed.

Let’s start by making an instance variable in our class to hold the old keyboard state. Add the following line to the top of your game class as an instance variable:

private KeyboardState oldState;

Next, in the Update() method, add the following code to retrieve the new state, handle it, and then update the old state:

KeyboardState newState = Keyboard.GetState();  // get the newest state

// handle the input
if(oldState.IsKeyUp(Keys.Left) && newState.IsKeyDown(Keys.Left))
{
    // do something here
    // this will only be called when the key is first pressed
}

oldState = newState;  // set the new state as the old state for next time

In this code, we will only run the stuff inside of the if statement when the key was first pressed.

Now before we wrap this section of the tutorial up, it might be a good idea to mention that in addition to the IsKeyUp() and IsKeyDown() methods in the KeyboardState class, it also has a method called GetPressedKeys() that can be used to get a list of all of the keys that are currently pressed. We can use it like below:

Keys[] pressedKeys = state.GetPressedKeys();

Key Modifiers

Sometimes, it is nice to be able to determine whether the modifier keys are being pressed as well. For example, you might want to do something different when the user presses Ctrl+C instead of just C . This is really easy to do, since even these modifier keys are just simply keys to the KeyboardState class. So we could do this with the code below:

if((state.IsKeyDown(Keys.LeftControl) || state.IsKeyDown(Keys.RightControl)) &&
        state.IsKeyDown(Keys.C))
{
    // do something here for when Ctrl-C is pressed
}
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace KeyboardInput
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        // Stores the most recent keyboard state.
        private KeyboardState oldState;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            //-----------------------------------------------------------------------------

            KeyboardState state = Keyboard.GetState();

            //-----------------------------------------------------------------------------

            bool leftArrowKeyDown = state.IsKeyDown(Keys.Left);

            //-----------------------------------------------------------------------------

            if (state.IsKeyDown(Keys.Left))
            {
                // do something here
            }

            //-----------------------------------------------------------------------------

            KeyboardState newState = Keyboard.GetState();  // get the newest state

            // handle the input
            if (oldState.IsKeyUp(Keys.Left) && newState.IsKeyDown(Keys.Left))
            {
                // do something here

                // this will only be called when the key if first pressed
            }

            oldState = newState;  // set the new state as the old state for next time

            //-----------------------------------------------------------------------------

            Keys[] pressedKeys = state.GetPressedKeys();

            //-----------------------------------------------------------------------------

            if ((state.IsKeyDown(Keys.LeftControl) || state.IsKeyDown(Keys.RightControl)) &&
                    state.IsKeyDown(Keys.C))
            {
                // do something here for when Ctrl-C is pressed
            }


            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            base.Draw(gameTime);
        }
    }
}