Adding another unit
Feedback
Currently we have 3 variables to track information about the unit: it's color, and it's two cartesian coordinates (row, column):
public static int unitRow = 0;
public static int unitColumn = 0;
public static Color unitColor = Color.BLACK;
To add another unit to the game, we simply add another set of 3 variables to track its information. These new variables have to have different names to distinguish between the original unit's variables. To differentiate them we'll add a number to the variable name and also go back and rename the original variables for consistency sake.
public static int unit1Row = 1;
public static int unit1Column = 1;
public static Color unit1Color = Color.RED;
public static int unit2Row = 10;
public static int unit2Column = 10;
public static Color unit2Color = Color.GREEN;
Here we are automatically assigning the initial values to the proper settings since we want the starting positions to be set for our game. At this point we can delete our code in the startup sequence to prompt the user for this information. We're also automatically assigning the unit colors. This is somehting you might want to keep in your code but I will eliminate it for brevity.
Using the information
Since we've changed the name of the variables that we are using to track our first unit, we'll have to change all our code that referred to it to now point to the new variables: unitRow > unit1Row, unitColumn > unit1Column, etc. In addition we will need to add the code to the paint function to put our new unit on the screen. It goes right after the code for painting the first unit
// Paint the second unit
canvas.setColor (Stakeout.unit2Color);
canvas.fillRect (UpperLeft (Stakeout.unit2Column), UpperLeft (Stakeout.unit2Row), GRIDSIZE, GRIDSIZE);
Turn-based system
Feedback
Switching teams
Right now, the only unit we can move is the first one. We have no way of switching to the second team to move the second unit. As stated in the introduction we are going to use the 's' key to switch back and forth. We will have to establish a variable to remember which team's turn it is and then we will change our keyPressed function to respond to the 's' key. First we add an int variable to the Stakeout class and initialize it to 1, then we add this code to the top of our keyPressed function:
if (keyId == KeyEvent.VK_S) {
if (Stakeout.teamsTurn == 1) {
Stakeout.teamsTurn = 2;
}
else if (Stakeout.teamsTurn == 2) {
Stakeout.teamsTurn = 1;
}
else {
assert (false);
}
}
In English it says if the 's' key was pressed, make it the 2nd teams turn if it's currently the 1st teams turn or make it the first team's turn if it's currently the second team's turn. If the teamsTurn is neither 1 or 2, then we assert because this should never happen since we only have two teams. Now that we change the team's turn when 's' is pressed, we need to change the way our program behaves when it's the second team's turn. Next we have to wrap the rest of the "moving" code in an "else if" statement. Then at the end of the function we have to make sure that we only move the units whose turn it is. The entire keyPressed function follows:
public void keyPressed (KeyEvent event) {
int keyId = event.getKeyCode ();
if (keyId == KeyEvent.VK_S) {
if (Stakeout.teamsTurn == 1) {
Stakeout.teamsTurn = 2;
}
else if (Stakeout.teamsTurn == 2) {
Stakeout.teamsTurn = 1;
}
else {
assert (false);
}
}
else if (keyId == KeyEvent.VK_UP
|| keyId == KeyEvent.VK_DOWN
|| keyId == KeyEvent.VK_LEFT
|| keyId == KeyEvent.VK_RIGHT) {
int newRow = 0;
int newColumn = 0;
if (Stakeout.teamsTurn == 1) {
newRow = Stakeout.unit1Row;
newColumn = Stakeout.unit1Column;
}
else if (Stakeout.teamsTurn == 2) {
newRow = Stakeout.unit2Row;
newColumn = Stakeout.unit2Column;
}
else {
assert (false);
}
if (keyId == KeyEvent.VK_UP) {
newRow = newRow - 1;
}
else if (keyId == KeyEvent.VK_DOWN) {
newRow = newRow + 1;
}
else if (keyId == KeyEvent.VK_LEFT) {
newColumn = newColumn - 1;
}
else if (keyId == KeyEvent.VK_RIGHT) {
newColumn = newColumn + 1;
}
else {
assert (false);
}
if (newRow >= 1 && newRow <= StakeoutComponent.MAPHEIGHT
&& newColumn >= 1 && newColumn <= StakeoutComponent.MAPWIDTH
&& Stakeout.component.map [newRow - 1][newColumn - 1] == StakeoutComponent.LAND) {
if (Stakeout.teamsTurn == 1) {
Stakeout.unit1Row = newRow;
Stakeout.unit1Column = newColumn;
}
else if (Stakeout.teamsTurn == 2) {
Stakeout.unit2Row = newRow;
Stakeout.unit2Column = newColumn;
}
else {
assert (false);
}
Stakeout.component.repaint ();
}
}
}
That's it. Now we have a turn-based system. One problem, though, is that it's hard to tell whose turn it is without actually moving a unit. That brings us to team names.
Team names
Intead of prompting the user for his starting positions, we need to prompt him for his name. We will use this name to tell him whose turn it is. This will just be another String variable that we will store along with our unit information. There's nothing new in prompting the for the team names:
// Prompt the first player for his name
boolean invalidName1 = true;
while (invalidName1) {
System.out.print ("Enter the name of the first player (red team): ");
String input = CmdInput.GetInput ();
if (! input.contentEquals ("")) {
team1Name = input;
invalidName1 = false;
}
else {
System.out.println ("You entered an invalid name!");
}
}
The same thing is done for the second unit... Now we should print a message on the command line informing the players whose turn it is. This only requires two extra lines to the keyPressed function:
if (keyId == KeyEvent.VK_S) {
if (Stakeout.teamsTurn == 1) {
Stakeout.teamsTurn = 2;
System.out.println ("It is now " + Stakeout.team2Name + "'s turn");
}
else if (Stakeout.teamsTurn == 2) {
Stakeout.teamsTurn = 1;
System.out.println ("It is now " + Stakeout.team1Name + "'s turn");
}
else {
assert (false);
}
}
Limiting movement
The last thing we need to do to truly have a turn-based system is to limit the number of moves that a unit can have in any particular turn. We do this by having another variable that we'll associate with the unit to track how many moves he has left for the current turn. Units should start a turn with 2 moves which is reset at the beginning of the turn. Moves do not accumulate from turn to turn.
public static int unit1Moves = 2;
We add this along with all the other unit variables. We initially set it to be two because that is how many moves the unit should have at the start of the turn. At the beginning of our turn, we have to reset this number to 2. You should recognize where the following code is form by now.
if (keyId == KeyEvent.VK_S) {
if (Stakeout.teamsTurn == 1) {
// Switches to team 2's turn
Stakeout.teamsTurn = 2;
Stakeout.unit2Moves = 2;
System.out.println ("It is now " + Stakeout.team2Name + "'s turn");
}
else if (Stakeout.teamsTurn == 2) {
// Switches to team 1's turn
Stakeout.teamsTurn = 1;
Stakeout.unit1Moves = 2;
System.out.println ("It is now " + Stakeout.team1Name + "'s turn");
}
else {
assert (false);
}
}
Then we have to subtract 1 from this number each time the unit is moved and refuse to move the unit if this number is 0.
else if (keyId == KeyEvent.VK_UP
|| keyId == KeyEvent.VK_DOWN
|| keyId == KeyEvent.VK_LEFT
|| keyId == KeyEvent.VK_RIGHT) {
int newRow = 0;
int newColumn = 0;
if (Stakeout.teamsTurn == 1) {
newRow = Stakeout.unit1Row;
newColumn = Stakeout.unit1Column;
if (Stakeout.unit1Moves < 1) {
return;
}
}
else if (Stakeout.teamsTurn == 2) {
newRow = Stakeout.unit2Row;
newColumn = Stakeout.unit2Column;
if (Stakeout.unit2Moves < 1) {
return;
}
}
else {
assert (false);
}
if (keyId == KeyEvent.VK_UP) {
newRow = newRow - 1;
}
else if (keyId == KeyEvent.VK_DOWN) {
newRow = newRow + 1;
}
else if (keyId == KeyEvent.VK_LEFT) {
newColumn = newColumn - 1;
}
else if (keyId == KeyEvent.VK_RIGHT) {
newColumn = newColumn + 1;
}
else {
assert (false);
}
if (newRow >= 1 && newRow <= StakeoutComponent.MAPHEIGHT
&& newColumn >= 1 && newColumn <= StakeoutComponent.MAPWIDTH
&& Stakeout.component.map [newRow - 1][newColumn - 1] == StakeoutComponent.LAND) {
if (Stakeout.teamsTurn == 1) {
Stakeout.unit1Row = newRow;
Stakeout.unit1Column = newColumn;
Stakeout.unit1Moves -= 1;
}
else if (Stakeout.teamsTurn == 2) {
Stakeout.unit2Row = newRow;
Stakeout.unit2Column = newColumn;
Stakeout.unit2Moves -= 1;
}
else {
assert (false);
}
Stakeout.component.repaint ();
}
}
The statements to update the number of moves might seem a little odd. The statement "x -= 1" is actually just shorthand for "x = x - 1". There are several other such operators: +=, *=, etc. Since incrementing by one is such a common operation, there is an even shorter way of doing it: "x--" can be used to decrease the variable x by one and "x++" can be used to increase the variable x by one.