Graphic by Keith Ohlfs
CS111, Wellesley College, Fall 2001

Problem Set 10

Part I is due on Tuesday, December 4, at 11pm

Part II is due on Tuesday, December 11, at 11pm

[CS111 Home Page] [Syllabus] [Assignments] [Documentation] [FAQ] [CS Dept.] [CWIS]

How to turn in this Problem Set

Before submitting your work, make sure that all the files have been saved and the projects compile and run as they should. After submitting your work, make sure to doublecheck that all the files have been uploaded correctly. If you need directions on how to submit your work or how to check whether the submission was successful, please click here. Please make sure to keep a copy of your work, either on a zip disk, or in your private directory (or, to play it safe, both).


Part I. Building your own objects

Building a Class: The Fish class

In lecture we discussed how to create a simple class definition, using instance variables, a constructor method definition and instance method definitions. The instance variables keep track of the state of each instance of the class, the constructor method initializes the state of each instance as it is created, and instance method declarations define methods that instances of the class can carry out. We also discussed using the graphics methods from the Java abstract windows toolkit library. Today you will combine these to build your own Fish class. You will write a program that has two classes. The Fishtank class contains the code that will create fish objects and invoke fish methods to change their color, size and position. The Fish class definition will define fish objects according to their instance variables, constructor method and instance methods. In the end you will have an applet that looks like this:

Getting Started: Defining a generic fish object

Download the ps10_programs folder from the CS111 download folder. In the Fishtank folder, look at Fishtank.java file. Notice the stubs for the two class definitions: Fishtank and Fish. The Fishtank class already has the stub of the paint() method that we will use for manipulating fish objects. Our first task is to write code for the Fish class that will produce a fish object in response to the following statement in the paint method:
        Fish freddy = new Fish(g);
The Fish object will be drawn as follows:

In order to accomplish this, we must complete 3 steps:

  1. Define the instance variables
  2. Define the constructor method
  3. Write an instance method to draw the fish.

Defining the Instance Variables

You should make your fish object so that a fish is defined by the following variables:
int length The length of the entire fish
Point position The position of the upper left corner
Color fishClr The Color of the fish body
Color tailClr The Color of the fish tail
Graphics gfx The graphics object for drawing to the applet window

Define these variables at the top of the Fish class. Make them private variables. Do not assign any values to them. Thus, the variable declaration for the position variable will be as follows:

        private Point position;

Defining the Constructor method

The constructor method should initialize the instance variables to default values when a fish object is created. You should write code in the constructor method to set the following defaults for the Fish objects:
length 100
position (1,1) (note that this is a point object)
fishClr Color.red
tailClr Color.green
gfx g (the parameter given in the method invocation)

To make these assignments, recall that we refer to the instance variables within the class using the keyword "this". Thus, we can set the value of the "postion" variable as follows:

        this.position = new Point(1,1);
To draw correctly to the applet window, the fish object needs to have access to the Graphics object from the paint method. The easiest way to do this is to use a parameter in the constructor method (this is the "Graphics g" parameter in the method definition). The fish object can keep track of this object by assigning its value to the "gfx" instance variable, as follows:
        this.gfx = g;
Fill in the other assignments for the length and colors of the fish.

When we create an instance of the fish class, we would like to have it drawn in the applet window. We can do this by invoking the "drawFish()" method from within the constructor method.

        this.drawFish();
Make sure you put this statement after the statements initializing the instance variables! (This doesn't do anything yet, we have to write the method first).

Writing the drawFish() method

Now you are ready to write the drawFish method. This method should draw a fish according to the following format:

In the above diagram, x and y refer to the x and y components of the "position" variable. They indicate the upper left hand corner of the bounding rectangle for the fish. They can be accessed in your class definition by the expressions "position.x" and "position.y". The red body should be colored in the color specified by the instance variable fishClr and the green tail should be colored according to the instance variable tailClr.

Use the java graphics methods: drawOval, fillOval, Polygon(), fillPolygon, and drawPolygon to draw the fish above. When you are finished, you should be able to include the statement:

        Fish freddy = new Fish(g);
in your paint method and have the fish appear in the applet window.

Instance Methods for the Fish Class

Now you are ready to write some methods that your fish can understand. You will write methods that set the body color, the tail color, the position of the fish, and the length of the fish. The methods names are as follows:
                public void setFishClr(Color c)
                Set the body color of the fish to c.  Redraw the fish with
                the new color.
                
                public void setTailColor(Color c)
                Set the tail color of the fish to c.  Redraw the fish with
                the new color.
                
                public void setPosition(Point p)
                Clear the current fish drawing and set the new fish position
                to be the point p.  Redraw the fish at point p.
                        
                public void resize(int size)
                Clear the current fish drawing and set the length of the fish 
                to size (note that this is specified in number of pixels). 
                Redraw the fish in the new size.
                        
                public void clearFish()
                Clear the fish from the screen.
In each method you must assign a new value to the appropriate instance variable and then redraw the Fish. In the setPosition and resize methods you must clear the old fish from the screen before you change the values of the instance variables. To clear the fish, you should write the instance method "clearFish()". clearFish() clears the fish by drawing over the current fish in the color white. For the purposes of this assignment, you can make the clearFish() method nearly identical to the drawFish() method except for the changes in the drawing colors. As you write each instance method, test it out by invoking it from the paint method in the fishtank class. For example, you can test the setPostion method by invoking:
        freddy.setPosition(new Point(100,200));

Creating Multiple Fish

You can now create multiple fish and change their characteristics from the paint() method in your fishtank class. Inside the paint method create 5 fish: freddy, felicia, frances, frank and franny. Use the Fish instance methods to change the state of these fish as follows:
Fish fishClr tailClr position length
freddy default default (50,100) default
felicia green yellow (100,200) 50
frances cyan magenta (175,150) 25
frank blue red (225,125) default
franny magenta cyan (75,250) 200

If you have completed the assignment correctly, your applet should look like the first figure above.

Part II. Java from scratch: creating your own applet

How to create an applet in CodeWarrior

  1. Start CodeWarrior by selecting it from the Apple menu.
  2. Choose New... from the File menu. A window will pop up, as shown below. Select "Java Stationary" as the kind of your project, and type in a name with the extension .mcp. Then click OK.
    Note that the extension .mcp is required for a project name. Otherwise the file will not be recognized as a project by Fetch.

  3. A new window will pop up giving you choice between 3 versions of Java. Click on JDK1.1 and select Java Applet. Then click OK.

  4. As the result, a new folder will be created on your Desktop which has the same name as the project, only without the .mcp extension. We call this folder a project folder. The project is created with three standard files: TrivialApplet.html, TrivialAppletDebug.html, and TrivialApplet.java. Remove these files from your project by dragging them from the project window to the trash. Note that deleting these files from the project does not automatically delete them from the project folder. If you want to delete them from the folder, double-click on the folder to open it, and then drag the files into the trash.
  5. In the CodeWarrior choose New Text File from the File menu. A new untitled file will open. You need to create two files: the HTML file that specifies which class to run and the JAVA file. Your HTML file can have any name and (for this project) it will look like this:
    
    <TITLE> Moire Patterns Applet </TITLE>
    
    <applet codebase = "Java Classes" code = "Moire.class" width = 400, height = 400>
    </applet>
    
    Type this code into the new file and save it in the project folder. You can give it any name with the extension .html.
  6. Create another new file called Moire.java and save it in the project folder. The name of this file must be the same as the name of the class that it defines (only with the .java extension), and in our case the class is Moire.class, as specified in the HTML file above.
  7. Now it remains to add the two new files to the project. To do this, open the project folder and drag the file Moire.java into the project window in the folder Sources. A window will pop up asking you to confirm that you are adding the files to the project's targets.
  8. The same way add the HTML file that you have created, also to Sources. In the end the project window should look like this:

    Now your project is created. Write your code in the Moire.java file. Happy programming!
What if you made a mistake and your project does not have the right files, or the files are not in the project folder? The easiest way to fix it is to create a new project from scratch. To do this, quit CodeWarrior and drag the entire project folder to the trash. Then start from Step 1 above.

Now, when you have created your project, here is the problem that you are going to solve:

Moiré patterns

  1. Create a new Applet named Moire. Make sure to import the packages java.awt.* and java.applet.Applet. Add the following code to the method paint and test the program:

        int width = 400;
        int height = 400;
        g.drawOval (0, 0, width, height);
    
  2. Look at the code below and draw a sketch of what you expect it to do. Here (x,y) is point at the upper left corner of the figure, and height and width are the height and width of the figure (this is a standard format of graphics method).

    public static void moire (Graphics g, int x, int y, int width, int
    height) {
        int i = 1;
        while (i<width) {
            g.drawOval (x, y, x + i, y + i);
            i = i + 2;
        }
    }
    
  3. Add the method moire to the Moire class and replace the invocation of drawOval() in paint() by a single line that invokes moire.
  4. Run the program. Did you get what you expected? For a partial explanation of what is going on, see the following:
  5. Modify the method so that the space between the circles is larger or smaller. See what happens to the image.
  6. Change the method moire so that the circles are drawn in the center of the screen and concentric, as in the following figure. Unlike in the figure, the distance between the circles should be small enough that the Moiré interference is apparent.

  7. Write a method named radial that draws a set of line segments as shown in the figure below.

    Replace the invocation of moire() in paint() by invocation of radial().
  8. Once you get radial() to work, adjust the spacing between lines to create a Moiré pattern.