Lab 5: Bouncing Balls
CS 145: Images and Imagination, Spring 2014


Due Date:
Final submission is due Wed, March 12 before class.
This lab is worth 20 points
See policy page for late penalties.

Summary of Goals

The main goals of this lab are to:

Dropping a Ball

Program 0 is a very simple example of an animated ball. The ball drops down vertically. When it reaches the bottom, it is reset to be at the top again. Run the code to see what it does.

Program 0: Single Ball Drop

int y;       // y location of ball
int dy = 3;  //  Amount y is incremented at each step
int x;       // x location of ball

void setup() {
   size(200,400); 
   x = width/2;
   y = (int) random(width);
}

void draw() {
   background(0);
   ellipse(x, y, 15,15);
   y = (y + dy) % height;  // update height
}

Array Basics

The above program would be a lot more interesting if we could have a lot of balls all moving independently. One way to do this for would be to declare multiple variables:

int y1, y2, y3, y4;
int x1, x2, x3, x4;
As you might expect, this can get a bit tedious if you have a lot of balls, e.g. 100 balls. Arrays are data structures used in most programming languages that allow one to create lists of variables of the same type.

The program below shows how you can declare, create, initialize, and use an array. It is important that you understand each of these concepts and terms, so carefully study what each part of the code does and how the syntax works. We will also go over this in class.

Program 1: Array Basics
size(400,400);

// declare and create an array of 10 floats
float x[] = new float[10];

// initialize the values in the array 
for (int i = 0; i < x.length; i++) {
  x[i] = random(width);
}

// print the values of the array
for (int i = 0; i < x.length; i++) {
  println("i="+i+":  " + x[i]);
}

fill(255,0,0);
// use the array to set the x location of ellipses
for (int i = 0; i < x.length; i++) {
   ellipse(x[i], i*40, 10,10);
}

Returning to the ball drop example, the program below uses an array to store the y location of 20 balls. Run the code to see what it does. The red lines of code highlight the declaration, creation, initialization, and update of the y array.

Program 2: Multiple Ball Drop
// This program draws n balls evenly spaced across
// the window.  The balls move vertically down. 
// When one hits the bottom, it resets back to the top.

int[] y;        // declare array to hold y-values of balls
int n=20;       // number of balls
int dx;         // x spacing between balls
int dy = 3;     // rate of falling

void setup() {
  size(200,400); 
  
  dx = width/n;    // divide width by number of balls
  
  // Create n spaces to hold y-values
  y = new int[n];  
  
  // Initialize the y values.
  for (int i = 0; i < n; i++) {
      y[i] = (int) random(height);
  } 
}

void draw() {
  background(0);
  for (int i = 0; i < n; i++) {
    ellipse(i*dx, y[i], 15,15);
    y[i] = (y[i] + dy) % height;  // update y-values
  }
}

One can modify the above program to include arrays for storing other characteristics for each ball such as the color, the x value, the dx and dy etc.

Try this on the code above: Modify the above code so that the rate at which each ball falls (currently determined above by dy) varies for each ball. To do this, you need to introduce a new array, e.g.

 int dy[]; 
Place this just below "int[] y;" near the top of code. And then for each subsequent red line of code in Program 2, you need to add an additional line for dy which is similar to the red code for y. Also, the dy in the last red line of code needs to be modified to be dy[i].

Program 3: The program below is a much more complicated version of the previous program. Here, we store the x and y locations and the x and y rate of change. The balls change direction when they hit the wall. This is also an example of an event-response situation. An event (hitting the wall) triggers a response (change in direction). The event could be any number of things such as a ball hitting another ball or the user clicking the mouse. The events could also be any number of things such as changing the ball's color or size. One could also have a sound play.

Program 3: Multiple Ball Bounce
// Simulates 10 bouncing balls
int maxNum = 10;  //  number of balls
float xLocs[] = new float[maxNum];
float yLocs[] = new float[maxNum];
float dxs[] = new float[maxNum];
float dys[] = new float[maxNum];
color colors[] = new color[maxNum];
float radius = 15;

void setup() {
  size(200,400);
  noStroke();
  fill(0); 

  // Initialize the arrays
  for (int i = 0;  i < xLocs.length; i++) {  
    xLocs[i] = random(2*radius, width-2*radius);
    yLocs[i] = random(2*radius, height-2*radius);
    dxs[i] = random(-5,5);
    dys[i] = random(-5,5);
    colors[i] = color(random(255),random(255),random(255));
  }
}

void draw() {
  background(255);

  for (int i = 0;  i< xLocs.length;  i++) {  
    xLocs[i] += dxs[i];
    yLocs[i] += dys[i];
    if (xLocs[i] < radius  || xLocs[i] > width-radius) {
      dxs[i] = -dxs[i];
    }
    if (yLocs[i] < radius  || yLocs[i] > height-radius) dys[i] = -dys[i];
    fill(colors[i]);
    ellipse(xLocs[i],yLocs[i],2*radius,2*radius);
  }
}

An example of an event triggered by the mouse would be having a ball's color change when the user clicks on it. To see how this works, add the following function to the bottom of the above program.

Program 3a: Mouse Event Code for Multiple Ball Bounce
void mousePressed() {
  for (int i=0; i < maxNum; i++) {
    if ( abs(xLocs[i]-mouseX) < radius && abs(yLocs[i]-mouseY) < radius) {
      colors[i] = color(random(255),random(255),random(255));
      println("hit");
    }
  }
}

If you want to save "snapshots" of the program as it runs, you can add a function which responds to key press events. Then, everytime you press a key on the keyboard, an image will be saved which shows the current state of the window.

Program 3b: Key Press Code for Saving Snapshots
int cnt=0;
void keyPressed() {
    save("image"+cnt+".png");
    cnt++;
}

(Optional) A Simple Sound Example

Do this section if you are interested in seeing how sound can be incorporated into your program. Program 4 is a simple program that makes use of sound. Start by creating a blank Processing sketch and copying in the code below. After you save the sketch, you need to go to the sketch folder and create a subfolder called audio. You are to place your sound files into this subfolder. You need to replace the names of the sound files with the names of the sound files you will use. For now, you may use some of the standard files that come with Windows, e.g. ding.wav, WinDing.wav, chimes.wav, tada.wav. Of course, you may use any files you want, however, it is important that the sounds be very short and the format should be WAV, AIFF, or AU. You may or may not have problems with MP3.

Program 4: Simple Sound Example
// Plays a sound and draws a circle when the 
// mouse is clicked in window.

// These are the names of the sound files.  Note,
// the files must be placed in your sketch folder 
// in a subfolder named "audio". If you don't do this,
// you will get a NullPointer error.
String names[] = {
  "ding.wav","WinDing.wav",
  "chimes.wav","tada.wav"
};

void setup() {
  size(200,200);
  soundSetup();   // initialize sound functions
  colorMode(HSB,names.length,100,100);
}

void draw() {
}

void mousePressed() { 
  int n = (int) ( names.length * mouseY/height ) ;
  println("Playing sound " + n);
  mySound[n].play(0);
  fill(n,100,100);
  ellipse(mouseX,mouseY,10,10);
}

Next, you need to add a new tab to your sketch program (e.g. give it the name "Sound") and copy in the code below. To add a new tab, press the small arrow next to the name tag and select "New Tab" :

Next, paste the code below (Program 4a) into this new tab. Note that you need to include this in any program where you use sound. You should not have to make any changes to it. The above program initializes the sound functionality using the function call soundSetup() which needs to be in the setUp function. To play the sound, the uses the command mySound[n].play(0).

Program 4a: Sound Code (add as extra tab)
import ddf.minim.*;
Minim minim;
AudioSnippet mySound[];

void soundSetup()
{
  minim = new Minim(this);
  mySound = new AudioSnippet[names.length];
  for (int i = 0; i < names.length;i++) {
    mySound[i] = minim.loadSnippet("audio/"+names[i]);
  }
}

void stop()
{
  for (int i = 0; i < names.length;i++) {
    mySound[i].close();
  }
  minim.stop();
  super.stop();
}

Run the program. When you click in the window, a different sound should play depending on the y value of the mouse click. An ellipse appears where you click whose color is linked to the choice of sound. We will go over the code in class.

Assignment

In class, you will be shown a simple game with balls moving around where the user must try to click on each of them to change their color. You lose if if you miss hitting a ball a certain number of times. You win if you manage to change all of the ball's colors before reaching the maximum number of misses.

In this lab, you are to become familiar with creating and declaring arrays. To demonstrate that understanding, you are to write a game program involving multiple objects or characteristics (e.g. location of balls) and user interaction (e.g. mouse or key presses) with these objects. Adding sound will be extra credit.

To Be Submitted

At the beginning of class on Wed, March 12: