Cay S. Horstmann
DRAFT 2007-02-08
This note gives some hints to advanced users who would like to extend the GridWorld environment for their own class projects. Nothing in this note is required or suggested reading for the AP CS exam.
The narrative explains how to design bugs and critters. For more general actors, you can simply subclass Actor, override the act method, and supply a GIF file.
NOTE: Images look best if their size is 48 x 48 pixels. If that is a problem, try 24 x 24 or 12 x 12 for smaller images/96 x 96 pixels for large images. Other image sizes will be scaled.
Example: Game of Life. Note that these actors alternate planning and living. The display changes with every second press of the Step button.
You don't have to use actors. In that case, use a World<Something>, not an ActorWorld. Here is an example of a loop practice lab that uses a simple World<Rock>. Of course, then the Step and Run buttons don't do anything.
Sometimes, you may want to draw occupants that are not GIF images.
The rendering algorithm is as follows:
What does all this mean for you?
The simplest occupants (such as numbers and Boolean values) are displayed correctly without any effort, simply by invoking toString.
Colored and labeled tiles can be done very simply: Provide a getText and, optionally, a getColor method. An example is the TileGame below.
If you have an occupant that needs different images depending on its state, then supply a getImageSuffix method. For example, a bug might be alive or dead. If the getImageSuffix method returns a string "" or "_dead", then you can supply two images MyBug.gif and MyBug_dead.gif. Note: (1) One of the images must have the same name as the class, even if you never use it. (2) The getImageSuffix method must return any separators such as underscores.
If you need to do a fancier drawing, supply a class that extends AbstractDisplay. You can use any of the Java AWT drawing calls in the draw method.
As an example, look at the code for FishDisplay. The result looks eerily familiar.
Finally, if you get an image from a superclass but you actually want a colored cell with text, then provide a display class that trivially extends the DefaultDisplay class, e.g.
public class MyTile extends Actor { . . . } // don't want to pick up Actor.gif public class MyTileDisplay extends DefaultDisplay { }
You can tweak the behavior of your world as follows:
You can use the GridWorld framework for games and other applications. In this case, you will want to install your own subclass of the info.gridworld.world.World class. There are three main extension points.
Here is an example for the first modification: a tile game. When the user clicks on a tile, it is flipped over to reveal its top side. Click again, and the next tile is flipped. If they both match, they stay up. Otherwise, they are both flipped again.
If you call
System.setProperty("info.gridworld.gui.selection", "hide");
the selection square is hidden. This may be useful for special environments (such as a Quzzle game in which it doesn't make sense to select a fractional tile.)
If you call
System.setProperty("info.gridworld.gui.tooltips", "hide");
the tooltips are hidden.
Call
System.setProperty("info.gridworld.gui.frametitle", titleString);
before showing the world to set a different title.
If you modify the framework to implement other special effects that shouldn't result in API clutter, consider using a similar “secret flag” mechanism.
The following is a more sophisticated morphing of the GridWorld environment in which the Step button has been redefined.
Students write a run method in a subclass of StepWorld, placing calls to pause when desired. Here is an example:
public class LoopWorld extends StepWorld<Rock> { public void run() { int n = 5; for (int i = 1; i <= n; i++) { for (int j = 1; j <= 2 * i - 1; j++) { add(new Location(i, n - i + j), new Rock()); pause("i=" + i + ",j=" + j); } } } }
In GridWorld, press the Step button. The program runs to the next call of the pause method. Keep doing this to see how the rock pile is built up one step at a time.
This allows the student to single-step through the loop without having to run a debugger.
Here is the complete project. The StepWorld implementation isn't for the faint of heart, but students don't need to see it.