Chapter 10. Arrays

We've introduced new programming ideas in each chapter (variables, functions, objects) and now we've come to the last step—arrays! An array is a list of variables that share a common name. Arrays are useful because they make it possible to work with more variables without creating a new name for each. This makes the code shorter, easier to read, and more convenient to update.

To see what we mean, refer to Example 7-3: Move a Shape. This code works fine if we're moving around only one shape, but what if we want to have two? We need to make a new x variable and update it within draw():

image with no caption
float x1 = 20;
float x2 = 20;

void setup() {
  size(240, 120);
  smooth();
  noStroke();
}

void draw() {
  background(0);
  x1 += 0.5;
  x2 += 0.5;
  arc(x1, 30, 40, 40, 0.52, 5.76);
  arc(x2, 90, 40, 40, 0.52, 5.76);
}

The code for the previous example is still manageable, but what if we want to have five circles? We need to add three more variables to the two we already have:

image with no caption
float x1 = 10;
float x2 = 10;
float x3 = 35;
float x4 = 18;
float x5 = 30;

void setup() {
  size(240, 120);
  smooth();
  noStroke();
}

void draw() {
  background(0);
  x1 += 0.5;
  x2 += 0.5;
  x3 += 0.5;
  x4 += 0.5;
  x5 += 0.5;
  arc(x1, 20, 20, 20, 0.52, 5.76);
  arc(x2, 40, 20, 20, 0.52, 5.76);
  arc(x3, 60, 20, 20, 0.52, 5.76);
  arc(x4, 80, 20, 20, 0.52, 5.76);
  arc(x5, 100, 20, 20, 0.52, 5.76);
}

This code is starting to get out of control.

Imagine what would happen if you wanted to have 3,000 circles. This would mean creating 3,000 individual variables, then updating each one separately. Could you keep track of that many variables? Would you want to? Instead, we use an array:

image with no caption
float[] x = new float[3000];

void setup() {
  size(240, 120);
  smooth();
  noStroke();
  fill(255, 200);
  for (int i = 0; i < x.length; i++) {
    x[i] = random(-1000, 200);
  }
}

void draw() {
  background(0);
  for (int i = 0; i < x.length; i++) {
    x[i] += 0.5;
    float y = i * 0.4;
    arc(x[i], y, 12, 12, 0.52, 5.76);
  }
}

We'll spend the rest of this chapter talking about the details that make this example possible.

Make an Array

Each item in an array is called an element, and each has an index value to mark its position within the array. Just like coordinates on the screen, index values for an array start counting from 0. For instance, the first element in the array has the index value 0, the second element in the array has the index value 1, and so on. If there are 20 values in the array, the index value of the last element is 19. Figure 10-1 shows the conceptual structure of an array.

An array is a list of one or more variables that share the same name.

Figure 10-1. An array is a list of one or more variables that share the same name.

Using arrays is similar to working with single variables; it follows the same patterns. As you know, you can make a single integer variable called x with this code:

int x;

To make an array, just place brackets after the data type:

int[] x;

The beauty of creating an array is the ability to make 2, 10, or 100,000 variable values with only one line of code. For instance, the following line creates an array of 2,000 integer variables:

int[] x = new int[2000];

You can make arrays from all Processing data types: boolean, float, String, PShape, and so on, as well as any user-defined classes. For example, the following code creates an array of 32 PImage variables:

PImage[] images = new PImage[32];

To make an array, start with the name of the data type, followed by the brackets. The name you select for the array is next, followed by the assignment operator (the equal symbol), followed by the new keyword, followed by the name of the data type again, with the number of elements to create within the brackets. This pattern works for arrays of all data types.

Note

Each array can store only one type of data (boolean, int, float, PImage, etc.). You can't mix and match different types of data within a single array. If you need to do this, work with objects instead.

Before we get ahead of ourselves, let's slow down and talk about working with arrays in more detail. Like making an object, there are three steps to working with an array:

  1. Declare the array and define the data type.

  2. Create the array with the keyword new and define the length.

  3. Assign values to each element.

Each step can happen on its own line, or all the steps can be compressed together. Each of the three following examples shows a different technique to create an array called x that stores two integers, 12 and 2. Pay close attention to what happens before setup() and what happens within setup().

First we'll declare the array outside of setup() and then create and assign the values within. The syntax x[0] refers to the first element in the array and x[1] is the second:

int[] x;            // Declare the array

void setup() {
  size(200, 200);
  x = new int[2];   // Create the array
  x[0] = 12;        // Assign the first value
  x[1] = 2;         // Assign the second value
}

Here's a slightly more compact example, in which the array is both declared and created on the same line, then the values are assigned within setup():

int[] x = new int[2];  // Declare and create the array

void setup() {
  size(200, 200);
  x[0] = 12;           // Assign the first value
  x[1] = 2;            // Assign the second value
}

You can also assign values to the array when it's created, if it's all part of a single statement:

int[] x = { 12, 2 };  // Declare, create, and assign

void setup() {
  size(200, 200);
}

Note

Avoid creating arrays within draw(), because creating a new array on every frame will slow down your frame rate.

As a complete example of how to use arrays, we've recoded Example 10-1: Many Variables here. Although we don't yet see the full benefits revealed in Example 10-3: Arrays, Not Variables, we do see some important details of how arrays work:

float[] x = {-20, 20};

void setup() {
  size(240, 120);
  smooth();
  noStroke();
}

void draw() {
  background(0);
  x[0] += 0.5;  // Increase the first element
  x[1] += 0.5;  // Increase the second element
  arc(x[0], 30, 40, 40, 0.52, 5.76);
  arc(x[1], 90, 40, 40, 0.52, 5.76);
}

Repetition and Arrays

The for loop, introduced in Repetition in Chapter 4, makes it easier to work with large arrays while keeping the code concise. The idea is to write a loop to move through each element of the array one by one. To do this, you need to know the length of the array. The length field associated with each array stores the number of elements. We use the name of the array with the dot operator (a period) to access this value. For instance:

int[] x = new int[2];     // Declare and create the array
println(x.length);        // Prints 2 to the Console

int[] y = new int[1972];  // Declare and create the array
println(y.length);        // Prints 1972 to the Console

A for loop can be used to fill an array with values, or to read the values back out. In this example, the array is first filled with random numbers inside setup(), and then these numbers are used to set the stroke value inside draw(). Each time the program is run, a new set of random numbers is put into the array:

image with no caption
float[] gray;

void setup() {
  size(240, 120);
  gray = new float[width];
  for (int i = 0; i < gray.length; i++) {
    gray[i] = random(0, 255);
 }
}

void draw() {
  for (int i = 0; i < gray.length; i++) {
    stroke(gray[i]);
    line(i, 0, i, height);
  }
}

In this example, there are two arrays to store the position of the mouse—one for the x-coordinate and one for the y-coordinate. These arrays store the location of the mouse for the previous 60 frames. With each new frame, the oldest x- and y-coordinate values are removed and replaced with the current mouseX and mouseY values. The new values are added to the first position of the array, but before this happens, each value in the array is moved one position to the right (from back to front) to make room for the new numbers. This example visualizes this action. Also, at each frame, all 60 coordinates are used to draw a series of ellipses to the screen:

image with no caption
int num = 60;
int [] x = new int[num];
int [] y = new int[num];

void setup() {
  size(240, 120);
  smooth();
  noStroke();
}

void draw() {
  background(0);
  // Copy array values from back to front
  for (int i = x.length-1; i > 0; i−−) {
    x[i] = x[i-1];
    y[i] = y[i-1];
  }
  x[0] = mouseX;  // Set the first element
  y[0] = mouseY;  // Set the first element
  for (int i = 0; i < x.length; i++) {
    fill(i * 4);
    ellipse(x[i], y[i], 40, 40);
  }
}

Note

The technique for storing a shifting buffer of numbers in an array shown in this example and Figure 10-2 is less efficient than an alternative technique that uses the % (modulo) operator. This is explained in the Examples→Basics→Input→StoringInput example included with Processing.

Shifting the values in an array one place to the right.

Figure 10-2. Shifting the values in an array one place to the right.

Arrays of Objects

The two short examples in this section bring together every major programming concept in this book: variables, iteration, conditionals, functions, objects, and arrays. Making an array of objects is nearly the same as making the arrays we introduced on the previous pages, but there's one additional consideration: because each array element is an object, it must first be created with the keyword new (like any other object) before it is assigned to the array. With a custom-defined class such as JitterBug (see Chapter 9), this means using new to set up each element before it's assigned to the array. Or, for a built-in Processing class such as PImage, it means using the loadImage() function to create the object before it's assigned.

This example creates an array of 33 JitterBug objects and then updates and displays each one inside draw(). For this example to work, you need to add the JitterBug class to the code:

image with no caption
JitterBug[] bugs = new JitterBug[33];

void setup() {
  size(240, 120);
  smooth();
  for (int i = 0; i < bugs.length; i++) {
    float x = random(width);
    float y = random(height);
    int r = i + 2;
    bugs[i] = new JitterBug(x, y, r);
  }
}

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

// Copy JitterBug class here

The final array example loads a sequence of images and stores each as an element within an array of PImage objects.

To run this example, get the images from the media.zip file as described in Chapter 6. The images are named sequentially (frame-0000.png, frame-0001.png, and so forth), which makes it possible to create the name of each file within a for loop, as seen in the eighth line of the program:

image with no caption
int numFrames = 12;  // The number of frames
PImage[] images = new PImage[numFrames];  // Make the array
int currentFrame = 0;

void setup() {
  size(240, 120);
  for (int i = 0; i < images.length; i++) {
    String imageName = "frame-" + nf(i, 4) + ".png";
    images[i] = loadImage(imageName);  // Load each image
  }
  frameRate(24);
}


void draw() {
  image(images[currentFrame], 0, 0);
  currentFrame++;      // Next frame
  if (currentFrame >= images.length) {
    currentFrame = 0;  // Return to first frame
  }
}

The nf() function formats numbers so that nf(1, 4) returns the string "0001" and nf(11, 4) returns "0011". These values are concatenated with the beginning of the file name ("frame-") and the end (".png") to create the complete file name as a String variable. The files are loaded into the array on the following line. The images are displayed to the screen one at a time in draw(). When the last image in the array is displayed, the program returns to the beginning of the array and shows the images again in sequence.

image with no caption

Arrays make it easier for a program to work with many elements. In this example, an array of Robot objects is declared at the top. The array is then allocated inside setup(), and each Robot object is created inside the for loop. In draw(), another for loop is used to update and display each element of the bots array.

The for loop and an array make a powerful combination. Notice the subtle differences between the code for this example and Robot 7 (see Robot 7: Objects in Chapter 9) in contrast to the extreme changes in the visual result. Once an array is created and a for loop is put in place, it's as easy to work with 3 elements as it is 3,000.

The decision to load the SVG file within setup() rather than in the Robot class is the major change from Robot 7. This choice was made so the file is loaded only once, rather than as many times as there are elements in the array (in this case, 20 times). This change makes the code start faster because loading a file takes time, and it uses less memory because the file is stored once. Each element of the bot array references the same file.

Robot[] bots;  // Declare array of Robot objects

void setup() {
  size(720, 480);
  PShape robotShape = loadShape("robot1.svg");
  // Create the array of Robot objects
  bots = new Robot[20];
  // Create each object
  for (int i = 0; i < bots.length; i++) {
    // Create a random x-coordinate
    float x = random(-40, width-40);
    // Assign the y-coordinate based on the order
    float y = map(i, 0, bots.length, 100, height-200);
    bots[i] = new Robot(robotShape, x, y);
  }
  smooth();
}

void draw() {
  background(204);
  // Update and display each bot in the array
  for (int i = 0; i < bots.length; i++) {
    bots[i].update();
    bots[i].display();
  }
}

class Robot {
  float xpos;
  float ypos;
  float angle;
  PShape botShape;
  float yoffset = 0.0;

  // Set initial values in constructor
  Robot(PShape shape, float tempX, float tempY) {
    botShape = shape;
    xpos = tempX;
    ypos = tempY;
    angle = random(0, TWO_PI);
 }
 // Update the fields
 void update() {
   angle += 0.05;
   yoffset = sin(angle) * 20;
 }

 // Draw the robot to the screen
 void display() {
   shape(botShape, xpos, ypos + yoffset);
 }

}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.93.141