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

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.

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:

  1. 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 the addDancer() method to add turtles you create to it. Call startAnimation() on the DanceFloor in order to start the animation.

  2. TwirlingTurtle

    The TwirlingTurtle (the green one in the above animation) is your most basic dancing turtle. A TwirlingTurtle should just turn 90 degrees in place for each step.

  3. 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 an int with a value of 1, a BACKWARD constant that is an int 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 to FORWARD, 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 about DanceStep.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, or enum. An enum 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 as DancingTurtle.DanceStep.FORWARD.

    Overall, your RoutineTurtle should take in a list of dance steps. Then in its step() 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.

  4. 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 Leaders 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 the TravelingTurtle might only be able to add one special follower.

  5. 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's addFollower() 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! FollowingTurtles 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.

  6. 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 class extend? What interfaces does it implement?.

    • 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 the moveFoward() 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 the moveForward() 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!

  7. 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, the addFollower() and removeFollower() methods should add followers to a list of followers who are given orders, so you can lead a whole troop.
    • In the step() method, your RoutineLeaderTurtle 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!

Some final notes:

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!

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.

Grading

This assignment will be graded on approximately the following criteria: