Graphic by Keith Ohlfs |
Friday, December 3 by 4:00 p.m. |
Note: You can find copies of Core Java and An Introduction to Data Structures and Algorithms in the E101 library as well as in the Science Library. Make sure you get a copy of Core Java that describes the JDK 1.0.2 version of the Java Abstract Window Toolkit. The 1.1, 1.2, and 2.0 versions of the toolkit differ in significant ways from the version supported by Cafe.
The purpose of this problem set is several-fold. The first is to practice building your own objects from scratch. Instead of extending pre-existing classes, you will be defining your own original class. You will get a chance to work with simple graphics in Java.
You currently know enough to do Problems 1 and 2 on this problem set. You will need to go to lecture on Wednesday, November 24, to be able to do Problem 3. (Problem 3 has not even yet been posted, but will be in the near future.)
By the end of this assignment, you will have built a small-scale variation of an applet world similar to BuggleWorld (though don't worry -- not nearly as complex!). What you will see will take you through building applets in Java from scratch.
Softcopy submission: Save the modified FishWorld.java file
in the ps9_programs folder. Upload the entire folder
(including all the other .java
and .class
files -- everything) to your ps9 drop folder.
Hardcopy submission: Turn in only one package of hardcopy materials. Staple your files together and submit your hardcopy package by placing it in the box outside of Lyn's office (121B, behind the mini-focus consultant's desk). Your package should include printouts of
Fish.java
from Problem 2 and 3
FishTank.java
from Problem 2
FishWorld.java
from Problem 3
Reminders
The purpose of this problem is to give you some practice drawing object diagrams. Recall that an object diagram shows a collection of interconnected class instances. Each instance is drawn as a large box that is labelled by the class name and contains the labelled instances variables of the class. Each variable is a small box that contains either a primitive data type (e.g., int, double, boolean, char) or a pointer to another object. These are in the style of Object Land from earlier in the semester.
Please note that these are not the same as the Box-and-Pointer diagrams we have been using lately.
Consider the following Java class declaration:
class Node { public int value; public Node left; public Node right; public Node (int v, Node l, Node r) { this.value = v; this.left = l; this.right = r; } }
The Node class specifies that instances of the node class have three instance variables: a value variable that holds an integer, and variables left and right that hold pointers to other Node instances. The Node constructor takes an integer and two Node instances and intializes the instance variables with these values.
Here is a sequence of statements that creates and manipulates Node instances:
Node a = new Node(1, new Node(2, null, null), new Node(3, new Node(4, null, null), null)); a.left.right = a.right.left; a.left.left = a; Node b = a.left; b.left.value = a.left.value + b.right.value;
Recall that null denotes the null pointer, a special value that can fill any variable of object type in place of a pointer to an object of that type.
In this problem, you are to draw a single object diagram that depicts the variables and objects created by executing the above five statements. Your diagram should include the local variables a and b as well as all of the Node instances that are created. It should show the state of all variables and objects at the end of the execution of the five statements.
Follow these conventions:
The purpose of this problem is to practice both building your own objects and creating simple graphics.
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. In this problem, 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:
Please note in advance that the coordinate system of points for Graphics starts in the upper left corner. The x-coordinate still goes across from left to right. The y-coordinate, however, goes from top to bottom. So Point (0,0) is in the upper left corner rather than the bottom left, and Point (0, 200) is somewhere down the left side of your drawing area.
Download the ps9_programs folder from the CS111 download folder.
Open the "Fish" folder. Open the Fish.proj file. Look at the
FishTank.java file. You will see the pieces which will call your
original Fish once you have defined it. You will also see the
paint
method which you will need to change later in this
problem.
Also look in the Fish.java file. Notice the stub for the Fish class definition. You will define your Fish class here to be able to do all the things needed for Problem 2 and 3.
The Point objects used in this assignment are the same as those used in BuggleWorld. That is, they are objects with two coordinates (x and y) that are accessible as public instance variables. For example, if myPoint is a particular point, then its coordinates are written myPoint.x and myPoint.y. However, note that the Java graphics coordinate system is different than the BuggleWorld coordinate system.
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 fred = new Fish(g);
The Fish object will be drawn as follows:
In order to accomplish this, we must complete 3 steps:
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 bodyColor |
The Color of the fish body |
Color tailColor |
The Color of the fish tail |
Graphics gfx |
The graphics object for drawing to the right part of 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;
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) |
bodyColor |
Color.red |
tailColor |
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 "position" variable as follows:
this.position = new Point(1,50);
To draw correctly to the applet's Canvas, 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's Canvas. 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).
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 bodyColor and the green tail should be colored according to the instance variable tailColor.
Use the java graphics methods: drawOval, fillOval, Polygon(), fillPolygon, and drawPolygon to draw the fish above. Notice that the Fish has a black outline around the body and around the tail. You will need to draw a black oval and black Polygon over your initial filled oval and filled Polygon in order for the outline to be visible on top of the colors. Remember that the most recent thing drawn is on top.
Because of the way Java graphics work, draw and fill do not have the exact same placement once they are drawn. In other words, they do not overlap exactly. What this means for you is that when you are drawing your Fish, the border needs to be on top of the filled shape, and when you are making your clearFish() method, you will need to clear the filled shape and the border separately in order to completely "erase" the previous Fish.
When you are finished, you should be able to include the statement:
Fish fred = new Fish(g);
in your paint method and have the fish appear in the applet window.
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 setBodyColor(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:
fred.setPosition(new Point(100,200));
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: fred, felicia, fran, fay and fanny. Use the Fish instance methods to change the state of these fish as follows:
Fish |
bodyColor |
tailColor |
position |
length |
fred |
default |
default |
(50,100) |
default |
felicia |
green |
yellow |
(100,200) |
50 |
fran |
cyan |
magenta |
(175,150) |
25 |
fay |
blue |
red |
(225,125) |
default |
fanny |
magenta |
cyan |
(75,250) |
200 |
If you have completed the assignment correctly, your applet should look like the first figure in Problem 2.