Adventure Game Design Specification (5/5/08 1601)

This is the design bible for the group project involving the following people:

This design is complete in the sense that a lot of time and thought has been put into it. It is also incomplete in the sense that it's going to change whether we like it or not. If you need to change a detail, particularly one related to the hooks, be a good person and tell us. Neglecting to do this is punishable by plague of locusts.

Direct any corrections, additions or complaints to me (Josh). Also, it is anticipated that this page will be highly superfluous once the program is integrated. Its main purpose is to show how other people's modules work before they do work, so we can all start slinging code real soon.

Overall Design

The following small picture demonstrates the big picture of how the modules fit together (the hooks, or links between modules, are expanded on below):

People responsible for each module are:

Module Design: Game State and Logic

The game state is the centre of the program, so is fairly well-defined. The general design is (I've drawn the UI object in to show it has a pointer to the Universe):

The methods shown are those that may be useful to some other module. I will expand on their proposed function for completeness (some of this is a bit pedantic, but you will understand that it is good to know exactly what to expect from someone else's function):
Thing
  • Each Thing object has a weight (this is really internal to the module). This serves as both a means of limiting the amount of stuff that can be put in a container, and a measure of how hard a door is to kick in or how hard something is to pick up.
  • getInteractions() Returns a Collection object, which is a list of interactions that can be chosen by the user. (See the section on hooks below.)
  • getName() Returns a String representing the name of the thing.
  • getResourceName() Returns a String representing what we are calling the resource name of the thing. This is the name used by the Renderer module to know what picture to draw.
  • getLocation() Returns a Location object describing the thing's location within the room.
  • getBoundingBox() Returns a BoundingBox object describing the thing's dimension and position.
Player
  • getRoom() Returns the Room object representing the room that the player is currently in.
  • getOrientation() and setOrientation(Orientation) Accesses and mutates the current Orientation of the player.
MazeWorld
  • getRooms() Returns a Room[][][] representing the grid of rooms in the maze world. The array value is null where there is no room, and is a reference to the Room that is in the given location if there is one.
Room
  • explored() Returns a boolean value representing whether the room has been explored. Will eventually be needed by the UI/Renderer modules for drawing maps.
  • getThings() Returns a Collection object which contains all the things in the room. This should include everything that needs drawing.
  • isOutside() Returns whether this is an outside room.
  • getBoundingBox() Returns the bounding box representing the room.

Module Design: Data Storage

A minimal design of the Data Storage module looks like this:

The getUniverse() method will return a Universe object with state for a new game. The getUniverse(File) method will return a Universe object with state for a game loaded from the given file. The saveUniverse(Universe, File) method will save the given Universe's state to a file.

The Data Storage module must also be able to load a PictureMap from a directory structure, to be used by the Renderer module. The getPictureMap() method will facilitate this. A PictureMap simply contains a map from resource names of Thing objects to Picture objects. Exactly what a Picture object is is still unclear, due to Josh being lazy.

Hooks

There are two main "technologies" used on the interface between modules. They are the Interaction interface, and the RoomListener interface.

Interaction Interface

Interactions are classes that describe a way in which the user can interact with a Thing object. They are characterized by having a "name" field and a do() which may take some sort of argument and returns a message as a String to be displayed by the User Interface. A proposed hierarchy looks like:

The idea is that all of these classes are abstract, and when an item wants to support an interaction it will make an inner class on the fly within its getInteractions() method. On the User Interface end, the user will be asked to select an interaction from the list and a sequence of instanceof statments will determine which type of interaction was chosen, and hence determine what must be required from the user.

The set of these abstract classes, while resembling the structure above, will no doubt be added to often throughout the development of the program. This is a crucial point of communication between the Game State and the User Interface developers.

RoomListener Interface

This is the device by which the RenderingFrame sends messages to the User Interface module. It mimics the Event model in the Java API.

The RoomEvent object could conceivable get more complex as the need arises, but for intial purposes it will contain a Thing that the user has clicked on. (The logical thing for the User Interface to do with this information is to process interactions on the received thing.)

Miscellany

Here is some example code that should be demonstrative of what each module knows, and how everything gets started.

public class AdventureGame {
	Universe universe;
	DataReader reader;
	UI ui;

	// New game

	AdventureGame(UI ui) {
		this.ui = ui;

		reader = new DataReader();
		universe = reader.getUniverse();
		ui.setPictureMap(reader.getPictureMap());

		ui.startGame(universe);
	}

	// Load game

	AdventureGame(UI ui, File f) {
		this.ui = ui;

		reader = new DataReader();
		universe = reader.getUniverse(f);
		ui.setPictureMap(reader.getPictureMap());

		ui.startGame(universe);
	}
}

public class UI {
	...

	public static void main(String[] args) {
		UI ui = new UI();
		ui.displayTitleScreen();
	}

	public void actionPerformed(ActionEvent e) {
		if(e.getActionCommand().equals("Play")) new AdventureGame(this);
		if(e.getActionCommand().equals("Load")) new AdventureGame(this, getFileFromUser());
	}
}

The Little Classes That Could

This is a list of all of the proposed helper classes that are mentioned somewhere above, and are concerned with multiple modules. I (Josh) will write these, I suppose.