# Visual Programming for Programming Fundamentals

Wei Jin, Hyesung Park, Xin Xu, Madhushri Banerjee, Yi Ding

## 1. Installing Processing

### 1.1. Learning Outcomes

Students will be able to:

1. Download and install Processing

2. Open a processing project folder

3. Execute a provided Processing project

### 1.2. The Processing Website

- Home page

- Download Page

### 1.3. Tutorial Video for Downloading and Installing Processing

How to download and install Processing on Windows 10 (recorded by a previous GGC student):

Note that sometimes the operating system’s search will not find the Processing app, since Processing’s "installation" does not register the app with the system. You will need to remember where the Processing app is to find and execute the app. Another way to start Processing is to open a Processing code file (see below).

### 1.4. Test Run the Example Project

After you’ve successfully downloaded and installed Processing following the video above, you can test whether the Processing has been installed properly by executing an example project.

Download the Square.zip and extract it into a folder called Square. Go into the folder and double-click on the file Square.pde. If Processing is installed properly, you should be able to open the file in Processing’s IDE (see the image below).

Click on the Run button to see the animation. You should see a green rectangle in the center of the display window, The rectangle will disappear with a mouse click and reappear with a click to any key on keyboard. Study the code and see whether you could understand it.

| For Processing, the file name and the folder name must match. For this example, since the file name is Square.pde, the folder must be named Square.

How to download and install Processing on Windows and create a very simple Processing program (recorded more recently by a professor):

## 2. Basics - Variables, Assignments, Expressions

### 2.1. Learning Outcomes

Students will be able to:

1. Students will be able to explain what variables are, why they are used, and how they are used in programming.

2. Students will be able to declare variables and initialize them with values.

3. Students will learn how to manipulate variables to calculate position and size circles/ellipses in processing.

### 2.2. Definition

A variable is a named storage location in computer memory that holds a value. In programming, it is important to create variable name meaningfully because that help us understand what each variable is used for and we can make our code easier to maintain. For example, if we are storing a person’s age, we might name the variable "personAge."

The folliwng is an example of how we could declare and use a variable.

| A fast way to test the code: Download a blank project Blank.zip and extract it into a folder called Blank. Copy the code in the editor and run the the code.

Variable Declaration and Print Statemnent

    // Declare a variable  named "personAge" for a person's age
    int personAge;

    // Assign a value 25 to the variable
    personAge = 25;

    // Print the value of the variable using "println()" function/method
    println("The person's age is " + personAge);

### 2.3. Tutorial

We will use a fun example to introduce how to use variables in Processing to change the visual effect. It uses the sine math function to scale the size of circles smoothly. Enter the following code block by block into your code editor. Please read the comments embedded in the code, which are intended for teaching the concepts.

The following video will guide you through the tutorial:

ThreeCirclesSine.pde segment 1

    //a comment about this program.

    /**
     * ThreeCirclesSine.
     *
     * Smoothly scaling size with the sin() function for three circles
     */

ThreeCirclesSine.pde segment 2

     //these two lines declare two float variables: "diameter" and "angle"

    float diameter; //diameter will store the size of the circle

    float angle = 0; //angle will control the size of circles.

ThreeCirclesSine.pde segment 3

    //setup() function is called at the beginning of the program

    void setup() {

      size(640, 360); //size() function creates a window of size 640 by 360 pixels.

      //diameter variable is defined to be the height of the window minus 10 pixels. This represents the size of the circle to the drawn.

      diameter = height - 10;

      noStroke(); //noStroke() function does not create the outline of the circle

      fill(255, 204, 0); //the circle sets the color to yellow.

    }

ThreeCirclesSine.pde segment 4

    /**
     * draw() function gets executed called repeatedly to
     * create the animation effect. Each time it get executed
     * is like the Processing "paints a frame in a movie".

     * The follwing draw() function draws three circles and
     * updates their size based on the current value of the
     * "angle" variable.
     */
    void draw() {
      background(0); //paint the black background

      /**
       * d1 is used to store the diameter of the first circle. It is
       * calculated using the "sin()" function and the "angle" variable.
       * The sin() funtion takes angle as a parameter and it returns/generates
       * a value between -1 and 1. Then this value will be scaled by "diameter/2"
       * to generate a value between "- diameter/2" and "diameter/2". Then, add
       * "diameter/2" to generate a value between "0" and "diameter". Last, add
       * "10" to generate a value between 10 and diamter + 10.
       */
      float d1 = 10 + ((sin(angle) * diameter/2) + diameter/2 );

      //d2 is calculated in a similar way to d1 but with a different angle value
      float d2 = 10 + (sin(angle + PI/2) * diameter/2) + diameter/2;

      //d3 is calculated in a similar way to d1 and d2 but with a different angle.
      float d3 = 10 + (sin(angle + PI) * diameter/2) + diameter/2;

      //ellipse() function draws each circle
      ellipse(0, height/2, d1, d1); //circle 1
      ellipse(width/2, height/2, d2, d2); //circle 2
      ellipse(width, height/2, d3, d3); //circle 3

      //angle variable is incremented by 0.02 to create a smooth animation effect.
      angle += 0.02;
    }

When you run the program, you will see three circles, one with center in the middle of the left edge, one with the center in the middle, and one with the center in the middle of the right edge of the window.

#### 2.3.1. A complete program

ThreeCirclesSine.pde complete program

    /**
     * ThreeCirclesSine.
     *
     * Smoothly scaling size with the sin() function for three circles
     */

    float diameter;
    float angle = 0;

    void setup() {
      size(640, 360);
      diameter = height - 10;
      noStroke();
      fill(255, 204, 0);
    }

    void draw() {
      background(0);
      float d1 = 10 + (sin(angle) * diameter/2) + diameter/2;
      float d2 = 10 + (sin(angle + PI/2) * diameter/2) + diameter/2;
      float d3 = 10 + (sin(angle + PI) * diameter/2) + diameter/2;
      ellipse(0, height/2, d1, d1);
      ellipse(width/2, height/2, d2, d2);
      ellipse(width, height/2, d3, d3);
      angle += 0.02;
    }

### 2.4. Exercise 1: Spiral Movement

- Declare variables

  - Declare "diameter" with an initial value of 10 (type: float)

  - Declare "angle" with an initial value of 0 (type: float)

  - Declare "radius" with an initial value of 0 (type: float)

  - Declare "angleStep" with an initial value of 0.1 (type:float)

- Set up the canvas - copy following code

Exercise 1 starter code segment 1

    void setup() {
      size(640, 340);
      diameter = 10;
      noStroke();
      fill(255, 204, 0);
    }

- Draw the circle in a spiral form (Please use the starter code below based on the following description inside of draw() function)

Exercise 1 starter code segment 2 (with instructions)

    void draw() {

      1. call background() function to set the background color to black. background() function takes 0 for black.

      2. compute x and y coordinates of the point on the ellipse/circle using the width, height, radius, and angle variables.
         by using the cos() and sin() functions. Copy two lines.

      float x = width/2 + radius * cos(angle);
      float y = height/2 + radius * sin(angle);

     3. use the ellipse() function to draw a circle on the canvas.
        ellipse() function takes four arguments: the x-coordinate of the center of the ellipse,
        the y-coordinate of the center of the ellipse, the width of the ellipse, and the height of the ellipse.

     4. angle variable is incremented by angleStep.

     5. radius variable is incremented by 0.2. This will create the spiral movement.

    }

### 2.5. Exercise 2: Sprial Movement and Gradual Larger

Building on Exercise 1, declare a new float variable named gradualIncrement and initialize it with a value of 0.1. Inside the draw() function, add the line diameter += gradualIncrement to gradually increase the diameter of the circle by gradualIncrement on each iteration of the loop. Test your program to ensure that the circle grows gradually and moves in a spiral pattern.

Exercise 2 starter code

    float diameter;
    float angle = 0;
    float radius = 0;
    float angleStep = 0.1;

    void setup() {
      size(640, 340);
      diameter = 10;
      noStroke();
      fill(255, 204, 0);
    }

    void draw() {
      background(0);

      float x = width/2 + radius * cos(angle);
      float y = height/2 + radius * sin(angle);

      ellipse(x, y, diameter, diameter);

      angle += angleStep;
      radius += 0.2;
    }

## 3. Conditionals

### 3.1. Learning Outcomes

Students will be able to:

1. Understand basics about boolean expression

2. Apply boolean expression in if statement to make choices and solve simple problems

### 3.2. Basics About Boolean Expression

Boolean expressions use relational operators such as < (less than), < = (less than or equal), > (greater than), >= (greater than or equal), != (not equal) to compare variables against certain values.

For example, for a student to pass a class, the grade must be greater than or equal to 70; that is, we need to compare a student’s grade with 70. The boolean expression that represents this comparison is grade >= 70. A boolean expression will evaluate as either true or false and used in if statement so the code block belongs to that if statement will only be executed when the condition (boolean expression) is true.

For more detailed information about boolean expression and relational operators, please click here.

### 3.3. Tutorial 1

The code below uses an if statment to detect which key has been pressed and change the color of a rectangle accordingly, with R for red, G for green and B for blue. At the start, the rectangle is grey rectangle.

If you need help understand RGB color values, please visit https://processing.org/tutorials/color .

| A fast way to test the code: Download a blank project Blank.zip and extract it into a folder called Blank. Copy the code in the editor and run the the code. Please read the comments embedded in the code, which are intended for teaching the concepts.

Tutorial 1 code

    //Use variables to store color code.
    color defaultColor = color(125,125,125); // default color: grey
    color RED = color(255, 0, 0);
    color GREEN = color(0, 255, 0);
    color YELLOW = color(255, 255, 0);
    color BLUE = color(0, 0, 255);
    color myColor;

    void setup() {
        // Initilize the window size.
        size(900, 900);

    }

    void draw() {
      //Use an if statement to determine the fill color
      if (keyPressed) {
        if (key == 'r' || key == 'R') {
          myColor=RED;
        }
        else if(key == 'g' || key == 'G') {
          myColor=GREEN;
        }
        else if(key == 'b' || key == 'B') {
          myColor=BLUE;
        }
        else
          myColor=defaultColor;
      }

      fill(myColor);

      // draw a rectangle with size 200 by 200.
      rect(350, 250, 200, 200); //rect(xLocation, yLocation, length, width)
    }

### 3.4. Tutorial 2

In this tutorial, you will learn how to use an if statement to change the moving direction of an object with left and rigth arrow keys.

Tutorial 2 code

    int recWidth = 50, recHeight=50; //rectangle size
    int directionX = -1, directionY = 0; //moving direction: 0 - not moving, 1 - coordinate increases, -1 - corredinate decreases
    float x=400, y=400;  //position of upper left corner of rectangle
    float speed=0.5;     //change value each iteration for location
    color myColor=color(255,0,0);

    // ==============================================
    void setup()
    {
      size(900, 900);
    }

    void draw()
    {
      background(0);  //0 represent the black color

      // Update position variables
      x = x + speed*directionX;
      y = y + speed*directionY;

      fill(myColor);
      rect(x, y, recWidth, recHeight);

    }

    // ==============================================
    void keyPressed()
    {
      //Currently the rectangle can only move left or right
      if (key == CODED)
      {
        if (keyCode == LEFT)
        {
          directionX=-1;
          directionY=0;

        }
        else if (keyCode == RIGHT)
        {
          directionX=1;
          directionY=0;
        }
      }
    }

### 3.5. Tutorial 3

Now, run Tutorial 2 code again and do not change the moving direction of the square and observer what will happen when the rectange approaches the border. You will notice that the square will move outside of the window. Let’s add an if statment so it moves to the opposite direction when hitting the left or right border.

Since the size of the window is 900 by 900, the square will touch the right border when its x coordinate is 900 - recWidth. It will touch the left border when its x coordinate is 0. Let’s check the location using the following if statement. If the boolean expression is true, indicating the square is hitting the border, change the moving direction to the opposite.

Code for detecting whether the rectangle touches either the right or the left border.

      if ( x >= 900-recWidth || x <= 0)
      {
        // code to change moving direction
      }

Here’s the complete code for Tutorial 3.

Tutorial 3 code

    int recWidth = 50, recHeight=50; //rectangle size
    int directionX = -1, directionY = 0; //moving direction: 0 - not moving, 1 - coordinate increases, -1 - corredinate decreases
    float x=400, y=400;  //position of upper left corner of rectangle
    float speed=0.5;     //change value each iteration for location
    color myColor=color(255,0,0);

    // ==============================================
    void setup()
    {
      size(900, 900);
    }

    void draw()
    {
      background(0);  //0 represent the black color

      // Update position variables
      x = x + speed*directionX;
      y = y + speed*directionY;

      // check if square reaches left or right border
      if ( x >= 900 - recWidth || x <= 0)
      {
        directionX = -directionX; // change direction
      }

      fill(myColor);
      rect(x, y, recWidth, recHeight);

    }

    // ==============================================
    void keyPressed()
    {
      //Currently the rectangle can only move left or right
      if (key == CODED)
      {
        if (keyCode == LEFT)
        {
          directionX=-1;
          directionY=0;

        }
        else if (keyCode == RIGHT)
        {
          directionX=1;
          directionY=0;
        }
      }
    }

### 3.6. Exercise 1

Add additional if statements so the square also moves up and down with border control.

#### 3.6.1. Starter code

Note: The starter code of Exercise 1 is also the finishing code of Tutorial 3.

### 3.7. Exercise 2

Allow a user to choose the shape they want by using the keyboard: 1 for circle, 2 for triangle and 3 for rectangle. Here’s the code to draw the three shapes. You can use them directly in the if statement. Feel free to change the numbers to understand how the shapes were created in Processing.

Code for drawing three different shapes

    circle(400, 400, 200); // (centerX, centerY, radius)
    triangle(300, 300, 600, 300, 450, 500);//(x1, y1, x2, y2, x3, y3)
    rect(350, 350, 200, 300); // (x1, y1, width, height)

#### 3.7.1. Starter code

Exercise 2 starter code

    color myColor=color(0, 0, 255);

    void setup() {
      // Initilize the window size.
      size(900, 900);

      //display text instructions
      textSize(24); // set text size
      fill(myColor); //set text color
      text("Choose your shape using1, 2, or 3.", 40, 100);
      text("1: Circle", 40, 130);
      text("2: Triangle", 40, 160);
      text("3: Rectangle", 40, 190);
    }

    void draw() {
      fill(myColor);
      //Use if statement to determine the shape (hint: check Tutorial 1)

    }

## 4. Loops

### 4.1. Learning Outcomes

Students will be able to:

1. predict the outcome of a loop

2. write a loop to solve a similar problem as shown in the tutorial

### 4.2. Tutorial 1

We are going to use the following example to understand what a loop is and how it works. The starter code can also be downloaded from Squares.zip. Open Squares.pde and you will see a code as follows:

Loop Tutorial 1 - Starter Code

    public void setup() {
      size(500, 500);      //window size 500 x 500
      background(100);     //a gray color
      fill(100, 130, 200); //a blue color

      rect(0, 0, 100, 100);
      rect(100, 0, 100, 100);
      rect(200, 0, 100, 100);
      rect(300, 0, 100, 100);
      rect(400, 0, 100, 100);
    }

If you run the code, you will see a window as follows.

The code draws five squares using five lines of code. If we need to fill up the window with the same-sized squares, we will need five total rows. That is, we will need to draw 5 squares per row for five rows, that is, a total of 25 squares, which will require 25 lines of code.

If we change the square size from 100 x 100 to 10 x 10, to fill up a row, we will need to draw 500 / 10 = 50 squares. We will need to draw 50 rows to fill up the window. That is, we need to draw a total of 50 x 50 = 2500 squares. Using the same approach as in the starter code, we would need 2500 lines of code.

If the window size becomes 2000 x 2000 and the square size is 10 x 10, we will need to draw 40,000 squares. Using the same approach as in the starter code, we will need to use 40,000 lines of code. We can see that it would be a very tedious, boring and error-prone task.

The good news is that we have a new tool - loop - that will allow us to do things repetatively. Let’s get started. Let’s transform the starter code to one as shown below:

Loop Tutorial 1 - Step-1 Transformation

    public void setup() {
      size(500, 500);      //window size 500 x 500
      background(100);     //a gray color
      fill(100, 130, 200); //a blue color

      int x = 0;
      rect(x, 0, 100, 100);     //x is 0 here
      x += 100;
      rect(x, 0, 100, 100);     //x is 100 here
      x += 100;
      rect(x, 0, 100, 100);     //x is 200 here
      x += 100;
      rect(x, 0, 100, 100);     //x is 300 here
      x += 100;
      rect(x, 0, 100, 100);     //x is 400 here
      x += 100;
     }

If you run the code, you will see that it draws the same five squares. Let’s examine the above code. We introduced a variable x. It starts with 0. After the each square is drawn, its value is increased by 100. We can see x takes on the values from 0, 100, 200, 300, to 400, the same as the x-coornates of the squares in the starter code, thus drawing the same squares.

You might ask why we bother to use a variable. That’s a good question! With a variable introduced, we can see that something interesting has happened. We can see that the following code is repeated five times in the program.

Code Segment that Repeats in the Step-1 Code

      rect(x, 0, 100, 100);
      x += 100;

Now it is a good time to introduce loop. We will introduce a while loop (also called a while statement) as shown below. A while loop is very similar to an if statement. Just like an if statement, the boolean expression is first evaluated, if it is true, the statements below will be executed. In the example code below, a 100 x 100 square is draw and x is incremented by 100. An if statement will be done, but a while statement will go back to check the boolean expression again. If it is still true, it will execute the statements below again. This process will repeat until the boolean expression becomes false.

A While Loop to Replace the Repetitive Code in the Step-1 Code

      while (__a boolean expression___) {
        rect(x, 0, 100, 100);
        x += 100;
      }

Now what the boolean expression should be in order to draw the five squares?

Let’s first go to Java Visualizer and copy the following following code into the main method and visualize the execution and observe how x's value changes.

      int x = 0;
      while (x < 1000) {
        System.out.println(x);
        x += 100;
      }

Ok. I think by now you have figured out that the boolean expression for drawing five squares should be x ⇐ 400 or x < 500. They will have the same effect for this program, since x is incremented by 100 each iteration of the loop.

Loop Tutorial 1 - Step-2 Transformation

    public void setup() {
      size(500, 500);      //window size 500 x 500
      background(100);     //a gray color
      fill(100, 130, 200); //a blue color

      int x = 0;
      while (x < 500) {
        rect(x, 0, 100, 100);
        x += 100;
      }
    }

Java and most programming languages offer another type of loop, called for loop. It does the same thing as a while loop but has a different format. The following is an equivalent for loop as the while loop in step 2. Pay attention to where x is intialized to 0 and where x is incremented by 100 are in the for loop.

Loop Tutorial 1 - Step-3 Transformation

    public void setup() {
      size(500, 500);      //window size 500 x 500
      background(100);     //a gray color
      fill(100, 130, 200); //a blue color

      for (int x = 0; x < 500; x += 100) {
        rect(x, 0, 100, 100);
      }
    }

We can see the for loop is more compact.

You can stop here, but if you are curious about how to fill out the whole window using the squares, you can read on.

For the remainder of Tutorial 1, we will use for loop. Let’s add another variable y and initialize y to 0. After drawing a row of squares, we will increase y by 100.

Loop Tutorial 1 - Step-4 Transformation - Fill the window with squares

    public void setup() {
      size(500, 500);      //window size 500 x 500
      background(100);     //a gray color
      fill(100, 130, 200); //a blue color

      int y = 0;
      for (int x = 0; x < 500; x += 100) {
        rect(x, y, 100, 100);   // y is 0 here
      }
      y += 100;

      for (int x = 0; x < 500; x += 100) {
        rect(x, y, 100, 100);   // y is 100 here
      }
      y += 100;

      for (int x = 0; x < 500; x += 100) {
        rect(x, y, 100, 100);   // y is 200 here
      }
      y += 100;

      for (int x = 0; x < 500; x += 100) {
        rect(x, y, 100, 100);   // y is 300 here
      }
      y += 100;

      for (int x = 0; x < 500; x += 100) {
        rect(x, y, 100, 100);   // y is 400 here
      }
      y += 100;
    }

If you run the code above, you will see that the window is covered with square as follows:

Again we can see that the following code is executed repetatively:

Code Segment that Repeats in the Step-4 Code

      for (int x = 0; x < 500; x += 100) {
        rect(x, y, 100, 100);
      }
      y += 100;

Treating the above block code as a unit and using the same approach as how we have converted the step-1 code to the step-2 code, we can use another loop to make this code execute five times and draw the five rows:

Loop Tutorial 1 - Step-5 Transformation

    public void setup() {
      size(500, 500);      //window size 500 x 500
      background(100);     //a gray color
      fill(100, 130, 200); //a blue color

      int y = 0;

      while (y < 500) {

        for (int x = 0; x < 500; x += 100) {
          rect(x, y, 100, 100);
        }
        y += 100;

      }
    }

Converting the while loop in step-5 code to a for loop, we have the following code that is more compact:

Loop Tutorial 1, Step 6

    public void setup() {
      size(500, 500);      //window size 500 x 500
      background(100);     //a gray color
      fill(100, 130, 200); //a blue color

      for (int y = 0; y < 500; y += 100) {
        for (int x = 0; x < 500; x += 100) {
          rect(x, y, 100, 100);
        }
      }
    }

### 4.3. Exercise 1

Change the code further so that it uses 10x10 squares to cover the first row or the whole window.

### 4.4. Tutorial 2

The following code plots two sine waves.

You may notice a similar phenomenon inside the drawOneWave method to that in Tutorial 1 - Step 1, where a segment of code is repeated over and over again, in this case, 20 times. This indicates that you can use a loop to remove the duplicated code.

#### 4.4.1. Starter Code

Loop Tutorial 2 - Starter Code

    /*Initialize variables that will be used later*/
    int xspacing = 32;   // How far apart should each horizontal location be spaced
    float amplitude = 75.0;  // Height of wave
    float period = 500.0;    // How many pixels before the wave repeats
    int w;                   // Width of entire wave
    float dx;                // Value for incrementing X, a function of period and xspacing
    int numPoints;           // # of points to draw for a wave

    void setup() {
      size(640, 360);
      w = width+16;
      dx = (TWO_PI / period) * xspacing;  // TWO_PI is 2 * PI
      numPoints = w/xspacing;
    }

    void draw() {
      background(0);
      noStroke();
      fill(255);

      drawOneWave(0);  // draw one sine wave
      drawOneWave(2);  // draw another sine wave
    }

    /*
     * This method draws a sine wave.
     */
    void drawOneWave(float angle) {
      float x, y;
      float plot_x, plot_y;

      int i = 0;

      x = angle + i * dx; //repeat 20 times
      y = sin(x)*amplitude;
      plot_x = i * xspacing;
      plot_y = height/2+y;
      ellipse(plot_x, plot_y, 16, 16);

      i++;

      x = angle + i * dx;
      y = sin(x)*amplitude;
      plot_x = i * xspacing;
      plot_y = height/2+y;
      ellipse(plot_x, plot_y, 16, 16);

      i++;

      ...

    }

The code that repeats in the code above is the following:

Code Segment that Repeats in the Starter Code

        x = angle + i * dx;
        y = sin(x)*amplitude;
        plot_x = i * xspacing;
        plot_y = height/2+y;
        ellipse(plot_x, plot_y, 16, 16);

        i++;

Using the same approach as in the tutorial one, the drawOneWave method can be transformed to a compact while loop.

Using While Loop to Shorten the drawOneWave Method

    void drawOneWave(float angle) {
      float x, y;
      float plot_x, plot_y;

      int i = 0;

      while (__boolean expression__) { //What the expression should it be for numPoints iterations?
        x = angle + i * dx;
        y = sin(x)*amplitude;
        plot_x = i * xspacing;
        plot_y = height/2+y;
        ellipse(plot_x, plot_y, 16, 16);

        i++;
      }
    }

The boolean expression should be: i < numPoints.

We can convert the whole loop to a more compact for loop: .An Equivalent For Loop

      for (int i = 0; i < numPoints; i++) {
        x = angle + i * dx;
        y = sin(x)*amplitude;
        plot_x = i * xspacing;
        plot_y = height/2+y;
        ellipse(plot_x, plot_y, 16, 16);
      }

#### 4.4.2. Solution Code

You can see that in the solution below, an eight-line for loop is used to replace the 20 repetitions of a code segment.

Loop Tutorial 2 - Solution Code

    /*Initialize variables that will be used later*/
    int xspacing = 32;   // How far apart should each horizontal location be spaced
    float amplitude = 75.0;  // Height of wave
    float period = 500.0;    // How many pixels before the wave repeats
    int w;                   // Width of entire wave
    float dx;                // Value for incrementing X, a function of period and xspacing
    int numPoints;           // # of points to draw for a wave

    void setup() {
      size(640, 360);
      w = width+16;
      dx = (TWO_PI / period) * xspacing;  // TWO_PI is 2 * PI
      numPoints = w/xspacing;
    }

    void draw() {
      background(0);
      noStroke();
      fill(255);

      drawOneWave(0);  // draw one sine wave
      drawOneWave(2);  // draw another sine wave
    }

    /*
     * This method draws a sine wave.
     */
    void drawOneWave(float angle) {
      float x, y;
      float plot_x, plot_y;

      for (int i = 0; i < numPoints; i++) {
        // For every x value, calculate a y value with sine function
        x = angle + i * dx;
        y = sin(x) * amplitude;
        plot_x = i * xspacing;
        plot_y = height/2 + y;
        ellipse(plot_x, plot_y, 16, 16);
      }
    }

#### 4.4.3. Animate the Wave

In an further update to the solution code, we will draw one wave but it is animated.

Add a variable angle at the top of the program:

An addtional variable

    float angle = 0;         // Angle of the first point of a wave

Loop Tutorial 2 - A Slight Update in the draw Method to Animate the Wave

    void draw() {
      background(0);
      noStroke();
      fill(255);

      angle += 0.02;
      drawOneWave(angle);  // draw one sine wave
    }

The following shows how the animation should look like:

### 4.5. Exercise 2: Draw Lots of Rectangles

In this exercise, you will first study the starter code that draws the rectangles as follows.

You will figure out the pattern of the locations of the rectangles and convert it into a loop based solution.

#### 4.5.1. Starter code

Loop Exercise 1 Starter Code

    //starter

    // Runs when the program is first launched
    public void setup() {
      // Initilize the window size in setup().
      size(1000, 1000);

      // Disable the layer.
      noStroke();

      // Set background color
      background(118, 128, 228);

      // Draw pipes at the upper left corner
      fill(58, 58, 58);
      rect(150, 150, 25, 200);  //x, y, width, height
      rect(200, 150, 25, 200);  //x, y, width, height
      rect(250, 150, 25, 200);  //x, y, width, height
      rect(300, 150, 25, 200);  //x, y, width, height
      rect(350, 150, 25, 200);  //x, y, width, height

      // Draw pipes at the upper right corner
      rect(1000-150-25, 150, 25, 200);  //x, y, width, height
      rect(1000-200-25, 150, 25, 200);  //x, y, width, height
      rect(1000-250-25, 150, 25, 200);  //x, y, width, height
      rect(1000-300-25, 150, 25, 200);  //x, y, width, height
      rect(1000-350-25, 150, 25, 200);  //x, y, width, height

      // Draw pipes at the lower left corner
      rect(150, 1000-150-200, 25, 200);  //x, y, width, height
      rect(200, 1000-150-200, 25, 200);  //x, y, width, height
      rect(250, 1000-150-200, 25, 200);  //x, y, width, height
      rect(300, 1000-150-200, 25, 200);  //x, y, width, height
      rect(350, 1000-150-200, 25, 200);  //x, y, width, height

      // Draw pipes at the lower right corner
      rect(1000-150-25, 1000-150-200, 25, 200);  //x, y, width, height
      rect(1000-200-25, 1000-150-200, 25, 200);  //x, y, width, height
      rect(1000-250-25, 1000-150-200, 25, 200);  //x, y, width, height
      rect(1000-300-25, 1000-150-200, 25, 200);  //x, y, width, height
      rect(1000-350-25, 1000-150-200, 25, 200);  //x, y, width, height
    }

### 4.6. Exercise 3: Show Gray Scale Value

In this exercise, you will write a program that draws a gradual change of color from black to white and shows the gray scale value of the color where the mouse points to. See the following image for a reference. Note that the text color should be white when the mouse points to anywhere on the left half of the window and black when the mouse points to anywhere on the right half of the window.

## 5. Methods

### 5.1. Learning Outcomes

Students will be able to:

1. Understand the basics of Method

2. Apply method defined by others

3. Create a method

### 5.2. Basic Concept

Simply speaking, we create a method by putting codes that focus on acehieving one specific task into one block and give this block a name, referred to as method name. Later on, the same code in places we need it without having to re-write it. (Over-simplified)

A method always has a method header and a method body. Once a method has been created, it needs to be invoked when you need to use it. Tutorial 1 will show you examples of defining a method and invoking methods.

### 5.3. Tutorial 1

Run Tutorial 1 code below in Processing, and draw an image by moving your mouse. The size of the circle is determined by the speed of your mouse movements.

In this program, a method variableEllipse() was created. The method header is:

Method header

    void variableEllipse(int x, int y, int px, int py)

void means this method will not return any data. variableEllipse is the method name. x, y, px, py are the parameters with integer data type.

This method is invoked in draw() method.

Take a look at the method body of variableEllipse: It invokes abs() method, stroke() method and ellipse() method. All these three methods are already defined in the Processing library and we just need to invoke them when needed.

| A fast way to test the code: Download a blank project Blank.zip and extract it into a folder called Blank. Copy the code in the editor and run the the code.

Tutorial 1 code

    /**
     * Move the cursor to create image
     *that responds to the speed of the mouse.
     */

    void setup() {
      size(880, 600);
      background(102);
    }

    void draw() {
      // Call the variableEllipse() method and send the
      // parameters for the current mouse position mouseX and mouseY
      // and the previous mouse position pmouseX and pmouseY
      variableEllipse(mouseX, mouseY, pmouseX, pmouseY);
    }

    // The  method variableEllipse() calculates the speed of the mouse
    // and draws a small ellipse if the mouse is moving slowly
    // and draws a large ellipse if the mouse is moving quickly

    void variableEllipse(int x, int y, int px, int py) {
      // calculate the speed based on current mousePosition and previous mouse position
      float speed = abs(x-px) + abs(y-py);
      stroke(speed);
      ellipse(x, y, speed, speed);
    }

The code was provided by Processing

### 5.4. Exercise 1

Look at the starter code provide below. Pay attention to the parameters of polygon() method. Invoke the method three times to create the three shapes similar to the ones shown in the picture.

#### 5.4.1. Starter code

Exercise 1 starter code

    color myColor=color(255, 255,0);
    void setup() {
      size(800, 600);
    }

    void draw() {
      background(200, 200, 200);
      fill(myColor);
     // invoke polygon() three times to create three shapes in a row, the y location is 150, the x location is up to you but please spread out the three shapes evenly.

    }

    void polygon(float x, float y, float radius, int npoints) {
      float angle = TWO_PI / npoints;
      beginShape();
      for (float a = 0; a < TWO_PI; a += angle) {
        float sx = x + cos(a) * radius;
        float sy = y + sin(a) * radius;
        vertex(sx, sy);
      }
      endShape(CLOSE);
    }

## 6. Arrays

### 6.1. Learning Outcomes

Students will be able to:

1. declare and initialize arrays

2. manipulate array elements using Processing in Java.

### 6.2. What is Arrays in Java?

An array in Java is a way to store a collection of elements of the same type. It is like a container that can hold multiple items of the same kind, such as a collection of numbers, letters, or even objects.

For example, imaging you are collecting the scores of games. Instead of creating separate variables for each score, you can use an array to store all the scores in one place. Then, you can access and manipulate the scores as needed.

Here’s a example of how to declare an array of integers in Java:

Declare an array in Java and intialize it with all zeros.

    //this creates an array called scores that can hold 5 integers.
    int[] scores = new int[5];

Declare an array in Java and intialize it with a set of specific values.

    //Initialize the array with specific values
    int[] scores = {10,9,8,7,6,5,4,3,2,1,0};

To access an element in the array, you use the index of the element, which starts from 0. The following code access the first element in the array and then assign it to a new value.

Access the first element of the array.

    int firstScore = scores[0];
    scores[0] = 100; //to change an element in the array.

### 6.3. Tutorial 1

#### 6.3.1. Starter Code - step 1

This program creates an array of circles and randomly sets their colors using an array of colors.

Starter code, segment 1

    int numCircles = 10; //variable determins the number of circles in the array

    //circleX, circleY, circleSize, and circleColor arrays store the x-position, y-position, size, and color of each circle.

    int[] circleX = new int[numCircles];
    int[] circleY = new int[numCircles];
    int[] circleSize = new int[numCircles];
    color[] circleColor = new color[numCircles];

    //colors array stores three different colors that will be randomly assigned to each circle.
    color[] colors = {color(255, 0, 0), color(0, 255, 0), color(0, 0, 255)};

#### 6.3.2. Starter Code - step 2

Starter code, segment 2

    // setup() function has a for loop iterates through each circle and sets its x-position, y-position, size and color using random values from the arrays
    void setup() {
      size(400, 400);
      for (int i = 0; i < numCircles; i++) {
        circleX[i] = int(random(width));
        circleY[i] = int(random(height));
        circleSize[i] = int(random(20, 50));
        circleColor[i] = colors[int(random(3))];
      }
    }

#### 6.3.3. Starter Code - step 3

Starter code, segment 3

    //draw() function has a for loop iterates through each circle and draws it with the assigned color and size.
    void draw() {
      background(255);
      for (int i = 0; i < numCircles; i++) {
        fill(circleColor[i]);
        ellipse(circleX[i], circleY[i], circleSize[i], circleSize[i]);
      }
    }

### 6.4. Tutorial 2 Preparation

We will visualize a set of data values over a map using the following code in Tutorial 2. To prepare for that, we first need to display the map. The following code display the map image. You can also download the code MapRender.zip, which contains map.png.

Code for displaying a map image

    PImage mapImage;

    /*
     * The setup() method executes once after click Run button
     */
    void setup(  ) {
      size(640, 400);
      mapImage = loadImage("map.png"); //load an image from the data folder
    }

    void draw(  ) {
      background(255);
      image(mapImage, 0, 0);
    }

The program should display the following:

### 6.5. Tutorial 2

We will visualize a set of data values over a map using the following code. We will load in the position data of the map so that we can use them to determine where to render our visualizeion against the map.

You can also download the code MapVisualization.zip, which contains the image and data files map.png, locations.tsv, and random.tsv.

Code for rendering a map

    PImage mapImage;Table locationTable;
    Table locationTable;
    int rowCount;

    void setup(  ) {
      size(640, 400);
      mapImage = loadImage("map.png");

      // Create a Table object with the provided coordinates data file.
      locationTable = loadTable("locations.tsv");

      // The row count will be used a lot, so store it globally.
      rowCount = locationTable.getRowCount();
    }

    void draw(  ) {
      background(255);
      image(mapImage, 0, 0);

      // Drawing attributes for the ellipses.
      smooth(  );
      fill(192, 0, 0);
      noStroke(  );

      // Loop through the rows of the locations file and draw the points.
      for (int row = 0; row < rowCount; row++) {
        float x = locationTable.getFloat(row, 1);  // column 1
        float y = locationTable.getFloat(row, 2);  // column 2
        ellipse(x, y, 9, 9);
      }
    }

The program should display the following:

### 6.6. Exercise 1

How can we use arrays in Processing to create a Dippin' Dots style rainbow ice cream that fills a cup?

1. Open the Processing software and create a new sketch by selecting "File" > "New" from the menu bar.

2. In the new sketch window, copy and paste the following code to create a program that generates a Dippin' Dots style rainbow ice cream:

#### 6.6.1. Starter code

Exercise 1 starter code

    int numCircles = 50;
    int[] circleX = new int[numCircles];
    int[] circleY = new int[numCircles];
    int[] circleSize = new int[numCircles];
    color[] circleColor = new color[numCircles];

    void setup() {
      size(400, 400);
      smooth();
      noStroke();
      for (int i = 0; i < numCircles; i++) {
        float t = random(0, TWO_PI);
        float r = random(0, 100);
        float x = r * cos(t) + width / 2;
        float y = r * sin(t) + height / 2 + 50;
        circleX[i] = int(x);
        circleY[i] = int(y);
        circleSize[i] = int(random(5, 15));
        circleColor[i] = color(random(255), random(255), random(255), 200);
      }
    }

    void draw() {
      background(255);
      for (int i = 0; i < numCircles; i++) {
        fill(circleColor[i]);
        ellipse(circleX[i], circleY[i], circleSize[i], circleSize[i]);
      }
      noLoop();
    }

1. Save the sketch by selecting "File" > "Save" from the menu bar, and give it a name such as "DippinDotsIceCream".

2. Run the program by clicking on the "Play" button in the upper-left corner of the Processing window. You should see a window with circles of different colors arranged in a circular pattern (see the image below).

3. To modify the program to create a Dippin' Dots style rainbow ice cream that fills a cup, do the following:

   - First increase the numCircles variable to 200 to create more circles and make the ice cream more dense.
   - Modify the circleSize array to create smaller circles with sizes between 3 and 7.

   - Modify the r variable to create a smaller radius, making the circles more tightly packed together. For example, you can change 100 to 50. When you run the code, you should see an image as follows:

   - Add vertex commands to create a cup shape using the beginShape() and endShape() functions. Add the following vertex commands to create a simple cup shape in the draw function right after the for loop:

         beginShape();
         vertex(80, height - 20);
         vertex(320, height - 20);
         vertex(310, height - 10);
         vertex(90, height - 10);
         endShape(CLOSE);

     When you play the program, you may not see anything. It is due to no stroke color for the shape. Add the following before the proceeding code for drawing the shape (but after the for loop):

         fill(255, 170, 0);
         stroke(255, 170, 0);
         strokeWeight(2);

     When you run the code, you should see the following:

4. Modify the draw() function as follows:

   1. Animate the ice cream by moving each circle down by a random amount int(random(1, 3)) each frame until they reach the bottom of the cup.
   2. Add an if statement to check if each circle has reached the bottom of the cup, and if so, reset its position to a random y-coordinate at the top of the cup.

   Your for loop should look like the following:

       for (int i = 0; i < numCircles; i++) {
         //add a small random number to y (i.e. going down a little)
         circleY[i] += int(random(1, 3));
         //if reach bottom, reset the y to a negative value (i.e. above the top of the window)
         if (circleY[i] > height - 20) {
           circleY[i] = int(random(-50, -10));
         }
         fill(circleColor[i]);
         ellipse(circleX[i], circleY[i], circleSize[i], circleSize[i]);
       }

5. Finally, remove the noLoop() function from the draw() function to allow the animation to run indefinitely. However, when you run the code, you will see that small circles of different colors falling down like raindrops. However, all the small circles will have a orange border. Add noStroke(); right above the for loop that draws the circles to remove the orange stroke.

6. Save and run the program to see a colorful icecream ball falling into the cup. After it is almost gone, another one will appear.

### 6.7. Exercise 2

Create an array called xPositions that stores 10 integer values between 0 and the width of the screen. Use a for loop to draw 10 circles with random y positions and a fixed size at each x position in the array.

### 6.8. Exercise 3

Create an array called colors that stores 5 color values of your choice. Use a for loop to draw 5 rectangles of equal size 40 x 40 on the diagonal of a window 200 x 200 with each being filled with a different color from the colors array.

### 6.9. Exercise 4

Create an array called yPositions that stores 50 integer values between 0 and the height of the screen, evenly distributed. Use a for loop to draw 50 lines of varying lengths with a fixed x position (the middle of the window) and a y position determined by each value in the yPositions array. The length of the line should be a random value between 10 and 50.

### 6.10. Exercise 5

Create an array called textStrings that stores 4 string values of your choice. Use a for loop to draw 4 text strings, each string being centered horizontally and spaced vertically with the height of the screen divided by the number of elements in the textStrings array.

### 6.11. Exercise 6

Create an array called circleSizes that stores 6 increasing integer values of your choice between 10 and 100. Use a for loop to draw 6 circles of equal spacing and varying sizes, each size being determined by an element in the circleSizes array.

## 7. Class and Object

### 7.1. Learning Outcomes

Students will be able to:

1. Understand the class definition structure

2. Understand how to creaete objects

### 7.2. Tutorial

We are going to use the following example to understand what class is, how to create objects from a class, and the advantages of using object-oriented programming. Download Balls.zip and extract it into a folder called Balls. Read and understand this starter code.

#### 7.2.1. Starter Code

Object-Oriented Programming Tutorial 1 - Starter Code (Balls.pde)

    // Arrays to store attributes of multiple balls
    int num = 5;  //# of balls
    float[] x = new float[num];   //x coordinates
    float[] y = new float[num];   //y coordinates
    float[] speedX = new float[num]; //speeds along x axis
    float[] speedY = new float[num]; //speeds along y axis
    float[] diameter = new float[num]; //diameters

    /**
     * setup method -  called once at the start of the program
     *
     * Initialize the attributes of balls
     */
    void setup() {
      size(800, 600);  //window size
      for (int i = 0; i < num; i++) {
        x[i] = random(width);         //set to a random value in [0, width)
        y[i] = random(height);        //set to a random value in [0, height)
        diameter[i] = random(20, 50); //set to a random value in [20, 50)
        speedX[i] = random(1, 3);     //set to a random value in [1, 3)
        speedY[i] = random(1, 3);     //set to a random value in [1, 3)
      }
    }

    /**
     * draw method - by default, called 60 times per second.
     *
     * Move and display each ball
     */
    void draw() {
      background(255);
      for (int i = 0; i < num; i++) {
        move(i);
        display(i);
      }
    }

    /**
     * Move the ball with index i
     */
    void move(int i) {
      x[i] += speedX[i];  //x coordinated modified by speed along x axis
      y[i] += speedY[i];  //y coordinated modified by speed along y axis

      // Check for collision with the screen boundaries
      if (x[i] <= 0 || x[i] >= width) {  //if goes to out of the window along x axis
        speedX[i] *= -1;  //reverse speed direction along x axis
      }
      if (y[i] <= 0 || y[i] >= height) { //if goes to out of the window along y axis
        speedY[i] *= -1;  //reverse speed direction along y axis
      }
    }

    /**
     * Display the ball with index i
     */
    void display(int i) {
      ellipse(x[i], y[i], diameter[i], diameter[i]); //draw a circle
    }

If you run the code, you will see a window with five balls moving around. When each ball hits a boundary, it reverses course.

You should be able to see that each ball has five attributes, x coordinate, y coordinate, diameter, speed along the x axis, and speed along the y axis. The starter code uses five arrays to store the five attributes for all the balls. If you need to extend the program so that each ball has more attributes, such as color, texture, weight, acceleration, etc., you will need to create more arranges to store these attributes and it could become cumbersome.

#### 7.2.2. Transformation to Object-Oriented Programming

We will learn a new program structure that allows a program to store all the attributes for a ball in "one place" or an object. A Java class is the definition of what attributes will be stored in the object and what "actions" the object can take.

Create another folder called Balls2 and create the following two files: Ball.pde and Balls2.pde.

Ball.pde is the class definition, a template for Ball objects. It contains the specification of the five attributes, a constructor method (the same name as the class name), two instance methods, move and display, that a Ball object can call.

Object-Oriented Programming Tutorial - Class Ball (Ball.pde)

    // Ball class to represent a moving ball
    class Ball {
      float x, y;           // Position of the ball
      float speedX, speedY; // Speed of the ball
      float diameter;       // Diameter of the ball

      //Constructor method that create a ball with the
      //specified position and diameter
      Ball(float x, float y, float diameter) {
        this.x = x;
        this.y = y;
        this.diameter = diameter;
        this.speedX = random(1, 3); // initial X speed set to a random value in [1, 3)
        this.speedY = random(1, 3); // initial Y speed set to a random value in [1, 3)
      }

      // Move the ball
      void move() {
        x += speedX;
        y += speedY;

        // Check for collision with the screen boundaries
        if (x <= 0 || x >= width) {
          speedX *= -1;
        }
        if (y <= 0 || y >= height) {
          speedY *= -1;
        }
      }

      // Display the ball
      void display() {
        ellipse(x, y, diameter, diameter);
      }
    }

You can see that the logic for moving a ball and display a ball is the same as the starter code. How the attributes are initialized are also similarly done as the starter code. However, with a class definition, the main program Balls.pde becomes very streamlined. We only need one array to store the information for all the Ball objects, instead one array for each attribute.

Object-Oriented Programming Tutorial - new main file Balls2.pde

    // Array to store multiple balls
    int num = 5;
    Ball[] balls = new Ball[num];

    void setup() {
      size(800, 600);
      for (int i = 0; i < balls.length; i++) {
        float x = random(width);
        float y = random(height);
        float diameter = random(20, 50);
        balls[i] = new Ball(x, y, diameter); //Create a Ball object and save it in the array
      }
    }

    void draw() {
      background(255);
      for (int i = 0; i < balls.length; i++) {
        balls[i].move();
        balls[i].display();
      }
    }

### 7.3. Exercise 1

Starter code is given below. It can also be downloaded Birds.zip.

Convert the starter code into an object-oriented solution. Define a class for Bird that has six attributes, a constructor method, update method, and display method. Update the main program Birds.pde so that it uses one array to store all the bird information.

Object-Oriented Programming Exercise 1 - Starter Code (Birds.pde)

    int num = 10;  //# of birds
    float[] x = new float[num];   //x coordinates
    float[] y = new float[num];   //y coordinates
    float[] speedX = new float[num]; //speeds along x axis
    float[] speedY = new float[num]; //speeds along y axis
    float[] wingSpan = new float[num]; //Widths of the bird's wings
    float[] wingPosition = new float[num]; //Position of the wings (to simulate flapping)

    void setup() {
      size(800, 600);
      for (int i = 0; i < num; i++) {
        x[i] = random(width/2);
        y[i] = random(height);
        wingSpan[i] = 30; // Initial wing position
        speedX[i] = 2; // Constant horizontal speed
        speedY[i] = 0; // No vertical speed
        wingPosition[i] = 0; // Initial wing position
      }
    }

    void draw() {
      background(135, 206, 250); // Sky blue background
      for (int i=0; i < num; i++) {
        update(i);
        display(i);
      }
    }

    void update(int i) {
      x[i] += speedX[i];
      y[i] += speedY[i];

      // Check for collision with the screen boundaries
      if (x[i] <= 0 || x[i] >= width) {
        speedX[i] *= -1;
      }
      if (y[i] <= 0 || y[i] >= height) {
        speedY[i] *= -1;
      }

      // Simulate wing flapping
      wingPosition[i] = sin(radians(frameCount * 5)) * 20; // Flap the wings up and down
    }

    void display(int i) {
      fill(255, 200, 0); // Yellow color
      ellipse(x[i], y[i], 30, 20);

      // Draw wings
      fill(255); // White color
      pushMatrix();
      translate(x[i], y[i]);
      rotate(radians(wingPosition[i]));
      triangle(0, 0, -wingSpan[i] / 2, 15, -wingSpan[i] / 2, -15);
      triangle(0, 0, wingSpan[i] / 2, 15, wingSpan[i] / 2, -15);
      popMatrix();
    }