CSSE 220 – BallWorlds
Feel free to ask questions of your instructor, student assistants and classmates as desired.
Goals
The goals of this exercise are to:
- Learn about informal use of UML to communicate and brainstorm.
- Learn about inheritance and its benefits.
- Gain more practice implementing interfaces.
- Learn about visibility modifiers
The Exercise
Instructions Part 1 - Demo and Basic Specification
Your instructor will demo BallWorlds and discuss the basic spec with you.
Instructions Part 2 - Design
UML (Unified Modeling Language) diagrams are used primarily for two purposes. First, project designers use them during the design phase of larger projects to brainstorm relationships between classes. Second, they can then be used for communication: to convey the design to the implementors of the project. We are using UML for the second purpose here.
Study this diagram and answer the questions below. (Your instructor may have had you answer these in class or on a separate worksheet. If so, your work on this part is done.)
- What class starts the program?
- What two kinds of objects does that class create?
- What are the classes of the three objects instantiated by a SimulationPanel?
- What three interfaces are implemented by BallWorld?
- What three interfaces are implemented by Ball?
- Any class that implements the Drawable interface must have at least what two methods?
- What five classes must you implement for this program?
Instructions Part 3 - Get the starting code
Connect to your team repository to get the starting BallWorlds code. Your instructor will announce the teams in class.
Refer back to earlier projects if you need a reminder about how to connect.
Instructions Part 4 - Implement basic code for each kind of ball
You will write this project in stages. First you’ll get the basic animation working for each kind of ball. Then you’ll iteratively add additional features to the program.
In the stages below, we’ve included some questions to guide your thinking. You don’t need to answer the questions in writing, but answering them will help you think about how to implement the stage.
Note: You must take full advantage of inheritance in this project to get full credit!
Stage 1: Pulsar
A Pulsar is a ball that appears on the screen and smoothly varies from white to black and back again, repeatedly. It should appear in a random location with any reasonable size.
- A note in BallWorld’s UML class diagram indicates that every Ball must have a constructor that takes a BallEnvironment object. Per the UML diagram, what method of BallEnvironment might be useful for determining the size of the ball’s world?
- Look at the UML diagram for Ball. How many methods does it require that its subclasses implement?
- Based on the interfaces Ball implements, how many methods does it promise that it (or its subclasses) will implement?
- Which of the interface methods will Ball implement? Which does it leave for its subclasses?
- The framework calls Ball’s timePassed() method every 10 ms or so. Looking at the code for Ball, what methods does Ball’s timePassed() call?
- What methods must Pulsar implement?
- What fields should a Pulsar have?
Commit your work to the repository now!
Stage 2: Mover
A Mover should start in the exact middle of its world (regardless of its world’s size). Each Mover should have its own fixed velocity that is set at random when the Mover is constructed. The random velocity should be in any reasonable range that includes all directions (not just the “positive” direction). Each new ball type’s color should be different from colors of the Ball types that you already implemented.
- Recall that the framework calls Ball’s timePassed() method every 10 ms or so. What methods does Ball’s timePassed() call again?
- What methods must Mover implement?
- Ball provides a couple of protected helper methods for use by its subclasses. Which of these might be useful for implementing Mover?
- What fields should a Mover have?
Commit your work to the repos (last reminder, after this, you are on your own).
Stage 3: Bouncer
A Bouncer should behave just like a Mover, except that it bounces off the edges of its world. Remember, each new ball type needs to be a different new color.
- From the UML diagram, what class must Bouncer extend?
- Ball provides a couple of protected helper methods for use by its subclasses. Which of these might be useful for implementing Bouncer?
Stage 4: Exploder
An Exploder should behave just like a Bouncer, except that as it moves/bounces, it also:
- Step 1: picks a random size between 2 and 10 times its initial size, and slowly grows to that size.
- Step 2: When it reaches that random size, it dies (and hence is no longer in the world, hence is no longer drawn, etc.)
- Step 3: When it reaches that random size, it constructs two new Exploders, each starting where the original Exploder died.
- From the UML diagram, what class must Exploder extend?
- What method in the BallEnvironment interface might be useful for “killing” the old Exploder?
- What behavior does Exploder share with Bouncer?
- Don’t duplicate code! Instead, move the shared code for Bouncer and Exploder into AbstractBouncer.
Instructions Part 5 - Iteratively extend the behavior
The four buttons to create new balls should all work now, as should the button to pause and resume the entire world. In the remaining stages of the project you’ll implement mouse-based features for individual balls, including: pause/resume, killing, and dragging.
Stage 5: Pause/Resume individual balls
When the user clicks a world, the nearest Ball should pause. That is, all motion of the Ball should cease. Pulsars shouldn’t pulse, Movers shouldn’t move, Bouncers shouldn’t bounce, and Exploders shouldn’t explode. Unless the nearest Ball is already paused! In that case, the Ball should resume its normal animation.
- What class implements both MouseListener and MouseMotionListener (and hence responds to mouse events)?
- The BallWorldComponent’s BallWorldMouseHandler responds to a mouse-press by selecting the Ball nearest the mouse (and showing this by turning that Ball cyan while the mouse is pressed).
- The BallWorldMouseHandler responds to a mouse-left-click by telling the selected Ball to toggle between the paused and not-paused state.
- The Temporal interface specifies the methods that BallWorldMouseHandler uses to communicate with the selected Ball. What methods in Ball must you implement or modify to handle pause/resume?
- What other class implements the Temporal interface? You might look at how it implements the required methods for some ideas.
- You don’t need to deal with the mouse directly. The provided code does that for you. For example, setIsPaused() is called on the nearest ball whenever the user clicks the mouse. You just need to properly implement the Temporal interface in Ball and all your balls should pause and resume correctly.
Stage 6: Kill individual balls
When the user right-clicks a world, the nearest Ball should be killed. That is, the Ball should disappear, never to be seen again.
- Like for pause/resume, the BallWorldMouseHandler takes care of signalling to the Ball that it should die.
- What method of Temporal should you finish implementing in Ball to kill it?
- What method from BallEnvironment might be useful?
- You should only need to change Ball. All the individual kinds of Balls should inherit the changed behavior!
Stage 7: Handle mouse drags
When the user drags on a world, the nearest Ball should move with the mouse. When the user releases the mouse button, the Ball should remain where it was “dropped” and be paused. (The user can click again to make the Ball resume its animation.)
- Like for pause/resume and dying, the BallWorldMouseHandler takes care of signalling to the Ball that it should move.
- What method of Relocatable should you finish implementing in Ball to make it, well, relocatable?
- You should only need to change Ball. All the individual kinds of Balls should inherit the changed behavior!
Bonus: “Implementer’s Choice”
For bonus points, you can design a Ball with its own special properties, extending the appropriate abstract class, or introducing new abstract classes for any shared behavior. You can certainly override methods of Ball to interesting effect. Triangles anyone?
Bonus points will vary from just a couple points for something that basically just copies something else that a ball can do (like just using random colors), up to 20 for something really original, cool-looking, and non-trivial!
Turning in your work
Don’t forget to commit your final project!