CS 161 Lab G - Bouncing Balls
Due Fri Mar 13 at the start of class
Overview
In this lab, you will modify an existing program in order to create an animation of a number of colored balls bouncing around in a box, changing properties (e.g., color, size, speed) when they hit the walls. Because there are too many balls to keep track of individually, you'll need to use an array
to track them all.
This lab should be completed in pairs. You will need to find a different partner than you had for the last lab. Remember to switch off who is driving and who is navigating!
Objectives
- To practice working with arrays: declaring them, instantiating them, and accessing them
- To review using for loops (particularly when working with arrays)
- To practice with graphics,
Color
, and implicit loops
Necessary Files
You will need to download and extract the BlueJ project from the BouncingBall.zip file. This project will supply you with the following classes that you will need to modify.
-
Ball
This class represents a Ball bouncing in the box. This class should be pretty familiar and straightforward. -
BallCourt
This class represents the box in which the Balls are bouncing. It handles all the moving and drawing of the Balls. You will need to make significant changes to this class (but ignore the stuff at the bottom).This class is acts like a graphics class, similar to the ones you've created and worked with in the past. Recall that the
public void paintComponent(Graphics brush)
method controls how the drawing appears on the screen.- You can start the animation program by instantiating a new
BallCourt
object (e.g., right-click on the class in BlueJ). You can also call the object'sstartAnimation()
andpauseAnimation()
methods, which do exactly what they sound like. - Remember, we let Java call
paintComponent()
for us when it makes a window appear--we never call it directly (either in code or through BlueJ)!
- You can start the animation program by instantiating a new
Assignment Details
In this lab, you will not need to write any new classes! However, you will need to modify the provided existing classes in order to add in extra functionality.
You can run the program by instantiating a new BallCourt
object. The easiest way to do this is to right-click on the class in BlueJ.
If you run the program without modifying anything, you should see a single red ball bouncing around on the screen:
Your task is three-fold: (1) replace this singleBall with a collection of multiple balls, (2) add the ability for the balls to have a random color, and (3) have the balls change when they hit a wall.
Part 1: Multiple Balls
Your first step is to modify the BallCourt
class so that the court has more than one moving ball.
-
The first thing you shuld do is modify the
BallCourt
's constructor so that it takes as a parameter the number of balls to display (numBalls
). You'll need to provide this value when you instantiate theBallCourt
. -
You'll need to declare and instantiate a new array of length
numBalls
(the constructor's argument) to hold your collection of balls. Think: should this be an instance or a local variable?-
Recall that you can declare a new array variable using (for example):
DataType[] arrayName;
and you can create a
new
array and assign it to that variable using:arrayName = new DataType[arrayLength];
- You may notice that there are "TODO" comments scattered around the class. These will tell you where to put your code. Make sure to delete the TODO comment once you've done the task!
-
-
The next thing you should do is fill your array with
new
Ball
objects! You should use a loop to go through each spot in the array (each room in the hotel) and make anew Ball()
to put in each room.-
Recall that you can treat spots in the array as regular variables, and assign values (including
new
objects) to them as such. For example:Robot[] myArray = new Robot[10]; //an example array of Robots myArray[5] = new Robot(); //assigns a new Robot to room 5
-
We also tend to use
for
loops to fill arrays, with thelength
of the array as our stopping condition. For example:for(int i=0; i < myArray.length; i++) { myArray[i] = new Robot(); //assigns a new Robot to every room! }
-
Recall that you can treat spots in the array as regular variables, and assign values (including
- This is a good time to switch drivers.
-
Next, modify the (bottom of the)
paintComponent()
method to use a loop to draw ALL of the balls on the BallCourt, rather than just the example singleBall. (Remember to stop drawing the singleBall!)-
You'll again want to use a
for
loop to go through the array ofBall objects
. Instead of calling getters() on the examplesingleBall
, you'll want to call them on thei
th item in your array. For example:myArray[i].getColor() //calls getColor() on the item in room i. //do something with this value!
Again, you can treat spots in the array as regular variables, and call methods on them as such.
-
Helpful hint: remember that you initialize Balls (create new ones) in the constructor, not in
paintComponent()
!
-
Helpful hint: remember that you initialize Balls (create new ones) in the constructor, not in
-
Remember to tell the
brush
to use the color of the ball, and to draw an oval for the ball in the correct spot! - When this is completed, you should be able to run the program and see a large number of red circles sitting on the screen.
-
You'll again want to use a
-
Finally, modify the (top of the)
paintComponent()
method to go through your array and tell eachBall
in the array to take a step. Remember to stop moving the examplesingleBall
; at this point you should just remove that variable entirely.- After you do this, you should be able to see all your red Balls moving and bouncing around the BallCourt! (Try testing your program using 25 balls--that's usually a pretty good number).
- This is a good time to switch drivers.
Part 2: Colorful Balls
This is great and all, but it will look better if we can change the color of the balls. Modify the Ball
class so that each Ball
is created with a random color.
-
If you go to the Ball class, you can see that they are all given a specific color in the constructor. This color is drawn from a constant at the bottom of the class called
PRETTY_COLORS
that is an array ofColor
objects (aColor[]
).- You can choose a random Color from this array by choosing a random number to use an as index into that array--it's like picking a random room number and going to that room to get the Color!
-
You can use the provided
Random
object'snextInt()
method to get a random number between 0 and the parameter. Think about what should be the lower and upper bounds of this random number. (Hint: think about the number of items in the array).-
Remember that you can figure out how many items are in an array by using the
.length
attribute. For example:int arrayLength = myArray.length;
-
IMPORTANT:
It is always better to be "general" and use the
.length
of an array, rather than trying to count the items and using a "hard-coded" number. After all---what happens if you decide to add more items (more colors) later? You'd have to remember where you hard-coded an item count and change that code as well! So much work...
-
Remember that you can figure out how many items are in an array by using the
-
After you've selected a random index (a random room), assign whoever is in that room in the
PRETTY_COLORS
array to be theBall
's color. - Once this works, you should be able to have lots of multi-colored balls bouncing around your BallCourt! How festive!
- Have you been switching drivers?
Part 3: Mutating Balls
There is one more step: in order to make things more interesting, modify the Ball
class further so that each Ball changes when it bounces off of a wall. Bouncing off one wall (your choice of which) should have the Ball change Color.
- Inside the Ball's
move()
method you should see logic for bouncing off a wall. Take a moment to look over the code and make sure you understand it. Add a few inline comments to note down what is going on! (This is good practice, and will help you out later). -
In addition to the current functionality, add code so that the Ball changes color when it hits one wall (your choice of which). This will involve picking a new color from the
PRETTY_COLORS
array and assigning that to the Ball's attribute. -
However, rather than picking a Color randomly, you should instead make it so that the Balls change color to the next Color in the array.
To do this, you'll need to keep track of the index of the current color--the
colorIndex
. Since you'll want to remember this across method calls, you will need to add it as an attribute of your Ball.-
Remember to make instance variables
private
, to declare them at the top, and then to assign values to them in the constructor. Think: do you already have some code that picks what the initial (random)colorIndex
should be?
-
Remember to make instance variables
- Whenever the Ball hits a wall, you'll want to increase this index by 1, and then change the Color attribute.
-
What happens when you increase the colorIndex so that it goes past the end of the list? You should make it so that the color starts over at the beginning of the list. You can cause the index to "cycle" by using an
if
statement (or by clever application of the%
operator). -
The logic of when to "cycle around" can get tricky! You need to make sure that you don't go outside of the bounds of array, but also that you start back at the beginning. Your Balls should be able to assume every color, from red to magenta.
-
Pro Tip: try testing your program by making a collection of only 1 Ball (so your
Ball[]
has a length of 1). This makes it easier to visually track if a single ball changes color. You can also (temporarily) give the balls a non-random color to help track what is happening.
-
Pro Tip: try testing your program by making a collection of only 1 Ball (so your
-
Hitting each other wall should also make some change to the Ball. For example, maybe
one wall makes it larger and one wall makes it small.
Or maybe one wall speeds up the Ball, and another slows it down. You are welcome to mix and match effects or come up with your own---but at least one wall needs to change the Ball's color!
- If you've got more ideas, you could even make it so that different halves of the wall produce difference changes! How might you add in this functionality?
- It is also possible to make different regions change the Ball--maybe the ball slows down when it nears the center of the BallCourt. Make this as interesting as you want!
Extensions
Here are some further options you might enjoy. Be sure to finish the main part of the program first!
- You might think about adding a bit more variety to the program. Maybe have the Balls be initialized with a random diameter (between 20 and 50 pixels looks nice). Maybe have the balls be more like ovals, with different widths and heights (this would involve changing your drawing code as well as your movement code, since you now bounce off the walls at different places!)
- Similarly, you might try "perturbing" the speed as you bounce off the walls, so that things aren't so uniform. Try adding a very small random value (that could be negative!) to the speed after you bounce. This should make it look like your balls have some "spin"
-
Challenging! I have provided an
isTouching()
method that you can use to determine whether one Ball is touching another. Can you modify your code so that the balls bounce off each other as well as the walls?- In your BallCourt class, instead of just moving each Ball, you'll also need to use another loop to run through the Balls again and have your first ball check if it is touching every other ball (though be careful that you're not bouncing off yourself!). If two Balls are touching, you'll want to use the
bounceOff()
method, which will change the Ball's direction and position to reflect a "bounce".
- In your BallCourt class, instead of just moving each Ball, you'll also need to use another loop to run through the Balls again and have your first ball check if it is touching every other ball (though be careful that you're not bouncing off yourself!). If two Balls are touching, you'll want to use the
Submitting
-
Make sure both of your names are in the JavaDoc comment on both of the classes you modified (
Ball
andBallCourt
). If your names aren't on your assignment, we can't give you credit! -
Right-click on the project folder you downloaded, then:
- If using Linux, select Compress...
- If using Windows, select Send to and then Zip file
- If using Mac, select Compress ... items
This will let you take the selected folder (or files) and generate a new compressed
.zip
file. -
Navigate to the course on Moodle
(Lecture Section A),
(Lecture Section B).
Upload your
.zip
file to theLab G Submission
page. Remember to click "Save Changes"! You may submit as often as you'd like before the deadline; we will grade the most recent copy. - While you're on Moodle, remember to fill out the Lab G Partner Evaluation. Both partners need to submit evaluations.
Grading
This assignment will be graded out of 20 points.
- [2pt] You have declared and instantiated an array of Balls in the BallCout
- [2pt] You have filled your array with Ball objects
- [1pt] Your paintComponent() method uses a loop to draw all of the Balls
- [1pt] You use the provided Graphics brush to draw Balls with the correct Color and location
- [1pt] Your paintCompnent() method uses a loop to move all of the Balls
- [2pt] Balls are constructed with a random color from the PRETTY_COLORS array
- [1pt] You have included descriptive inline comments explaining the Ball's
move()
method - [1pt] Balls change color when they bounce off of at least one wall
- [2pt] Balls change color in order, including all colors in the PRETTY_COLORS array
- [2pt] Balls change in some other way when they bounce off of the other walls
- [1pt] You use the
.length
attribute of an array rather than hard-coded sizes - [1pt] You have removed example code (e.g., the
singleBall
and TODO comments) -
[2pt] Your code shows proper style--including well-named variables (and lcvs) and
private
instance variables - [1pt] You submitted a lab partner evaluation