C212 Assignment 6

Moving Sprites

Due: Thursday, February 24th, 9am

Pair programming, with a partner of your choice, so long as your are both in the same lab.

Motivation

A central characteristic of many video games is that the playing area is divided into a rather course grid of cells. The movable game elements, called sprites, move smoothly in a horizontal or vertical direction between the centers of the grid cells. Cells may also contain various fixed elements, such as walls, treasure chests, trap doors, and so on. Many of the fixed elements, such as walls of various kinds, are so solid that a sprite cannot move onto one of their cells. These characteristics provide enough realism and versatility for satisfying play in many games, while providing enough constraints (such as allowing only horizontal or vertical motion and stopping only at fixed grid positions) to make the game more efficient and much easier to program than it would be without the constraints.

In this assignment you will be programming a simple game with these characteristics. You will modify the resulting code to build more complete games in future assignments. The assignment provides experience with threads (objectdraw ActiveObjects), loops, and a simple array.

In lab

Choose your partner and begin work on the following assignment.

This assignment is to implement a FrameWindowController class with behavior similar to the sample application moveSprite.jar. It should have the following properties:

  1. Most of the white canvas area is divided into a course grid of roughly square cells divided by light-gray lines.
  2. Red circles represent sprites and blue cells represent walls.
  3. The user may be in control of only one sprite at any given time.
  4. The user initially starts in control of no sprites.
  5. If a user clicks on a sprite, and if they currently control no sprite, they take control of the sprite on which they clicked.
  6. If a user clicks on a sprite, and if the sprite they currently control is not moving, they take control of the sprite on which they clicked.
  7. If a user clicks on an cell, and if they currently control no sprite, nothing happens.
  8. If a user clicks on an cell in the same row or column as the sprite they currently control, and if that sprite is not moving, that sprite moves smoothly in the direction of the clicked cell and stops.
  9. If a wall or another sprite is in the sprite's path of motion, the sprite stops just before moving into the square which contains that object. Otherwise, it stops in the cell that was clicked.

Design

Define your own wall layout and initial sprite position using a constant array of strings. Each string represents a row, with specific characters representing cells containing wall segments or the sprite, and a blank if neither. For example the following was used to define the layout of the sample program:

private static final String[] FIELD =
      {
         "***************",
         "*      s     **",
         "* *** ****    *",
         "* *** ****    *",
         "* *** ****    *",
         "*  *   *****  *",
         "*  * * *****  *",
         "*  * * *****  *",
         "*  *          *",
         "*             *",
         "*   **   ***  *",
         "*   * **  s*  *",
         "*     *     * *",
         "*     *       *",
         "***************" };

Your program needs to check that this array has the following properties:

If any one of these constraints is violated, print a message indicating the nature of the error and terminate the program. Call System.exit with the integer 1 to terminate the program, in keeping with the Unix convention that programs terminating with an error return a non-zero integer. Print error messages to the standard error output, using System.err instead of System.out. It is good style to define your own error method that prints a given message and exits.

 

Use constants to specify the cell width and height (20 pixels works well for both). Use these, together with the length of the string array and the length of its strings to compute the size of the canvas. Then determine the size you need make the frame by adding 12 pixels to the width of the canvas and 73 pixels to its height. (This allows for the frame border and title bar). Then set this size of the frame by using the commands:

getAppletFrame().setSize(width, height);
getAppletFrame().validate();

 

The hardest part of this program's design is how to make sprites alternately move and stop. We want to use an active object to animate the motion, as discussed in lecture. Yet since active objects run until they die, it is not satisfactory for the sprite to be an active object. Instead, we use a system of callbacks to keep moving the sprite until it has finished its actions. So far we have made extensive use of callbacks, such as onMousePress, but they have always been invoked by the JVM/objectdraw system, not by code that we wrote. In this program, the timer invokes a callback method belonging to the sprite, called pauseOver, each time a pause is over. The timer passes the pauseOver method the actual length of the pause, which as we have learned is somewhat unpredictable and something the sprite needs to know for smooth animation. Most callback methods do not return anything, but we have the pauseOver method return an integer indicating the length of the next pause (which is always the same), or zero if we don't want any more callbacks. This solves a two-way communication problem. The timer must do the pausing (since it is the active object) and so must call the sprite when the pause is over, but only the sprite knows when it has finished moving, so the timer should stop. Use the timer class definition in Timer.java.

Here is a diagram showing how the system should work:

 

Thus we have the following CRC design:

Class MoveSprite
Responsibilities Draw the grid and walls, creates the sprite, and handles mouse press events.
Collaborators Sprite

Class Sprite
Responsibilities  Display the sprite, moves the sprite, and reports whether the sprite is moving.
Collaborators Timer

Class Timer
Responsibilities Call the sprite when a given time interval has expired.
CollaboratorsSprite

Complete the high-level design by making use-case scenarios and a UML design specification including all of the public members of each class. Show your design to your lab instructor before the end of the lab. If you have time, you may continue by beginning detailed code design.

 

Assignment

Implement your solution in several stages, testing (and saving) each one before coding the next.

Submit your source code packaged as a6.jar.