Assignment 7:

Introduction to Computer Program Design: Assignment 7

days Due 15 Dec 7pm

ALERT! This is a Graded Assignment.

Goals

This assignment is intended to give you experience in writing larger programs:
  • with simple event-driven input (mouse, buttons, etc)
  • with multiple classes
  • that use collections of objects stored in ArrayLists and search for objects and add/remove things in an ArrayList
  • that store data to files and read data from files

To Submit:

  • DiskGame.java and Disk.java
  • FireworksDisplay.java

right Do not rename these files. You must use the provided template file and not remove the setupGui and main methods.

right When you have submitted the files, check that you can read the files listed on the submission page, and complete the submission process.

Zip file

DiskGame Program (80%)

Description of the game

DiskGame is a simple game in which the player has to blow up disks spread out over a shooting range. The game starts with a collection of randomly placed small disks on the upper half of the graphics pane, and a gun at the bottom. The gun is fixed in the middle of a horizontal line below the shooting range, and shoots in any direction within a 180 degrees radius.

The player fires the gun with the mouse by releasing the mouse within the firing zone, which is limited by an arc surrounding the upper part of the gun. That will give the direction of the shot.

If a shot hits a disk, it will damage it. If the disk is damaged sufficiently, it will explode and may damage surrounding disks if they are within range. The player has a limited number of shots, and the goal is to cause the maximum damage. Each disk can report its score (based on how much damage it received - the greater the damage, the greater the score), and the score for the game is the sum of the scores for each disk.

The game is over when the player runs out of shots or all the disks have exploded.

Classes

The program consists of two classes DiskGame and Disk. The DiskGame class has an ArrayList which contains the list of all the disks.

User Interface

disk-game.png

The user interface of DiskGame has two sliders: one to set the number of disks in the next game, and the other one to set up the number of shots the player can fire in the next game. It has 4 buttons:
  • the Restart button should start a new game;
  • the Load game will load a previously saved game;
  • the Save game will save a game to be carried on later;
  • the Quit button will exit.
The program also listens to mouse events, and responds when the mouse is released.

The Disk class is written for you, and you do not need to change it for the Core. Make sure you read it carefully so that you know what methods you can call on a Disk object.

Instructions and Tips

  • You must use the constants defined in DiskGame.
  • You must make use of the methods implemented in the Disk class. Do not duplicate code.

Core (70% of DiskGame)
Some of the code is provided; you will need to read and understand it. In particular, note the fields storing the disks, the gun position, the number of shots remaining, and the current score.

tip We strongly advise you to build your program in stages, testing each stage and getting it working before progressing to the next stage!

The following steps are one way of constructing your program in stages. You don't need to follow them, but it may be helpful to you. They give one way of breaking the program into stages, each of which results in a working (though limited) program.

  • Stage 1. GUI Setup: Set up the user interface by completing the setupGUI() method, so that it:
    • adds two sliders to set the number of disks and initial shots. They should call setNumDisks and setNumShots methods, accordingly.
    • adds a Restart button that calls the startGame method.
    • sets up the mouse listener.
  • Stage 2. Basic Initialisation: Initialise the game by creating disks with random positions, setting the total number of disks, and initial shots.
    • Define the setNumDisks(double value) method so that it sets the total number of disks in the game.
      help Hint: Make variable types compatible by using type casting when setting the number of disks.
    • Define the setNumShots(double value) method so that it sets the initial number of shots for the player.
      help Hint: Make variable types compatible by using type casting when setting the number of shots.
    • Define the initialiseDisks() method so that it creates a new list of Disks at random positions within the shooting range.
      Note that it is okay for the core if some of the Disks are initially touching or overlapping.
  • Stage 3. Redrawing the Game Interface: Keep the display updated during the game.
    • Complete the redraw() method so that it also redraws all the Disks in the ArrayList.
  • Stage 4. Mouse Interaction and Shooting: Implement mouse interactions, allowing the player to click and shoot.
    • Define the doMouse(String action, double x, double y) method so that it responds to mouse releases. It must
      • check whether there is any remaining shot (if not, the game is over)
      • then, if the mouse is released within the firing zone, it shoots by calling the fireShot() method.
        help Hint: you can use the isWithinFiringZone() method to check if the given point was within the firing zone.
    • The fireShot(double x, double y) method is the core of the game. Complete it so that it:
      • moves the shot up the screen from the gun, 1 unit at a time, until it either goes off the screen or hits a disk. (Written for you)
      • checks whether the shot hits a disk (use getHitDisk() method). If it does:
        • it damages the disk,
        • If the disk is broken, it should explode and damage any other disks within range ( use damageNeighbours() method).
        • it exits the loop.
    • Define the getHitDisk(double shotX, double shotY) method so that it returns the disk that has been hit by the shot, if any. The method returns null otherwise. help Hint: You use the isOn method of the Disk class.
    • Define the damageNeighbours(Disk disk) method so that it inflicts damage on all the neighbours of the given disk.
  • Stage 5. Game State and Scoring: Manage the game state by checking if all disks have exploded.
    • Define the haveAllDisksExploded() method so that it returns true if all the disks are exploded, false otherwise.
    • Define the updateScore() method so that it iterates through disks and adds up the scores. It also prints the current score.

Note there are many useful methods in the Disk class. Make sure you use them rather than duplicating their code.

Completion (20% of DiskGame)

  • Stage 6. Extend the Disk class:
    • The second constructor in the Disk class should take x and y coordinates and an initial damage level.
    • The toString method should return a string representation of the disk attributes such as coordinates and damage.
  • Stage 7. Improve GUI Setup:
    • Add two buttons for "save" and "load" that call saveGame method and loadGame method.
  • Stage 8. File Handling:
    • Define the saveGame() method so that it
      • asks the user to select a file and save the current game to the selected file.
      • saves at least the score, the number of remaining shots, all the disk attributes such as their coordinates and damage.
        help Hint: You can use toString() method.
    • Define the loadGame() method so that it
      • asks the user to select a file for loading a saved game.
      • reads all game attributes and recreate the game. (It must mirror what was saved in the saveGame() method)
  • Stage 9. Improve Initialisation:
    • Extend the initialiseDisks() method. The core version of the game sometimes starts with overlapping Disks. Fix this so that it is guaranteed that all of the Disks are separated at the start.
  • Stage 10. Improve Redrawing the Game Interface:
    • Extend the redraw() method so that it also displays the remaining number of shots(e.g. as a pile of little squares).

Challenge (10% of DiskGame)
  • If you explode a disk and it damages other disks, the core does not check whether they should be exploded (which might damage further disks, ...). Make the program do this properly, propagating the damage and exploding broken disks.

Fireworks Display (20%)

The FireworksDisplay.java program has waves of fireworks that all go up together. The GUI has a slider to set the number of fireworks in the next wave.

You will need to complete
  • the setWaveSize method, to change the number of fireworks that should be made in the next wave. The slider provides the value for this.
  • the runDisplay method, which should repeatedly send up waves of fireworks. It has a variable containing an ArrayList of the Firework objects in the current wave. This involves:
    • Creating and initialising an ArrayList to store Firework objects for the current wave.
    • Updating the state of each firework in the ArrayList using its step() method.
    • Removing fireworks from the ArrayList after they are finished (isFinished( method).

Watch the demo video to make sure you know what the program should do.

The Firework class is written for you. You are not allowed to modify it. The Firework class has a constructor and three methods you can call:
  • new Firework() to create a new random firework
  • void step() to make the firework take one more step
  • boolean isFinished() to check if the firework has finished
  • void draw() to display the firework on the screen

You are not permitted to modify Firework.java.

Core (70% of FireworksDisplay)

  • Complete the setWaveSize method.
  • One Wave: Intialise the ArrayList with a collection of Firework objects and repeatedly make them step and remove any fireworks that have finished.

Completion (20% of FireworksDisplay)
  • Multiple Waves: In addition to the Core, extend the runDisplay to check each time around the loop if the fireworks have all finished, and if so, make a new wave of fireworks.

Challenge (10% of FireworksDisplay)
  • Nicer Fireworks: The fireworks given are boring - they just draw expanding coloured circles. Make the fireworks explode in a more realistic way, with a collection of "sparks" that expand outwards in a cloud.