1. Introduction
You now know the basics
of computer game programming. You know that a program is actually a
sequence of statements, each of which performs a single action. You have
seen that statements are held inside methods, each of which performs a
particular task, and that methods are held in classes along with data.
The program itself works on data values, which are held in variables of a
particular type, and the program can make decisions based on the values
that the variables have.
Now you are going to
expand your understanding to include how to receive input from the
outside world so that games can actually react to what the player does.
You shall see that once we have done this, a number of possibilities
open up, and you can create some truly silly games, including "Color
Nerve," "Mind Reader," "The Thing That Goes Bump in the Night," and
"Gamepad Racer."
Before you start looking
at gamepads, though, you need to decide how the program will actually
work. Consider the following statement of C# from the previous
mood-light program, which is part of the Update method:
if (redCountingUp) redIntensity++;
This is one of the tests that controls the intensity of the red part of the color. What it is saying is "If the Boolean value redCountingUp is True, increase the value of redIntensity by 1." The statement is processed each time Update is called (at the moment that is 60 times a second), so this means that if redCountingUp is True, the red intensity of the screen gets progressively brighter over time.
You want to write some code that says, "If the red button on Gamepad 1 is being pressed, increase the value of redIntensity
by 1." Then, if the player holds down the button, the screen gets
redder. So all you have to do is change this test to read the button on
the gamepad, and you can create a user-controlled light easily.
2. Reading a Gamepad
The gamepads are
actually very complex devices. They are connected to the host device
either by a universal serial bus (USB) cable or by a wireless
connection. As far as you are concerned, the way that programs work with
gamepads does not depend on how they are connected. The connection to a
gamepad can be used to read the buttons and joysticks and can also be
used to send commands to the gamepad—for example, to turn the vibration
effect on and off. The Xbox and XNA provide support for up to four
gamepads connected simultaneously. The Zune has a single gamepad with
two buttons that can be used for input. It is used in exactly the same
way as the Xbox gamepad.
2.1. Gamepads and Classes
The gamepad information is represented in XNA by means of a class called GamePadState.
The job of this class is to provide the connection between the program
and the physical gamepad that the player is holding. To understand how
you are going to use this, you have to learn a bit more about how
classes work.
A class contains data (variables that can hold stuff) and methods (code
that can do stuff). You can think of a class as an office, with a desk
holding the variables and people acting as the methods. Figure 1 shows the office plan for the class Game1, which you have seen is the basis of an XNA game.
This class contains some
variables on the desk (in this case, the background color intensities)
and two methods, which we have called Mr. Draw and Mrs. Update. Each
method has a corresponding telephone. Programs can place calls to the
telephones to request that the method perform the required task.
Note:
Our
Great Programmer has been reading these notes and finds them quite
amusing. She says that classes are not exactly like offices, but she
thinks that for the purpose of getting an understanding of how programs
are constructed, it is okay to regard them as such.
When an XNA game starts, the XNA system makes an instance of the Game1 class that it then can ask to Draw and Update.
When an instance of a class is created, the instructions for the
methods that it contains are loaded into memory and space is set aside
for the data variables that the instance holds.
The class files that you
write give the plans for the class so when the program runs, instances
of each class can be created. In real life, you would make a game office
by building a room, putting a desk and some telephones in the room, and
then hiring a Mr. Draw and a Mrs. Update. The process of making an
instance of a class is similar. However, to save memory, the running
program uses only one copy of the method code, which is shared among all
the instances of a class.
Note:
It is important to
remember that this happens when a program runs. The process of creating
instances of classes is not performed by the compiler. The job of the
compiler is to convert your C# source code into instructions that the
target device runs. By the time that your program has control, the
compiler has done its job, and the computer is just running the machine
language output that the compiler produced.
2.2. Finding a Gamepad
XNA also looks after a lot of other things when a game is running, one of which is the GamePad
class connected to all the gamepads. You don’t have to know how the
gamepad is actually connected; for all you know, it might use tiny
pixies traveling up and down the wires carrying pixie notes written on
pixie paper saying "Master has pressed the Red Button," but then again
it might not. Figure 2 shows how the GamePad class would look if it were an office.
The GamePad class contains a method called GetState, which gets the state of one of the gamepads. When GetState
is called, it looks at one of the gamepads, reads its settings, and
then sends information back for use in the statement it was called from.
The GetState method is supplied with a parameter that identifies the gamepad to be read. A parameter
is a way that a call can give information to a method. You have seen
these before; in your very first programs, you were passing Color parameters into the Clear method to select the color of the screen that you wanted.
In the case of the GetState
method, the parameter identifies the gamepad that you want to read. If
you are thinking in terms of offices, you can think of a parameter as
part of the instructions that come down the telephone. When the phone
rings and Mr. GetState answers it, he is asked, "Get me the state of Gamepad 1." The information about the state of the gamepad is sent back in a GamePadState structure, which is shown in Figure 3.
You can think of this as a
set of items filled in on a form if you wish, but actually it is a C#
structure that contains the data members shown in Figure 3, as well as some other data.
So, if Mrs. Update wants to know the state of one of the gamepads on the Xbox, she calls the GetState method in the GamePad
class and asks, "Can you give me the state of the gamepad for Player 1,
please?" Mr. GetState jumps up, fills in a "GamePadState" form, and
sends it back to her. Figure 4 gives the breakdown of the C# statement that gets the state of a gamepad into a variable of type GamePadState.
3. Testing the Gamepad Status
Now that you have the status, you can use it in the program to see if a button has been pressed. Figure 5 shows the breakdown of the C# statement that will perform the test.
This compares the state of the red button B with the value ButtonState.Pressed. If the two are equal, this means that the button is down, and the Update
method must make the red intensity bigger. You can then use the same
principle to manage the blue and green values, which means that you now
have an Update method that looks like the following:
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
GamePadState pad1 = GamePad.GetState(PlayerIndex.One);
if (pad1.Buttons.B == ButtonState.Pressed) redIntensity++;
if (pad1.Buttons.X == ButtonState.Pressed) blueIntensity++;
if (pad1.Buttons.A == ButtonState.Pressed) greenIntensity++;
base.Update(gameTime);
}
The only problem with the Update
method described here is that the program doesn’t handle the yellow
button yet. When the yellow button is pressed, the program needs to
increase the green and the red intensities; that is, it must perform two
statements if the condition is true. It turns out that doing so is very
easy; you can just put the two statements into a block that is
controlled by the condition, as shown here:
if (pad1.Buttons.Y == ButtonState.Pressed)
{
redIntensity++;
greenIntensity++;
}
You have seen blocks before; the body of a method (the bit that does the work) is a block. In C# terms, a block
is a number of statements that are enclosed in curly braces. The code
shown here performs both statements if the condition is true because
they are in a block controlled by the condition.
Note:
Our Great Programmer tends to use blocks after if
conditions even when she doesn’t actually need to. She says that it
makes the program text clearer and that it is much easier to add extra
statements later if you need to.
If you put the preceding statements into the Update method of one of your earlier Mood-Light programs, you get compiler warning messages because the new version of Update
doesn’t use all the variables that were created for previous versions
of the program. To get rid of these warnings, you must delete the
statements that create the unused variables.
The Great Programmer doesn’t like it when programs have variables in
them that are not used. She says this looks unprofessional, and I agree
with her.
4. Zune Buttons
You can run this
program on a Zune. However, it doesn’t have colored buttons—the Play
button is the same as button B (Red) on a gamepad, and pressing the
center of the joypad is the same as pressing A (Green), but the other
buttons are not supported. However, you can create a Moodlight for the
Zune by using the Dpad inputs as follows:
if (pad1.DPad.Left == ButtonState.Pressed) blueIntensity++;
if (pad1.DPad.Right == ButtonState.Pressed) redIntensity++;
if (pad1.DPad.Down == ButtonState.Pressed) greenIntensity++;
if (pad1.DPad.Up == ButtonState.Pressed)
{
redIntensity++;
greenIntensity++;
}
The Zune control pad is
mapped onto the Dpad on the gamepad, so this code also allows the
MoodLight to be controlled by the Dpad on a gamepad.
Game Idea: Color Nerve
Every now and then, we are
going to try out a game idea. These start out very simply and then
build up to more complicated and interesting games. You can use the
Manual MoodLight code to create your first game. You noticed that if you keep making a value bigger, there comes a point
where it won’t fit in the memory store allocated for it, and then it
overflows. This is what caused the screen to go from bright white to
black. However, you can use this to create our first "Very Silly Game."
Color Nerve is a game for
two or more players. The players take turns pressing one or more
buttons on the gamepad. (The other players must watch carefully to make
sure that they actually do press at least one button.) Each player can
press as many buttons as he wants for as long as he wants during his
turn, but if the screen changes suddenly (because one of the color
values has gone from 255 to 0), he is out, and the game continues. The
last player left in the game is the winner.
This
game can be very tactical. Players can press the buttons for very short
times, or at the start of the game, they can show their nerve by
holding the buttons down for longer periods, trying to cause problems
for the next player. They can also try to work out which color has
wrapped around so that they can press that button when it is their turn.
|