Objectives

Objectives include:

  • Call and write methods with parameters and return values.
  • Use the DrawingPanel, Graphics, and Color classes.
  • Use for loops and if statements to control assignments.

Introduction

In this project you will write a program for a simple game. Project 3 will be a more sophisticated version of this game.

In this game there will be a runner and a chaser. The computer will control the chaser, which should always move toward the runner. The user (you) will control the runner by keyboard input. The goal is to keep away from the chaser for a short amount of time.

This project will involve graphics and animation. Here an example of playing the game. The user is controlling the movement of the runner, the green square.

Main Method

Below is an initial, incomplete class for you to start with. It contains an incomplet main method.

import java.util.*;
import java.awt.*;

public class SurvivorI {
public static void main(String[] args) {
// Create DrawingPanel and draw a box in the panel.
// The box is a square of this size.
int boxSize = 760;
DrawingPanel panel = new DrawingPanel(800, 800);
Graphics g = panel.getGraphics();
g.fillRect(10, 10, 10, 780);
g.fillRect(10, 10, 780, 10);
g.fillRect(780, 10, 10, 780);
g.fillRect(10, 780, 780, 10);

// Initialize positions of runner and chaser.
Point runner = new Point(200, 400);
Point chaser = new Point(600, 400);

// Variable for input from user to move runner.
char keyInput = ' ';

// The program should wait sleepTime ms between moves.
int sleepTime = 100;

// The runner should move moveSize (or zero) pixels each time step.
// The chaser should move moveSize - 1 pixels each time step.
int moveSize = 10;

// Display players using Color.GREEN and Color.RED (or whatever colors you want).
displayPlayers(panel, runner, chaser);

// Wait one second before start of game.
panel.sleep(1000);

// NEED TO PUT SOME OF THESE STATEMENTS IN A FOR LOOP

// Erase players from the panel using Color.WHITE.
erasePlayers(panel, runner, chaser);

// Get input from user if any.
char newKeyInput = panel.getKeyChar();
if (newKeyInput == 'w' || newKeyInput == 'a' || newKeyInput == 's' || newKeyInput == 'd') {
keyInput = newKeyInput;
}

// Move the players according to parameters.
movePlayers(runner, chaser, keyInput, boxSize, moveSize);

// Display players using Color.GREEN and Color.RED (or whatever colors you want).
displayPlayers(panel, runner, chaser);

// Game is over if the chaser catches up to the runner.
if (collision(runner, chaser)) {
System.out.println("YOU LOST!!!");
}

// Wait sleepTime ms between moves.
panel.sleep(sleepTime);

// NEED AN IF STATEMENT TO DETERMINE WHEN TO PRINT THIS.
System.out.println("YOU WON!!!");
}
}

Drawing Panel

The program uses a DrawingPanel to show the runner and chaser and the box that confines them.

Points

A Point is a convenient way to store a pair of values X and Y. For example, runner.getX() is initially equal to 200, and runner.getY() is initially equal to 400. The other method you will need to use is translate, for example, runner.translate(1,-1) would add 1 to the X value and subtract 1 from the Y value. The program also uses a Point to store the coordinates of the chaser.

Input from User

The runner should be controlled using the WASD keys on the keyboard. 'w' means go up. 'a' means go left. 's' means go down. 'd' means go right. The last 'w', 'a', 's', or 'd' character is stored in keyInput.

Animation

To control the rate of animation, the program needs to wait between moves (a time step). The variable sleepTime indicates how long to wait. Waiting 100 milliseconds each time step is not short enough for smooth animation, but should be good for debugging.

Move Size

The moveSize variable indicates how many pixels the runner moves each time step. The chaser needs to move slightly slower, otherwise the chaser can easily corner the runner.

The displayPlayers Method

The displayPlayers method should draw the runner and the chaser on the panel.

public static void displayPlayers(DrawingPanel panel, Point runner, Point chaser)

displayPlayers should use the getGraphics method of DrawingPanel and the setColor and fillRect methods of Graphics. The runner should be a 10x10 filled rectangle using Color.GREEN. The chaser should be a 10x10 filled rectangle using Color.RED. You can choose different colors if you like.

The erasePlayers Method

The erasePlayers method should erase the runner and the chaser on the panel. This is in preparation for drawing the runner and chaser in new positions.

public static void erasePlayers(DrawingPanel panel, Point runner, Point chaser)

displayPlayers should use the getGraphics method of DrawingPanel and the setColor and fillRect methods of Graphics. The runner should be erased with a 10x10 filled rectangle using Color.WHITE. The chaser should be erased with a 10x10 filled rectangle using Color.WHITE. It might be interesting to choose different light colors to show the paths of the runner and chaser.

The movePlayers Method

The movePlayers method is the most important and most involved method of the game.

public static void movePlayers(Point runner, Point chaser, char keyInput, int boxSize, int moveSize)

A move by the runner means using the translate to change either the x or y coordinate of the runner, but not both. A single move of moveSize pixels must be one of:

  • up: runner.translate(0, -moveSize)
  • down: runner.translate(0, moveSize)
  • left: runner.translate(-moveSize, 0)
  • right: runner.translate(moveSize, 0)

The runner's move is determined by keyInput as described above. The runner should not be allowed to go into the box boundary; in this case, the runner should not move at all. It is recommended that you define two additional methods: a method that determines whether a move is legal and another that performs the runner's move if it is legal.

A move by the chaser means using the translate method to change the x or y coordinate of the chaser, but not both. A single move of moveSize - 1 pixels must be up, down, left, or right. For example, chaser.translate(0, -(moveSize - 1)) would move the chaser up. The move of the chaser is determined by choosing the move (out of the four possible moves) that gets the chaser chosest to the runner. The chaser should not be allowed to go into the box boundary; in this case, the chaser should not move at all. It is recommended that you define two additional methods: one for determining the distance between two points and another for performing the move using the distance method and the legal method described above.

The distance between two Points point1 and point2 is:

the square root of ( ( point1.getX() - point2.getX()) 2 + ( point1.getY() - point2.getY()) 2 )

The collision Method

The collision method determines whether the chaser has caught up to the runner.

public static boolean collision(Point runner, Point chaser)

This method should return true if the two players touch or intersect each other, if runner.getX() is close enough to chaser.getX(), and if runner.getY() is close enough to chaser.getY().

The Loop

The main method need a for loop that runs the game for 300 time steps. However, if a collision occurs, use a break statement to end the loop early.

User Input

The main method currently has fixed values for boxSize, moveSize, and sleepTime. The user should be asked for these values using a single prompt.

Enter the box size, move size, and sleep time: 760 10 100

If the user enters a 0 or negative number, use the default value for that variable. Other magic numbers in the main method might need to replaced with appropriate expressions to take the user's inputs into account.

Suggestions for Proceeding

Add a statement at beginning printing (with appropriate substitutions):

Project 2 written by YOUR NAME

Initially define stubs for the methods you need to code. Compiling and running should show a window with a box that has a 10 pixel boundary

Define the displayPlayers and erasePlayers methods. erasePlayers should be about the same code as displayPlayers expect that erasePlayers uses Color.WHITE. Compiling and running should show a small green box and small red box at the specified positions.

Write code for the main method and movePlayers method so that the user can control the motion of the runner. Leave the code for the chaser for later.

  • Add this code to movePlayers so the runner moves to the left.
    runner.translate(-moveSize, 0)

    This should show the small green box making one small hop to the left. You may need to modify erasePlayers if the green box is not erased from the original position.
  • Modify the main method with a for loop so the runner continues to the move to the left and out of the box. Keeping the runner in the box is addressed later.
  • Modify and test movePlayers to use keyInput to move the runner in the appropriate direction. This will be an if statement to call runner.translate with the appropriate parameters.
  • Modify and test movePlayers to keep the runner in the box. You should create a boolean method that will test whether the runner is in the box. If the runner is not in the box, the change should be undone, so that the runner does not move.
  • At this point, the user should have full control over the movement of the runner in the box.

Write the code for the collision method so it returns true if the runner collides with the chaser. This method should also return true if the runner "sideswipes" the chaser. Add a break statement to the if block so that the loop ends. Add a boolean variable and an if statement to ensure that YOU WON!!! is not printed out after YOU LOST!!!.

Write code in the movePlayers method to control the movement of the chaser. It will be better to make this a separate method called by movePlayers.

  • Write and test a method that calculates the distance between the runner and the chaser.
  • For each legal move by the chaser, determine the distance between the runner and the chaser if the chaser makes that move.
  • Select and execute the move that minimizes the distance between the runner and the chaser.
  • At this point, the game should fully functional for the fixed values of boxSize, moveSize and sleepTime.

Modify the main method so that the user can enter the values of boxSize, moveSize and sleepTime on a single line. If a zero or negative number is entered, set the corresponding variable to its default value, that is, the ones shown in the main method above. Obviously, the size of the box should depend on boxSize, but the size of the panel and the initial positions of the runner and chaser should also depend on boxSize.

Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.