8_Lecture - lonettataylor

Timers
COMPUTER PROGRAMMING 2
Game Idea: Mob Reaction Timer
 Use a timer variable to keep track of time and a variable
for each player to measure the reaction time of that
player.
 Those variables are declared in the following code:
// Game World
int timer;
// Gamepad 1 scores
int ascore1;
int bscore1;
int xscore1;
int yscore1;
Game Idea: Mob Reaction Timer
 The timer starts counting up from zero when the
sound plays.
 Each time that XNA calls the Update method, the
value in timer is increased by one and the program
checks to see if the player has pressed his or her
button.
 If the button has been pressed, the value of the timer
is copied into the score variable for that button.
 The player with the lowest value is the winner.
Game Idea: Mob Reaction Timer
 The first problem we have to solve is how to start the
game.
 If the sound is produced as soon the game begins, the
player who starts the game has an obvious advantage.
 One way to make this work is to make the timer a
negative number when the game starts and increase it
each time Update is called.
 When it reaches the value 0, the sound is played and the
game starts counting
Game Idea: Mob Reaction Timer
 Each time Update is called, the flow in Figure
8-1 is performed.
 If the Start button is pressed, the timer variable
is set to –120.
 Each time Update runs, the value in timer is
made one bigger.
 When timer reaches zero, the sound is played.
 When a button press is detected, the program
copies the current value of timer into the score
for that button.
 If a player presses a button before the sound
has been played, he or she has a negative timer
value.
 The player who gets the smallest positive value
is the winner.
Game Idea: Mob Reaction Timer
protected override void Update(GameTime gameTime)
{
pad1 = GamePad.GetState(PlayerIndex.One);
if (pad1.Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
// start a new game
if (pad1.Buttons.Start == ButtonState.Pressed)
{
timer = -120;
ascore1 = 0;
bscore1 = 0;
xscore1 = 0;
yscore1 = 0;
}
timer++; // update the timer
// play the sound at the start of the game
if (timer == 0)
{
dingSound.Play();
}
// if A is pressed copy the timer
if (oldpad1.Buttons.A == ButtonState.Released && pad1.Buttons.A == ButtonState.Pressed)
{
ascore1 = timer;
}
// repeat for buttons B, X and Y
oldpad1 = pad1;
// repeat for gamepads 2, 3 and 4
base.Update(gameTime);
}
Reaction Timer Bug
 If you look at the code in the Update method, you
find that there’s nothing to stop a naughty player
from pressing his or her button lots of times.
 There’s no penalty for pressing the button before the
sound plays because the player can just press the
button again.
 You’ve designed the game without allowing for the
fact that players might cheat
Possible Solutions to the Bug
 The problem occurs because you’re not detecting
when the player releases the button as well as when
it’s pressed.
 The problem occurs because you should be using
level detection on the buttons, not edge detection.
 The problem occurs because you should register only
the first press of the button.
 The problem occurs because you need to reset the
gamepad after it’s been read.
Which Solution is Best?
 The problem occurs because you’re not detecting
when the player releases the button as well as when
it’s pressed.
 The problem occurs because you should be using
level detection on the buttons, not edge detection.
 The problem occurs because you should
register only the first press of the button.
 The problem occurs because you need to reset the
gamepad after it’s been read.
Reaction Timer Bug Fix
 The program works by copying the value of the timer
into the score for each player.
 When the Start button is pressed, the program loads
zero into the score values for each of the players.
 The very first time the player presses his or her
button, the zero is replaced with a time value.
 Next time he or she presses the button, the score is
not zero, so you should not update this value.
Reaction Timer Bug Fix
// if A is pressed and ascore1 is 0 copy the timer
if (oldpad1.Buttons.A == ButtonState.Released &&
pad1.Buttons.A == ButtonState.Pressed &&
ascore1 == 0)
{
ascore1 = timer;
}
Finding Winners Using Arrays
XNA GAME STUDIO 4.0
Creating an Array
 A variable that holds a list of values is called an array.
 Arrays can be declared and initialized just like any other
C# variable:
dataType [] arrName = new dataType[size];
 Example
int[] scores = new int[4];

This declares an array variable called scores that can refer to onedimensional integer arrays and makes it refer to a new 4-element
array instance.
Creating an Array
 You can think of an array as a row of numbered
boxes, each of which can hold a single value.
 A single “box” in an array is called an element.
 Note that the first element is at the index position 0.
 The index position can also be called a subscript.
Using Data in an Array
 Example of using an array.
if (oldpad1.Buttons.A == ButtonState.Released &&
pad1.Buttons.A == ButtonState.Pressed && scores[0] == 0)
{
scores[0] = timer;
}
 This code uses the first element in the array, scores[0],
instead of a variable called ascore1.
 You can use scores[1] as bscore1, the score for the B
button on gamepad 1 and so on.
Using Data in an Array
 You can use a for loop construction that takes the value of
i from 0 to 3 (remember that when the value of i reaches 4, the
test “i less than 4” fails and the loop stops).
 The value of i is used as a subscript for the array access.
for ( int i = 0; i < 4 ; i++ )
{
scores[i] = 0;
}
 If you step outside what are called the bounds of an array,
your program is stopped in its tracks by an exception because
this is just not allowed to happen in a proper language like C#.
Scanning an Array
 You use an array to help you find the best score.
 You can’t say to the C# compiler, “Look along the
row and find me the winner.”
 You will have to provide code.
Scanning an Array
int winningValue = 120;
for (int i = 0; i < 16; i++)
{
if (scores[i] > 0)
{
if (scores[i] < winningValue)
{
winningValue = scores[i];
}
}
}
string winnerName;
if ( scores[0] == winningValue )
{
winnerName = "Gamepad 1 button A";
}
if ( scores[1] == winningValue )
{
winnerName = "Gamepad 1 button B";
}
Using an Array as a Lookup Table
 Find out the position in the array of the winning score
int winningValue = 120;
int winnerSubscript = 0;
for (int i = 0; i < 16; i++)
{
if (scores[i] > 0)
{
if (scores[i] < winningValue)
{
winningValue = scores[i];
winnerSubscript = i;
}
}
}

winnerSubscript that holds the position in the array of the winning value
Using an Array as a Lookup Table
 Now that you have the subscript value of the winning
score, you can use it in another array to find the
string that describes that player.
 This is an array of strings of text. There is an element
in the array for each of the buttons on gamepad 1,
and the names are lined up with the buttons that are
tested.
Using an Array as a Lookup Table
string[] names = new string[] {
"Gamepad 1 A",
"Gamepad 1 B",
"Gamepad 1 X",
"Gamepad 1 Y"
};
No Size Needed with Initializer List
Displaying the Winner
 A good time to display the winner would be two
seconds after the sound was produced, which is
when the timer value reaches 120.
 By then, all the players should have pressed their
buttons.
Displaying the Winner
protected override void Update(GameTime gameTime)
{
pad1 = GamePad.GetState(PlayerIndex.One);
if (pad1.Buttons.Back == ButtonState.Pressed)
{
t his.Exit();
}
// start a new game
if (pad1.Buttons.Start == ButtonState.Pressed)
{
for (int i = 0; i < 16; i++)
{
scores[i] = 0;
}
winnerName = "";
timer = -120;
}
// update the timer
timer++;
// play the sound at the start of the game
if (timer == 0)
{
dingSound.Play();
}
// if A is pressed and scores[0] is 0 copy the timer
if (oldpad1.Buttons.A == ButtonState.Released &&
pad1.Buttons.A == ButtonState.Pressed && scores[0] == 0)
{
scores[0] = timer;
}
// Repeat for other buttons and gamepads
if (timer == 120)
{
int winningValue = 120;
int winnerSubscript = 0;
for (int i = 0; i < 16; i++)
{
if (scores[i] > 0)
{
if (scores[i] < winningValue)
{
winningValue = scores[i];
winnerSubscript = i;
}
}
}
if (winningValue != 120)
{
winnerName = names[winnerSubscript];
}
else
{
winnerName = "**NO WINNER**";
}
}
base.Update(gameTime);
}