The purpose of this exercise is:
|
It's not enough to be able to loop, we need code that sometimes does one thing and sometimes does another. Hence the if statement.
public class Bounce{ public void animateBouncingCircle(){ Circle c = new Circle(); c.makeVisible(); // the canvas is 300 in size, and the circle is 30 in diameter. We // could hard-code this as 270 but this explains where the value comes // from. int maxSize = 300 - 30; for (int i = 0; i < getNumberOfSteps(); i++) { c.moveHorizontal(getHorizontalStep()); c.moveVertical( getVerticalStep()); animateStep(); } eraseObject( c ); } private int numberOfSteps; public int getNumberOfSteps() { return numberOfSteps; } public void setNumberOfSteps(int numberOfSteps) { this.numberOfSteps = numberOfSteps; } private int verticalStep; public int getVerticalStep() { return verticalStep; } public void setVerticalStep(int verticalStep) { this.verticalStep = verticalStep; } private int horizontalStep; public int getHorizontalStep() { return horizontalStep; } public void setHorizontalStep(int horizontalStep) { this.horizontalStep = horizontalStep; } } and another like this. public class BounceTest { public static void main(String[] args) throws InterruptedException { Bounce b = new Bounce(); b.setHorizontalStep( 1 ); b.setVerticalStep( 2 ); b.setNumberOfSteps( 2000 ); b.animateBouncingCircle(); Thread.currentThread().sleep( 2000 ); System.exit( 0 ); } } |
These classes should both be in the animate package. You will need to
put import statements in place also. Your code will still not compile because
you lack methods such as animateStep . Copy all the relevant methods from
Grow.java until your code compiles.
|
This is fine, but the Circle
falls of the edge of the Canvas
which is not what
we want. What would be nice is to change the direction of the Circle
when it
hits the edge. For this, we need two things. First, we need to know where the
Circle
object is and, second, we need a conditional statement.
public int getXPosition(){ return xPosition; } public int getYPosition(){ return yPosition; }
for (int i = 0; i < getNumberOfSteps(); i++) { c.moveHorizontal(getHorizontalStep()); // check here if getXPosition has got too large. c.moveVertical( getVerticalStep()); // check here if getYPosition has got too large. animateStep(); }
|
Our code now works, so it's worth creating a copy of it, so that we can go back to this version if necessary. Next thing is to change it!
One problem is that some of the code appears in both Bounce.java
and
Grow.java
. This is a pity; if we want to change the code, then we need to
change it in two places. So we are going to use inheritance to get around
this. You can read more about inheritance if you choose.
You should have three pieces of code in both places. We are going to move them
to a new class called Animate.java
.
private int animateStep; /** * Get the value of animateStep * * @return the value of animateStep */ public int getAnimateStep() { return animateStep; } /** * Set the value of animateStep * * @param animateStep new value of animateStep */ public void setAnimateStep(int animateStep) { this.animateStep = animateStep; } protected void animateStep() { Canvas.getCanvas().wait( 50 ); } protected void eraseObject(Object erased) { Canvas.getCanvas().erase(erased); }
public class Bounce extends Animate
|
It is easy with this exercise to underestimate the importance of inheritance;
all we have done is move code around, surely? But, we've also decreased the
total amount of code, as it's now in Animate.java
rather than both Bounce.java
and Grow.java
. With just two classes performing animation this is a small
advantage, but if we had 20 it would be a big advantage. Effectively using the
same code in two (or more) places is essential to modern programming.
As well as saving typing, it means that the code is more likely to be correct;
if we find a bug, we only have to fix it in a single place. If we add more
functionality to Animate.java
, it's automatically available to all the other
classes that extend it. So, for example, Windows 7 has some nice features
for managing windows like "extend the window to half the screen size" — very
useful if you have a big monitor. Every application built on windows gains
this function automatically, without having to be changed.
Inheritance is one of the building blocks of "object orientation". It's not the only way to achieve code reuse, but it is very common. Please read the java tutorial if you didn't the first time.
The two new files —
Bounce.java and BounceTest.java — and the two
modified files Grow.java and GrowTest.java are coursework for this exercise.
|
1. There are two small changes to the original code which you should be able to find. Don't worry about these too much.