The Many Keys Of A Keyboard (XNA Game Studio 4.0 Programming)

The keyboard is one of the most widely used input devices for games. Because almost every Windows PC has a keyboard along with the mouse, they are the standard input devices for Windows PC gaming.With well over 100 keys, the keyboard has the most input buttons of any input device supported by XNA Game Studio.You use keyboards in games for controlling movement and for game scenarios with a large number of actions. For example, in a real-time strategy game, a player can use the keyboard to issue commands to units in the game much quicker than if the player had to click an onscreen icon.

Keyboard input is not limited to just the Windows platform. XNA Game Studio also supports reading keyboard input on Xbox 360 and Windows Phone.The Xbox 360 supports two types of keyboard devices. Users can plug USB keyboards directly into Xbox 360 as they would an Xbox 360 gamepad.The USB keyboard then works normally as if it were attached to a Windows PC.The other keyboard available on the Xbox 360 is the chatpad.The chatpad is a mini keyboard that attaches directly to the bottom of an Xbox 360 gamepad.

Note

Chatpad input is available only on Xbox 360. Although Xbox 360 controllers work on Windows, the chatpad keyboard input does not.

Most players do not have a chatpad or keyboard attached to their Xbox 360, so when developing your game for Xbox 360, you should not require these input devices.

XNA Game Studio also supports keyboard input on some Windows Phone devices. Some Windows Phone devices come with a hardware keyboard. Not all devices have a hardware keyboard, so your game should not require keyboard input if targeting the Windows Phone platform.


Reading Keyboard State

As we have discussed, reading input devices in XNA Game Studio is a matter of requesting the current state of the device.That state can then be used for updating actions in your game. In XNA Game Studio, the keyboard is represented by the Keyboard class. The main method the Keyboard class contains that we use is Keyboard.GetState() .This method returns the current state of the keyboard.The keyboard state is stored in the KeyboardState structure.Table 12.1 contains the methods exposed by the Keyboard type.

Table 12.1 Methods of KeyboardState

Method

Description

GetPressedKeys

Returns array of keys that are pressed

IsKeyDown

Returns true if the provided key is currently pressed

IsKeyUp

Returns true if the provided key is not currently pressed

To read the current state of the keyboard, use the following line of code: KeyboardState currentKeyboardState = Keyboard.GetState();

Reading Xbox 360 Chatpad Input

Because each Xbox 360 gamepad might have a chatpad attached, it is possible that more than one player can enter keyboard input. To read the keyboard input for a specific player,use the Keyboard.GetState(PlayerIndex playerIndex) overload and specify the player index.

Now that the current state of the keyboard is saved into the KeyboardState structure, you can read what keys were pressed at the time that Keyboard.GetState() was called. KeyboardState contains a number of methods to determine the current state of a specific key.To check whether a specific key is currently pressed, use the KeyboardState. IsKeyDown(Keys key) method.This method takes an enum value of the type Keys.The Keys enum contains all of the readable keyboard keys using XNA Game Studio. Keys contains values for normal alphanumeric keys you expect such as the letter A or the number 1.The Keys enum also contains values for more rarely used keys that exist only on some keyboards such as the application launch and media buttons. To determine whether a specific key is currently pressed, use the following lines of code:

tmp14258_thumb

Note

User input and handling often, but not always, occurs in the game’s Update method. Reading the current state of an input device can happen anywhere in your game code.

If the player presses the A key over multiple frames, the IsKeyDown method will continue to return true.This means that the previous bit of code continues to be true and does not require that the player press the key each frame. IsKeyDown returns true if the key was pressed when the state was polled using Keyboard.GetState. It does not express if the key was pressed in a previous frame.This can become a problem because often in games, it is desirable for an action to happen only once per key press. If you want an action to happen only once per key press, you need to store the KeyboardState in a previous frame.

In your game class, define the following member variable:

tmp14259_thumb

At the end of the Update method where you have read the current state of the keyboard, set the last frame state to the current state:

tmp14260_thumb

This preserves the previous frame’s keyboard state so you can use it in the following frame.To determine whether a key is pressed in the frame, use the IsKeyDown method along with the IsKeyUp method exposed by KeyboardState:

tmp14261_thumb

Because you know the key is pressed in this frame and is not pressed in the previous frame, you know it is pressed in this frame for the first time and you can execute the appropriate action.

KeyboardState provides an indexer overload that enables you to determine the KeyState for a particular key. The following lines of code check the state of the spacebar key:

tmp14262_thumb

 

 

 

tmp14263_thumb

KeyboardState provides the capability to return an array of the Keys pressed.The following lines of code get an array of Keys and loops over them:

tmp14264_thumb

Moving Sprite Based on Keyboard Input

Now that we covered how to read the current state of the keyboard and can determine whether a key is pressed or released, let’s move a sprite around the screen using the keyboard. First, you need to declare some member variables to store your sprite texture, the sprites position, and the last keyboard state:

tmp14265_thumb

Next, load a texture to use as your sprite. In the game’s LoadContent method, add the following line of code:

tmp14266_thumb

Now, you are ready for some keyboard input. In the game’s Update method, you need to store the current state and move the sprite’s position based on the arrow keys, as follows:

tmp14267_thumb

 

 

tmp14268_thumb

Whenever the arrow keys are pressed, you move the sprite in the appropriate direction. Notice that "up" corresponds to moving the sprite in the negative Y direction because values for Y increase when moving down the screen.

When you move the sprite, you don’t move by a constant value. Take the elapsed game time into account. Each frame can take a different amount of time to complete. If a constant movement amount is used to update the position of the sprite, it might appear to shudder as it moves across the screen. Correct this using the GameTime.ElapsedGameTime property. You previously used the elapsed time in total seconds.This means pressing the right arrow for one second moves the sprite 100 pixels to the right no matter how many frames happen over that second.

Note

Older PC video games didn’t always take into account the elapsed time when animating and moving sprites. As computing power of PCs increased, these games were able to run faster and so did the animations and speed of the games, making some of the game unplayable.

Finally, you need to display the sprite on the screen using the position you have been updating.To display the sprite, add the following lines of code to your game’s Draw method:

tmp14269_thumb

Now if you run your game, you can control the sprite on the screen using the keyboard arrow keys. Congratulations—you have created your first XNA Game Studio interactive game.This simple game should look similar Figure 12.1.

Onscreen Keyboard

If your goal is to gather user text input, the Keyboad class is not the best solution. If you try to implement text entry using the Keybord state APIs, you run into a number of issues such has handling the current shift state of the keyboard and making sure to call GetState quick enough that you don’t miss a single key press.The Keyboad API is not designed for text entry (see Figure 12.2).

For text entry, use the Guide.BeginShowKeyboardInput method. If you are familiar with C#, notice that BeginShowKeyboardInput is an asynchronous method.This means that when you ask to show the keyboard, this method quickly returns but that does not mean the keyboard has been shown or that the user has entered text into the keyboard. For your game to continue running, it needs to handle a method that takes a number of frames to return. BeginShowKeyboardInput returns an IAsyncResult object.This object is used each frame to check on the state of the call to BeginShowKeyboardInput.

Sprite controlled by user keyboard input

Figure 12.1 Sprite controlled by user keyboard input

Onscreen keyboard in the Windows Phone emulator

Figure 12.2 Onscreen keyboard in the Windows Phone emulator

If the IsCompleted property of the result is true, that means the call has completed and that you can request the string from the keyboard input.This is done calling Guide. EndShowKeyboardInput passing in the result.The method returns the string the user entered. The string might be null because the user can cancel the onscreen keyboard.

To add the onscreen keyboard to your game, store the async result over multiple frames.You also need to store the string returned. Add the following members to your game class:

tmp14272_thumb

We cover the Guide.BeginShowKeyboardInput method, sometimes called gamer services, later in the topic. The important point to know now is that your game constructor needs to initialize gamer services on Windows and Xbox 360 to use the onscreen key-board.This is done by adding the GamerServicesComponent to the Components list of your game. On Windows and Xbox, add the following line of code at the end of your game’s constructor:

tmp14273_thumb

Next, check for a spacebar press. If the user presses the spacebar and the onscreen keyboard is not already visible, you start to display the keyboard. Add the following lines of code to your game’s Update method:

tmp14274_thumb

In the previous code, check the keyboard async result to make sure you are not already waiting for a previous call.Then, if the spacebar is pressed, you make a call to BeginShowKeyboardInput.The first parameter is the PlayerIndex you want to have control of the onscreen keyboard.This can be only PlayerIndex.One for the Windows and Windows Phone platforms, but on Xbox 360, up to four players can play a game and you might want player three to enter his or her character’s name. In this case, player three should be the one controlling the onscreen keyboard. The next three parameters are string values representing the title, description, and default text to display. We cover the last two values a little later.

Now that you asked for the keyboard to display, it should display when the user presses the spacebar. But when a user enters text or cancels the keyboard, the return value is thrown away.To get the result of what the user enters into the keyboard, you need to call Guide.EndShowKeyboardInput. Calling this method blocks until the previous call to BeginShowKeyboardInput completes, so first check whether the call is complete.After the code you just added, place the following lines of code:

tmp14275_thumb

Notice that the EndShowKeyboardInput call takes the IAsyncResult from the BeginShowKeyboardInput call and returns the string entered by the user.This string can be null if the user canceled the onscreen keyboard.

In the previous code, you use the IAsyncResult from the BeginShowKeyboardInput call to check whether the call completed each frame. Instead of checking the status of each frame, you can use an AsyncCallback method that is called after the method completes. To use the callback method, add the following method to your game:

tmp14276_thumb

After the BeginShowKeyboardInput is complete and the user has entered text, this method is called. Similar to the previous example, you then call EndShowKeyboardInput and check the resulting string.To have BeginShowKeyboardInput use the callback, change the call to look like the following:

tmp14277_thumb

You no longer need to store the IAsyncResult because the StoreKeyboardResult method is called after the user has completed entering text.

The last parameter of BeginShowKeyboardInput is used to pass in an object to be stored in the IAsyncResult.AsyncState property.This can be useful when you need a specific object after the operation is completed. For example, if you are asking a user to enter his or her character name and you want to store the result in your game’s specific Character class, you can pass the user’s instance of that Character class into BeginShowKeyboardInput and when the call completes, use the IAsyncResult. AsyncState property to access the instance of the Character class.

Next post:

Previous post: