CSCI 136
Fundamentals of Computer Science II
Spring 2017

Montana Tech
Computer Science & Software Engineering



ASSIGNMENT 3 - Dungeon

In this assignment, you will be making a game in which you wander around a dungeon.
  • You will use 2D arrays.
  • You will develop a class hierarchy using inheritance.
  • You will experience the power of polymorphism (polymorphic goodness).
  • You will use enumerations.

Dungeon game. Our hero is exploring a dungeon collecting gems. The dungeon has a bunch of locked doors that our hero needs to use keys to open. Our hero obviously can't walk through walls, unless of course it is a secret passage! The provided main program DungeonGame.java reads in the dungeon from a file. Here is the d0.txt file and what it looks like:

13 10
3 10
1 1
W W W W W W W W W W W W W
W - W - - - - - - D - - W
W - W - W W W - W W - - W
W - W - S - S - W W - - W
W - - - W W W - W W W O W
W W W - W W W D W W - - W
W W W - W - - - - D - - W
W W W - W - - - - W - - W
W - - - W W W W W W - - W
W W W W W W W W W W W W W

The first line contains the width and height of the dungeon in cells. The second line contains the number of keys followed by the number gems that will be randomly placed in the dungeon. The third line contains the x-index and y-index that the hero starts at. The remaining lines contain a character specifying what is at each location in the dungeon. Even though each cell is given by a single character, DungeonGame.java reads it using next() since this method will split the data on whitespace as expected. The string code for cells are as follows:

CodeDescription
WWall, appears as , the hero cannot pass through it.
SSecret passage, appears as , but the hero CAN walk here.
-Passage, appears as , the hero can walk here.
DClosed door, appears as a closed (locked) door , the hero must have a key to open it.
OOpen door, appears as an open (unlocked) door , the hero can walk right through.

Your dungeon should appear on the screen oriented in the same way as the ASCII text version shown above. We think it is easiest if you setup your 2D array (let's call it map) so map[0][0] is the lower-left cell in the dungeon with the first index being the x-position and the second index being the y-position. So in the above map, the hero is at map[1][1], there is an open door at map[11][5], and so on.

Coordinates and pixels. All cell images in the game are square. The exact image filenames and the size of the square is defined by the Config class. The number of tiles on the screen depends on the width and height read from the first line in the dungeon definition. The provided DungeonGame program sets StdDraw.setCanvasSize() so the entire dungeon can be shown. Be sure you are using the latest version of StdDraw (provided in the assignment zip file). The old StdDraw put a 5% border around the drawing area which will cause your cell images to slightly overlap. DungeonGame sets the x-scale and y-scale so the coordinate system matches the pixel size of the canvas. This allows the various objects to draw themselves based on just knowing the tile resolution and their (x, y) indexes in the 2D array.

Gems and keys After your dungeon is created, it gets populated by gems and keys at random cell locations. Only cells that the hero can walk through are allowed to have a gem or key. So passages and secret passages can have a gem or key, but walls cannot. Doors are allowed to have a gem or key, but only if the door is open. A cell can only contain a single gem or key. The cell where the hero starts at should never have a gem or key. When the hero walks into a key, it is added to the hero's key total and the key collection sound effect is played. When the hero walks into a gem, it is added to the hero's gem total and the gem collection sound effect is played. Gems and keys should be drawn on top of the cell background image.

Hero. The hero always starts at the cell specified on the third line of dungeon definition. You can assume this location is a passable cell. The hero defaults to using the image specified by the heroImage method in the Config class, but the Hero API allows the hero to be set to any image via the setImage method. The hero moves based on the following keys:

KeyAction
wHero attempts to walk north.
sHero attempts to walk south.
aHero attempts to walk west.
dHero attempts to walk east.

The hero can only walk in the desired direction if the cell at that location is passable. If the cell is passable, the hero's position is updated and the walking sound effect is played. If the cell is not passable, or if a move would take the hero outside the dungeon bounds, the hero remains in the current position and the hit wall sound effect is played.

Doors. Some doors in the game started closed and locked. If the hero attempts to move into a locked door, and the hero has at least one key, the door opens and the key use sound effect plays. Opening a door costs the hero one key. Once a door is open, it remains open. Note that since the placement of keys is random, it is entirely possible that parts of a dungeon could end up unreachable.

Classes. To get started, download dungeon.zip. The zip file contains images, sounds, dungeon definitions, some completed Java classes, and some classes that you will complete for the assignment. Classes you need to complete have stubbed out methods along with a detailed description of what each method should do. Here is a high-level description of each class:

ClassDescription
Config Like many games, Dungeon involves numerous image and sound assets. Rather than sprinkle the literal names of these assets throughout your code, you should instead use the provided Config.java class. This class provides methods that can be called to obtain image filenames, sound filenames, and the size of cells in pixels. Config also provides a method that maps user input to a game action, and methods that determine what sounds to play when items (i.e. gems or keys) are collected or used. You should not need to modify this class.
Action The Action enumerated type represents the different actions the hero might take in the game. Currently this is just moving to the north, south, east, or west. You should not need to modify this class.
Item The Item type represents things the hero can collect in the game. Currently this is just gems and keys. You should not need to modify this class.
DungeonGame Main program that runs the game. Responsible for reading in the dungeon control file using standard input. Creates the Dungeon and Hero objects. Sets up the drawing canvas and coordinate size. The game continues forever. You should not need to modify this class.
Cell Represent an individual cell location in the dungeon. This is the base class in the inheritance. As such it defines the API that all the other Cell-related data types implement. The Cell type itself is quite basic, it represents an impassable wall with a given background image. You need to complete the missing code in two methods.
CellPassage This class extends the Cell class. It is a cell that the hero can walk through. Depending on the image it is created with, it could be a normal passage or a secret passage. It can contain either a gem or a key (but not both). You need to add instance variable(s) and implement all methods.
CellDoor This class extends the CellPassage class. It is a cell that the hero can sometimes walk through (if the door is already open or if the hero has a key). A CellDoor may be created either open or closed. If the door is open, it can contain either a gem or a key (but not both). You need to add instance variable(s) and implement all methods.
Hero Represents the state of the hero in the game. It keeps track of where the hero is, the image used to draw the hero, and how many keys and gems the hero has collected. This class plays sound effects related to collecting or using items. You need to add instance variable(s) and implement all methods.
Dungeon Stores the grid of cells containing the dungeon. A dungeon also keeps track of the Hero object. This class plays sound effects related to moving or hitting walls. You need to add instance variable(s) and implement all methods.

Main test methods. The classes Cell, CellPassage, CellDoor, Dungeon, and Hero have provided test main() methods. This allows you to test most of the methods in each class independent of the other classes. You can modify or add to these test main() methods as you like (we ignore all main() methods during grading). Here are our sample outputs using the provided main() methods:

ClassGraphical outputText output
Cell
      
% java Cell
    
CellPassage
      
% java CellPassage
Adding gem to passage,  result =  true
Adding gem to passage,  result = false
Adding key to passage,  result = false
Adding key to passage2, result =  true
Adding key to secret,   result =  true
Adding gem to passage,  result = false
Adding key to passage,  result = false
Adding key to secret2,  result =  true
    
CellDoor
      
% java CellDoor
Adding gem to closed door, result = false
Adding key to closed door, result = false
Adding gem to open door,   result =  true
Adding key to open door,   result = false
Adding key to open door2,  result =  true
Adding gem to open door2,  result = false
    
Hero
      
% java Hero
hero1, location (0, 0)
hero1, gems = 0, keys = 0
hero1, gems = 1, keys = 0
hero1, gems = 1, keys = 1
hero1, gems = 1, keys = 2
hero1, gems = 2, keys = 2
hero1, using key =  true, gems = 2, keys = 1
hero1, using key =  true, gems = 2, keys = 0
hero1, using key = false, gems = 2, keys = 0
hero1, using gem =  true, gems = 1, keys = 0
hero1, using gem =  true, gems = 0, keys = 0
hero1, using gem = false, gems = 0, keys = 0
hero2, location (1, 0)
    
Dungeon
      
% java Dungeon
    

You might also want to test with the bigger dungeons d1.txt and d2.txt. Here are links to what the dungeons look like in our solution: d1.png, d2.png.

Grade ItemPoints PossiblePoints Earned
Program Compiles
1
Program Runs
1
javadoc Comments on All Your Classes and Methods
4
Implemented Cell Correctly
5
Implemented CellPassage Correctly
5
Implemented CellDoor Correctly
5
Implemented Hero Correctly
4
Implemented Dungeon Correctly
5
Total
30

Why are my tiles are all offset and appearing in the borders of the drawing window? Remember that the StdDraw.picture() method expects the center (x,y) position of the picture, not the lower-left corner. You need to adjust appropriately to get things to line up nicely.

Is it okay to put the literal filenames of images, sounds, and/or the tile size in my classes? No. You should use the methods in the provided Config class. This way if any of these literal values changes, you only need to modify it in one place. It also provides a way (via subclassing Config) to easily change all the images, sound effects, and even the input keys by only modifying one line in your existing code. Cool aye?

Where did you get the graphics and sounds? We cut out bits from some of the images provided in the set: Danc's Miraculously Flexible Game Prototyping Tiles. The audio effects were obtained from freesound.org.


Extra credit. Make the game better. But please see the note below on how to submit your extra-credit creation. Be sure to submit your regular submission first and ensure it works per the assignment specifications.
Submission. Submit only the classes you implemented: Cell.java, CellPassage.java, CellDoor.java, Hero.java, and Dungeon.java using Moodle. Be sure each submitted source file has the required header with your name and a description of the program. For extra-credit, please submit a single zip file containing all your programs/graphics/sounds/configuration files via the special extra-credit drop box.

Page last updated: January 04, 2018