Digital and Analog Input
There
are two types of values when dealing with user input analog and
digital. Digital input allows for two specific states. Examples of
digital input are the keys on a keyboard or the buttons on the Xbox 360
gamepad. The keys or the buttons are either pressed or they are
released. Analog input allows for a much wider range of values often
expressed in float values from –1 to 1 or 0 to 1. Examples of analog
input are the mouse location or the thumb stick location on the Xbox 360
gamepad.
Polling versus Event-Based Input
There are generally two
mechanisms to handle user input polling and input events. With polling,
input devices are queried or polled for their current state. The state
is then preserved in some type of object such as KeyboardState or MouseState.
These states do not change as the input device itself changes. To get
the latest state, the input device needs to be polled again. Often the
states of the current and previous frames are required when handling
user input utilizing polling.
Because of the game loop
nature of update and draw that games utilize, XNA Game Studio APIs
utilize polling methods to query the current state of each of the input
devices. The input devices are generally polled at the start of the
update phase of the game loop. The user input along with the elapsed
time that has occurred since the last update call is then used in game
play logic such as moving the players’ characters.
Event-based input systems are
utilized more in application development. For example, within a
Silverlight application, you can create an event that fires when the
mouse is clicked. The event code fires only when that condition occurs
and your code does not need to poll the mouse. This works well in
applications that utilize an event-based application model and generally
don’t have continuous loops running as in games.
The Many Keys Of A Keyboard
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,
rRin 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 1 contains the methods exposed by the Keyboard type.
Table 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:
if (currentKeyboardState.IsKeyDown(Keys.A))
{
// The A button on the keyboard is pressed
}
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:
KeyboardState lastKayboardState;
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:
lastKeyboardState = currentKeyboardState;
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:
if (currentKeyboardState.IsKeyDown(Keys.A) && lastKeyboardState.IsKeyUp(Keys.A))
{
// The A button was pressed this frame
}
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:
KeyState spacebarState = currentKeyboardState[Keys.Space];
if (spacebarState == KeyState.Down)
{
// Spacebar is pressed down this frame
}
else if (spacebarState == KeyState.Up)
{
// Spacebar is up this frame
}
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:
Keys[] pressedKeys = currentKeyboardState.GetPressedKeys();
foreach (Keys key in pressedKeys)
{
// Game logic to handle each key
}