Design 20 points; code 40 points.
In this assignment you will begin to construct your game following the description that you handed in for the last assignment. You will do this by creating several new classes and interfaces. What classes you create will depend on the design of your particular game. What you will be constructing now is the beginning of the ``playing field'' -- the background on which the game is played. To do this, you will write what may seem like a lot of classes, but some of them can be very short, and for others you will have access to source code for the equivalent classes in Dr. Lewis's starter game.
Before reading further, review the Project Description, particularly the section ``The game framework''.
The design for this assignment will include descriptions of all the classes and interfaces you will write (for this assignment) and their methods. As in the previous assignment, you will write these descriptions in the form of comments for the classes you need; they will then appear in the HTML documentation generated by Eclipse (or with the javadoc command). As before, what you turn in does not set in stone the code you write for this assignment or later assignments, but you should try to at least plan fairly carefully what you will do for this assignment.
/** Class for circles. */ public class Circle { /** * Constructs a circle with specified radius. * @param r -- radius */ public Circle(int r) { } /** * Gets the circle's area. * @return area */ public double getArea() { return 0; } }
For this assignment, you have to write a number of classes, described in the next section (``Classes for this assignment''). This section describes the overall procedure.
When you get everything right, starting your program (by running its main class, as you did in the previous assignment) will pop up a window much like the starter game, except with a screen and blocks that you created, rather than the starter screen and blocks.
(Read, or at least skim, all of this section before starting your design.)
As you may have noticed from browsing the API for the game framework, many classes and interfaces are generics defined in terms of two basic types, one that extends Block and one that extends GameEntity. These two interfaces are themselves generics defined in terms of Block and GameEntity, and if this sounds to you like infinite recursion -- yes, but this can be avoided by you writing your own class or interface for each of these basic types. I'll call these YourBlock and YourEntity here, but you should give them names related to your game (e.g., PacManBlock and PacManEntity). You will then use these types everywhere the framework wants types that extend Block or GameEntity. YourBlock, and all of your game entity classes will be For example: In Homework 1 you had a MainFrame<BasicBlock,BasicEntity>. In this assignment you will replace that with a MainFrame<YourBlock,YourEntity>.
Making YourBlock an interface involves much less code; in fact, all you need (other than the usual package and import statements) is the following line:
public interface YourBlock extends Block<YourBlock,YourEntity> { }The idea is that all of the classes you write to represent blocks will implement this interface. So your comment describing this class could be something like ``this is an interface that all the block classes for my game will implement.''
The alternative is to make YourBlock a class, possibly an abstract class, and make all of your other block classes subclasses of YourBlock. This is a good choice if you find yourself writing the same code over and over in your block classes, since then you could put that common code into YourBlock and have it inherited by the other block classes. You can model this class on BasicBlock, for which source code is provided as part of this assignment.
public interface YourEntity extends GameEntity<YourBlock,YourEntity> { }As with YourBlock, the idea is that all the classes you write to represent entities -- including the player -- will implement this interface.
Once you have definitions for YourBlock and YourEntity, for this assignment you will write several additional classes, described below. (This is not as overwhelming as it might sound; for most of these classes you have starter code that you just need to modify.) These classes will replace corresponding starter-code classes (e.g., your class implement GameSetup will replace BasicGameSetup), which means you will need to make other changes (e.g., in your main method that you wrote for Homework 1).
Here are the classes you will write by modifying starter code (linked from this page, at the bottom):
You only need to write one class from scratch for this assignment, and that is your ``screen class'', which will implement the framework's Screen interface. (You could call it, e.g., PacManScreen.) This interface includes a number of methods, but code for most of them will be very short. To find out what methods you need in this class and what they are supposed to do, look at the project API for the Screen interface. (See below for some thoughts about a sensible order for implementing the methods.) At this point not all the methods will make sense to you; for those that don't (and the documentation should give you some hints about which ones these are), just write skeleton/stub versions, with comments that indicates you'll fill them in later. If one of these methods is supposed to return something, have it return 0 or null for now. It's up to you to decide what variables your class will need, but you will almost certainly need a two-dimensional array of blocks (i.e., a two-dimensional array of YourBlocks) and a list of game entities. For the list of game entities, for now you should use the GameEntityList class in the framework. (Later you will write your own replacement for this class.) GameEntityList is described in the project API and included in this assignment's JAR file.
For initial testing, you should write your game setup class so that it directly creates a screen and fills it with blocks. Once you're reasonably confident that your screen and block classes are working, you may want to use Dr. Lewis's screen editor (see ``Links and files'' below) to actually build screens for your game. This is a nice visual tool that allows you to build screens using your block classes and save them in a binary format that can be read into your game in the constructor of your game setup class. There is commented-out code in the starter version of this class that you can use as a model for doing this. Warning: Do not put too much effort at this point into creating elaborate screens using the screen editor; almost any change you later make to your screen or block classes will make it necessary to start over (because the saved binary-format representation will no longer be valid -- later in the semester we'll talk about why). However, do try out the screen editor, to make sure the parts of your screen and block classes that interact with it are working right.
The methods you need fall into several groups, and you might want to implement them group by group in order:
There is one of these in the Block and GameEntity interfaces as well. You can ignore them all for now -- they're there to allow doing some interesting things with the screen editor tool (giving different properties to different screens/blocks/entities), but you don't really know enough yet to use them. Just return null for now.
The screen editor (which I will show in class) puts up a graphical menu of blocks and entities. It uses these methods to do that.
So, getNumBlockTypes should return the number of different kinds of blocks, and getNumEntityTypes should return the number of different kinds of entities (not counting the player). If you never plan to use the screen editor, both of these methods can just return 0. For now getNumEntityTypes should probably return 0 in any case.
If getNumBlockTypes returns 0, getBlockOfType can just return null, and similarly for getNumEntityTypes and getEntityOfType.
If getNumBlockTypes returns a positive (nonzero) number N, the screen editor will call getBlockOfType with values ranging from 0 through N-1, and this method must return something other than null. The ``something'' should be an instance of one of your block classes, different for different values of the input parameter -- e.g., in pseudocode:
if (parameter == 0) return new background block else if (parameter == 1) return new wall block else ....getEntityOfType will work similarly, when you have some non-player entities to work with.
A ``screen'' can be thought of as having two important components: a 2D grid of blocks, and a list of entities. There are several methods that do things with the grid of blocks, and others that do things with the list of entities. These methods exist so that the game framework can draw your playing field -- it needs to know the dimensions of the grid, for example, and what entities are there. So you almost surely need instance variables to represent both things, as described earlier.
For the methods relating to entities: If you look at the API for GameEntityList, you will notice a remarkable similarity to the methods above, which should mean that implementing the above methods will take very little code. (Hint, hint.)
The other methods should all do the obvious(?) thing with that grid of blocks -- return its dimensions, return a single element, change a single element.
The starter code for the GameSetup class uses a BasicScreen constructor with two parameters. You could provide a similar one, or one with no parameters. This might be a good place to lay out the playing field.
If your browser doesn't do a nice job of displaying .java files (flowing the whole file into one big paragraph rather than showing it with separate lines), you should still be able to get the above files by downloading (saving) them rather than trying to display them. (E.g., in Firefox, you right click on the link and then select ``Save link as''.)