CS 261 Homework 2 - Dancing Turtles
Due Wed Feb 05 Thur Feb 06 at 11:59pm
Overview
In this assignment, you will be creating a graphical animation of a turtle dance party. There can be lots of different kinds of dancers at the party--but since they all share some characteristics (e.g., they are all dancing turtles), you can use inheritance to easily create the program and avoid code duplication.
A sample dance party is below: Notice all the different kinds of dancers. In the center are a large group of turtles dancing a pre-specified routine--specifically, the red turtle is dancing the routine and all of the orange turtles are copying her. The black and pink turtles are dancing back and forth across the floor, and the green turtle is just twirling in the corner. Your program will be able to support all of these turtles (and more!)
This assignment should be completed individually. You are welcome to ask for help from me, or from your classmates (following the Gilligan's Island rule)!
Objectives
- To practice with inheritance and interfaces
- To review working with collections and graphical systems
- To explore a few new ways of structuring Java classes
Necessary Files
You will need a copy of the Hwk2.zip file which contains a few classes to get you started. You will need to extract these classes and import them into Eclipse.
-
DancingTurtle
This abstract class (we'll talk about what that means) will act as the basis/parent class for your specific kinds of dancers. This class provides a number of methods to help you quickly get turtles to appear and move, such as: themoveForward()
,moveSide()
, andspinRight()
methods. By extending this class, all your dancing turtles will have access to these methods, without you having to write them!Note that as an abstract class, you cannot instantiate this class directly. Instead, you will need to extend it and instantiate its children classes. However, you can re-use code from this class's constructors by calling the parent's constructor using
super(<params go here>)
.Your inheriting classes will need to implement the abstract
step()
method inherited fromDancingTurtle
in order to give the turtle instructions on how to dance (an "abstract" method means that it is listed as something that children need to support, but the details aren't given. We will talk about this more as we go). Thestep()
method specifies what dance step the turtle performs at each frame of the animation.You are not required to modify this class; however, if you add new functionality or helper methods that are accessible to all DancingTurtles, you may want to put them in this class. If you make any modifications, be sure to describe them in the README!
-
DanceFloor
This class will provide the graphical window and animation system to make your turtles dance. You are welcome to look through its code, though you should not modify it. Check the documentation for methods that you may use: in particular,addDancer()
will let you add turtles to the dance floor, andstartAnimation()
will start them dancing.
Finally, the project contains a README.txt file that you will need to fill out--be sure and answer the questions thoroughly for full credit.
Details
First, read through all of the assignment carefully. As you do so, think about what kinds of classes and functionality you may need to create, and how those data structures will interact.
For this program you will be making many new classes: specifically ones representing specific kinds of dancers. Many of these classes will extend
either DancingTurtle
or each other. I will describe each class you need below:
-
DanceTester
The first thing you should do is make a tester class to test and run your program as you develop it. Your tester should instantiate a
DanceFloor
and then use theaddDancer()
method to add turtles you create to it. CallstartAnimation()
on the DanceFloor in order to start the animation. -
TwirlingTurtle
The
TwirlingTurtle
(the green one in the above animation) is your most basic dancing turtle. ATwirlingTurtle
should just turn 90 degrees in place for each step. -
RoutineTurtle
The
RoutineTurtle
is much more complicated. This turtle follows a specified routine, performing one step of the routine at each step.A routine should be specified as a list of steps (consider: would it be easier to use an array or an ArrayList?). You should specify this list and then pass it as a parameter to the
RoutineTurtle
's constructor.-
But how to specify the list? One option would be to make it a list of Strings (e.g., ["forward", "back", "left", "right"]). However, a cleaner way to do this would be to use constants: for example, you might make a
FORWARD
constant that is anint
with a value of 1, aBACKWARD
constant that is anint
with a value of 2, etc. This makes it fast and easy to check which step you're on: if the step in the list is equal toFORWARD
, then you can moveForward(). Thus means you can write routines as[FORWARD, BACK, LEFT, RIGHT]
, without needing to compare Strings (since String comparison is much slower than integer comparison). We could even make a separate class to hold these constants, that way we'd be able to talk aboutDanceStep.FORWARD
, which is nice and readable.But since the separate
DanceStep
class would only hold these constants, it's a bit overkill to define an entire class. So instead,DancingTurtle
contains I've included an enumerated list, orenum
. Anenum
is like a mini-class that just contains a number of constants (the constants don't have specified values, we're just using them as a "list" of different values). This "enum class" is part of the DancingTurtle class, so you can refer to a particular dance step such asDancingTurtle.DanceStep.FORWARD
.
Overall, your
RoutineTurtle
should take in a list of dance steps. Then in itsstep()
method, you should get the next step in the list and perform that. When you get to the end of the list, go back to the beginning!- You will need to keep track of which step you're on in the list, and then increment this counter each time you take a step. Hint: the modulo operator is a good way to cycle around! Try using math like
i = (i+1)%listSize
. - Extra Hint: the rest of the program will be slightly easier if you increment the step you're on BEFORE you perform it. So get the next step, then do that step. This means that you'll need to initially start at the -1th step, so that you can start by incrementing to 0 and then do the 0th step.
- For moving, stepping 25 pixels at a time ended up working well for me, but you can of course change that. Try using a constant or a variable to specify the distance you move, instead of hard-coding it as a "magic number".
This turtle can be complicated, so be sure to test him thoroughly! Note that your routine will be specified in the tester and then passed to the turtle.
-
-
Leader
You'll need to enable some turtles to lead other turtles (to give the other turtles directions about what dance steps to do). But you'll want multiple different kinds of turtles to be able to lead. As such, you will need to make a
Leader
interface that other classes can implement.Remember that interfaces only have method signatures, not method definitions. And then any class that implements the interface must define those functions. You're specifying that all
Leader
s can perform certain functions (methods)---the interface describes what those functions are.Your interface may include methods such as the following methods:
-
public Point getLocation() //so the leader can report its position to its follower(s); this is helpful for positioning
-
public Point getDirection() //so the leader can report its facing to its follower(s); again, this is helpful for positioning
-
public void addFollower(DancingTurtle) //so the leader can add a follower (who it will give steps to).
-
public void removeFollower(DancingTurtle) //so the leader can remove a follower
Note that these methods can be inherited, which counts as being defined (since the child does have that method--even if they just got it from the parent!).
Again, each leader might implement these differently. So the
RoutineLeaderTurtle
might be able to add multiple followers so it can lead a whole troop, while theTravelingTurtle
might only be able to add one special follower. -
-
FollowingTurtle
In order to have a Leader effectively lead, it will need a follower. So you will need to make a
FollowingTurtle
(the pink and orange turtles in the above graphic) that is intended to follow a leader.-
You should include a constructor for this turtle that takes in a
Leader
as a parameter. The follower should then set its position and facing to be immediately opposite of the Leader (75 pixels away from the leader's position was a good number for me). The constructor could also call the Leader'saddFollower()
method to add itself to the leader!- Note that you may want other constructors as well that do NOT put the follower immediately in front of the leader---such as for making the line dancing turtles shown in the animation.
- This turtle will need to define the
step()
method (why?), but this method shouldn't do anything!FollowingTurtle
s only move when ordered to by their leader; they do not step on their own!
Be sure and test that the follower shows up on the dance floor and doesn't do anything without a leader.
-
You should include a constructor for this turtle that takes in a
-
TravelingTurtle
The
TravelingTurtle
is a turtle who leads its dance partner across the floor, turning around when they get to the far side (the black turtle in the above graphic, who is leading the pink follower). What classes does this classextend
? What interfaces does itimplement?
.- Start by making the basic constructors and filling in the required methods (just like with the previous turtles); test that you can make your TravelingTurtle show up!
- Once that works, fill in the
step()
method to have the turtle walk across the floor. When it hits the other side (which you'll know because themoveFoward()
method will return false), have it start walking backwards! - The turtle will also need to give instructions to the follower. If it doesn't have a follower, it might just stand still (or travel on its own; either way!) In your
TravelingTurtle
's step() method, you will also need to tell its follower to move in a certain way by calling the appropriate methods on that object. For example, if you want your follower to step forward, you will call themoveForward()
method on the follower. Note that you can't just call the step() method (why? not) -
In order to get your very own Fred & Ginger to waltz across the floor, consider the following algorithm:
if I'm walking forward tell the follower to step backwards if the partner cannot step backwards change movement direction otherwise step forward after the follower otherwise if I'm walking backward step backwards if I cannot step backwards change movement direction otherwise tell the follower to step forward after me
You can also make further changes to this: can you avoid pausing at the edges of the wall? Can you get the pair to spin around as they walk (like a in a Viennese waltz)?
Make sure to test this turtle carefully. Be especially watchful for what happens when you hit a wall; note that turtles don't move via the the moveForward() method if they hit a wall!
-
RoutineLeaderTurtle
The last turtle is the
RoutineLeaderTurtle
, who can lead multiple followers in a routine--such as the red turtle in the above graphic. This turtle should take a step from a routine, and then tell all its followers to perform exactly that step. Think: what class should you inherit from? What interface should you implement?- You will need to implement all of the methods in the
Leader
interface. In particular, theaddFollower()
andremoveFollower()
methods should add followers to a list of followers who are given orders, so you can lead a whole troop. -
In the
step()
method, yourRoutineLeaderTurtle
should first do the routine exactly like its parent! You should do this by calling the parent's step() method. This will allow you to reuse the parent's method and functionality without needing to rewrite code--instead just extending that functionality.- After you have done a step (using the parent's method), you should go through your list of followers and tell each of them to take that same step. You may consider abstracting the "perform a DanceStep" functionality into a separate helper method to avoid code duplication.
You can test this turtle by making followers and checking that they all dance in sync!
- You will need to implement all of the methods in the
Some final notes:
- Be sure and test all your turtles! They should be able to dance and play without any problems :)
- Be carefully about using good Object Oriented style: keep in mind coupling and cohesion, and try to avoid code duplication. Inheritence means that we can re-use code easily, but we want to make sure that we're only giving functionality to classes that should have it (i.e., don't put everything inside DancingTurtle, because a DancingTurtle can't do everything!). Remember that calling parents' methods is a good thing!
- Include a Javadoc class comment on each of your classes (including the tester!) You should also include comments on each method. Documentation is important!
- Remember to include lots of inline comments that explain your code (the why, not the what). This is a big program, and comments will help both you and me to not get lost.
Timeline
This assignment is sizable, bigger than the last and closer to the normal size of our assignments. There are a lot of parts (though each part may be somewhat small). GET STARTED EARLY so you don't run out of time!
- You should get your first turtle (the Twirler) implemented on Day 1--make sure you can do basic inheritance!
- The RoutineTurtle may take a day or two, but it should definitely be done by Thurs 01/30.
- Adding the Leader, FollowingTurtle, and TravelingTurtle shouldn't be too difficult by this point, and you should be able to get them done over the weekend, by Mon 02/03.
- You can then add the RoutineLeaderTurtle and any extensions, as well as clean up documentation and stuff, by the due date on Wed 02/05.
Time is going to be tight on this assignment, so don't put it off!
Submitting
BEFORE YOU SUBMIT: make sure your code is fully documented and functional! If your code doesn't run, I can't give you credit! Your name should be in the class comment at the top of each class.
Submit your program to the Hwk2 submission folder on hedwig, following the instructions detailed in Lab A. Make sure you upload your work to the correct folder!. You should upload your entire src folder with all your classes. Your tester should show off all your dancers! Also Be sure to complete the provided README.txt file with details about your program.
The homework is due at midnight on Wed Feb 05.
Extensions
There are many extensions to this assignment. Completing them can earn you up to 5 points of extra credit.
- The provided "turtles" are pretty simple artistically--they actually look more like bugs. You might change the draw() method of the DancingTurtle class to draw more interesting turtles. Remember that turtles can face in one of four directions, which should be clear from your drawing!
- You might add further custom turtles: I mentioned the Viennese waltz before, but you also might make a traveler that circles the room, or maybe does some other crazy kind of dance (that ISN'T just specified through a routine!)
- Can you make the turtles dance in a conga line? You might have a CongaTurtle class that is both a Leader AND a Follower! Notice that followers won't turn at the same time as the leader, but instead will turning a step later.
- Another fun set of dancers might "cut in" and steal a follower from another leader.
Grading
This assignment will be graded on approximately the following criteria:
- You have a working TwirlingTurtle [5%]
- You have a working RoutineTurtle, who follows a specified routine [20%]
- You have a Leader interface that is used by other classes [5%]
- You have a working FollowingTurtle that can position itself opposite the leader [10%]
- You have a working TravelingTurtle who will lead its partner across the dance floor [20%]
- You have a working RoutineLeaderTurtle who can lead multiple followers in the routine [15%]
- You have a tester class that shows off all your dancers! [5%]
- Your code is carefully documented, with good Javadoc methods and inline comments [5%]
- Your code demonstrates good OOP style [5%]
- You have completed the included README.txt file [10%] <<< note that this is worth more than normal!