The
communication between the gamepad and the game works in both
directions. Not only can you read buttons on the gamepad, but also you
can send commands to the gamepad to turn on the vibration motors. Again,
you don’t have to know exactly how these messages are delivered; all
you need to know is the features of XNA that are used to control this
vibration effect.
This means you can make
your Color Nerve game even more exciting by making the gamepad vibrate
when the intensity values are getting close to their limits. It is
interesting how features like this can enhance even a simple game. You
will be using the vibration effect on the gamepads quite a lot in the
next few games.
1. Controlling the Vibration of a Gamepad
The GamePad class provides a method called SetVibration that lets a program control the vibration motors:
GamePad.SetVibration(PlayerIndex.One, 0, 1);
The SetVibration
method uses three parameters. The first one identifies which gamepad
you want to vibrate. The second parameter is a value between 0.0 and 1
that controls the vibration of the left motor. The bigger the number,
the more the gamepad vibrates. The third parameter controls the right
motor in the same way as the left one. The statement shown here would
set the right motor of Gamepad 1 vibrating at full speed. The left motor
is the low-frequency vibration, and the right motor is the
high-frequency vibration.
If you think of the GamePad
class/office having a man called Mr. SetVibration, this means that he
would be told which gamepad to vibrate and the settings for the left and
right motors. Once the method has been called, the gamepad starts to
vibrate, and it keeps vibrating until you call the method again to
change its setting. In other words, you can think of the SetVibration
method as a switch that can be set to a number of different positions.
Initially, both of the gamepad motors are set at 0, which means no
vibration.
2. Testing Intensity Values
The game needs to decide
when to turn on the vibration. To do this, it must test the intensity
values and turn on the vibration motor if any of them is getting too
large. The program can decide to turn on the motors if any of the red,
green, or blue intensity values is greater than 220. To do this, the
program must test the intensity values as follows:
if (redIntensity > 220)
{
GamePad.SetVibration(PlayerIndex.One, 0, 1);
}
This code shows another
form of condition. In the previous examples, the conditions have been
checking to see if two values are equal. This code tests if one value is
greater than another. The greater-than sign (>) is another logical
operator. Placed between two values, it returns true if the value on the left is greater than the value on the right and false if not. That is exactly what you want.
Using the preceding
code, the gamepad starts to vibrate using the right motor when the red
intensity value goes above 220. If you add this code to the Update
method in the Color Nerve game, you find that if you increase the red
value, the gamepad starts to vibrate. Unfortunately, our program has a
bug. When the red intensity value returns to 0, the vibration does not
stop. You need to add some code that turns off the motor when the intensity value is less than 220. It turns out that this is very easy to do—you can add an else part to the condition:
if (redIntensity > 220)
{
GamePad.SetVibration(PlayerIndex.One, 0, 1);
}
else
{
GamePad.SetVibration(PlayerIndex.One, 0, 0);
}
The statement after the else is performed if the condition is found to be false. (You can add an else part to any if
condition that you create.) This means that when the red intensity
value returns to 0, the vibration stops. You can extend the tests using OR so that the program tests all the intensity values:
if ( redIntensity > 220 ||
greenIntensity > 220 ||
blueIntensity > 220 )
{
GamePad.SetVibration(PlayerIndex.One, 0, 1);
}
else
{
GamePad.SetVibration(PlayerIndex.One, 0, 0);
}
Now the vibration is
controlled by all the intensity values. As an improvement to the game,
you might want to experiment with different kinds of vibration for
different colors, perhaps by using the low-frequency motor as well. This
is controlled by the other value in the call of SetVibration:
GamePad.SetVibration(PlayerIndex.One, 1, 0);
The line of code shown
here turns on the low-frequency vibration. You might also want to
experiment with the thresholds at which the vibration starts.
The program still has one
more problem. If you run it and make the gamepad vibrate, when the
program finishes, the gamepad doesn’t always stop vibrating. You need to
add code that stops the vibration when the game ends. The game stops
when the player presses the Back button on the gamepad. The test for
this is in the Update method. If the Back button is pressed, the Exit method is called to stop the game:
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
The Exit
method removes the game display and shuts the game down in a tidy
fashion. What the program must do is turn off the gamepad motors before Exit is called. To do this, the program needs to perform more than one statement if the Back button is pressed, so we need another block:
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
GamePad.SetVibration(PlayerIndex.One, 0, 0);
this.Exit();
}
Now, when the player presses the Back button to end the program, the vibration motors are turned off.
Note:
The Great Programmer says
that if you are in a situation where you are not sure whether something
is always the case, you should add code to remove all possible doubt.
Testing the vibration behavior described in this section, I discovered
that the gamepad is left vibrating on earlier versions of XNA, but not
on some newer ones. To make absolutely sure that the vibration stops
regardless of the version of XNA under which your game runs, you should
include the code to stop the vibration yourself.
Game Idea: Secret Vibration Messages
Once you see that it is
easy to read gamepad buttons and drive the motors, you can start to have
more fun with XNA, particularly with wireless gamepads. You can create
mind-reading games where your assistant seems to know exactly what you
are thinking. What the audience doesn’t know is that both of you are
holding Xbox gamepads in your jacket pockets and using them to send
signals back and forth using the vibration feature. The code to do this
is actually very simple, and you should be able to understand what it
does:
protected override void Update(GameTime gameTime) { // Allows the game to exit if(GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) { GamePad.SetVibration(PlayerIndex.One, 0, 0); GamePad.SetVibration(PlayerIndex.Two, 0, 0); this.Exit(); }
GamePadState pad1 = GamePad.GetState(PlayerIndex.One); GamePadState pad2 = GamePad.GetState(PlayerIndex.Two);
if (pad1.Buttons.A == ButtonState.Pressed) { GamePad.SetVibration(PlayerIndex.Two, 0, 1); } else { GamePad.SetVibration(PlayerIndex.Two, 0, 0); }
if (pad2.Buttons.A == ButtonState.Pressed) { GamePad.SetVibration(PlayerIndex.One, 0, 1); } else { GamePad.SetVibration(PlayerIndex.One, 0, 0); }
base.Update(gameTime); }
The Update
method reads the A button on the gamepad for Player 1. If this is
pressed, it turns on the fast vibration motor in the gamepad for Player
2. It then repeats the process the other way, sending signals from
Gamepad 2 to Gamepad 1. This gives you a way in which you can send
wireless signals from one gamepad to another. Note that both conditions
have else parts so that if the button is not pressed, the vibration is turned off.
You could also use this
for practical jokes; for example, just leave a gamepad underneath your
victim’s bed and then wait until he turns the light off and settles
down. Then give the vibration a quick blast for the maximum scare
factor. Just don’t blame me if you never get the gamepad back!
|
Game Idea: Gamepad Racer
The final game idea in
this article is really silly, but it can be great fun. The first thing
you need to do is find a large, smooth table. Put a couple of books
under the legs at one end so that the table is sloping, not horizontal.
If you put a wireless Xbox gamepad at the top of the table and make the
gamepad vibrate, it slides down the table toward the other end. You may
need to experiment with the angle, but I’ve found that with care,
you can arrange things so that a gamepad takes around 30 seconds to
slide all the way down the table with vibration at full power. If you
line up four gamepads on the top of the table, players can pick the one
they think will win, and then you can race them down the slope.
The code for this game is very simple indeed; the Update method just turns on all the vibration motors in the gamepads:
protected override void Update(GameTime gameTime) { // Allows the game to exit if(GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) { GamePad.SetVibration(PlayerIndex.One, 0, 0); GamePad.SetVibration(PlayerIndex.Two, 0, 0); GamePad.SetVibration(PlayerIndex.Three, 0, 0); GamePad.SetVibration(PlayerIndex.Four, 0, 0); this.Exit(); }
GamePad.SetVibration(PlayerIndex.One, 1, 1); GamePad.SetVibration(PlayerIndex.Two, 1, 1); GamePad.SetVibration(PlayerIndex.Three, 1, 1); GamePad.SetVibration(PlayerIndex.Four, 1, 1);
base.Update(gameTime); }
The only complication is
that when the game ends, you must turn off all the vibrations. Put all
the gamepads at the top of the slope and then run the program. Press the
Back button on Gamepad 1 to stop the game.
|
Note:
By carefully tuning
vibration values it is possible to "sabotage" gamepads so that the same
one wins each time. Note that I do not condone such behavior.