openobject.org

Using Arrays in Processing

From Physical Programming

An Array is a collection of data. Each piece of data in an array is identified by an index number. The first element in the array has an index number of [0], the second element is [1], and so on. The image below gives a graphical representation of an array.

Image:MyArray_1D.gif

Arrays are similar to objects and must be created using the new keyword. The total number of elements in an array (the array's length) is defined when the array is created (the length of an array may be modified latter using various array functions).

Use:

int[] numbers = new int[3];
numbers[0] = 90;
numbers[1] = 150;
numbers[2] = 30;
int a = numbers[0] + numbers[1]; 	// Sets variable a to 240
int b = numbers[1] + numbers[2]; 	// Sets variable b to 180
String[] animals = new String[3]; 
animals[0] = "cat"; 
animals[1] = "seal"; 
animals[2] = "bear"; 


Multi-Dimentional Arrays

It is also possible to have an array that contains arrays (and those arrays can contain yet more arrays, and so on). These are called multi-dimentional arrays and are particularly useful for storing data from a grid formation. The image below gives a graphical representation of a 2 dimentional array.

Image:MyArray_2D.gif

A multi-dimentional array is defined using two or more sets of square brackets as in the example below.

int[][] numberGrid = new int[5][8]; 	// This code produces an array of 5 x 8 integers.

The following code creates an array of 200 x 200 color values and populates the array with random colors. It then draws these colors as points on the Display Window.

size(200, 200);

color[][] allPixels = new color[width][height];

for(int x=0; x<width; x++) {
  for(int y=0; y<height; y++){
    allPixels[x][y] = color(random(255), random(255), random(255));
  }
}

for(int x=0; x<width; x++) {
  for(int y=0; y<height; y++){
    stroke(allPixels[x][y]);
    point(x,y);
  }
}

Multi-dimentional arrays are often used in grid based games. In the example below each square on the gameboard can be represented using a 2 dimentional array.

Image:gameboard.gif

An array of 16 x 14 boolean values could be used to store the location of the path.

boolean[][] path = new boolean[16][14];
path[0][0] = false;
path[0][1] = false;
path[0][2] = false;
path[0][3] = false;
...
path[1][0] = false;
path[1][1] = true;
path[1][2] = true;
path[1][3] = true;
... and so on.

A players position could be stored as a grid reference.

player.x = 9;
player.y = 3;

To determine if a players move is valid we can then simply check the array to see if the new grid location is defined as a path.

if (path[newLocation.x][newLocation.y]) {
	// the move is valid
}


A Game of Life

Multi-dimentional arrays are perfect for storing cell states for Conway's Game of Life. The following Processing sketch uses a 2D array of boolean values to store the game state. The board size is set by the size of the display window. Cell size is defined by the variable cellSize. Initial population is set by the fillGrid() function.

/*
* Conway's Game of Life
* by Scott Mitchell
*/

boolean[][] gridOfLife;
int cellSize = 4;
int gridWidth;
int gridHeight;


void setup()
{
 size(600, 600);
 noStroke();
 frameRate(10);
 // set grid size
 gridWidth = floor(width/cellSize);
 gridHeight = floor(height/cellSize);
 // instigate the array
 gridOfLife = new boolean[gridWidth][gridHeight];
 // populate grid
 fillGrid();
}


void draw()
{
 background(0);
 displayGrid();
 updateGrid();
}


void fillGrid()
{
 // fill the grid with random values
 for (int x = 0; x < gridWidth; x++) {
   for (int y = 0; y < gridHeight; y++) {
     if (random(1) > 0.9) {
       // make the square live
       gridOfLife[x][y] = true;
     } 
     else {
       // make the square dead
       gridOfLife[x][y] = false;
     }
   }
 }
}


void displayGrid()
{
 // cycle through the grid and draw the true values
 for (int x = 0; x < gridWidth; x++) {
   for (int y = 0; y < gridHeight; y++) {
     if (gridOfLife[x][y]) {
       drawSquare(x, y);
     }
   }  
 }
}


void drawSquare(int x, int y)
{
 rectMode(CENTER);
 int originx = x * cellSize;
 int originy = y * cellSize;
 fill(255);
 rect(originx, originy, cellSize, cellSize);
}


void updateGrid()
{
 // setup temperary array to hold new grid state
 boolean[][] tempGrid = new boolean[gridWidth][gridHeight];
 // cycle through the grid and check the neighbours
 for (int x = 0; x < gridWidth; x++) {
   for (int y = 0; y < gridHeight; y++) {
     // count live cells
     int liveCells = 0;
     // top left
     if (checkCell(x-1, y-1)) {
       liveCells++;
     }
     // left
     if (checkCell(x-1, y)) {
       liveCells++;
     }
     // bottom left
     if (checkCell(x-1, y+1)) {
       liveCells++;
     }
     // top
     if (checkCell(x, y-1)) {
       liveCells++;
     }
     // bottom
     if (checkCell(x, y+1)) {
       liveCells++;
     }
     // top right
     if (checkCell(x+1, y-1)) {
       liveCells++;
     }
     // right
     if (checkCell(x+1, y)) {
       liveCells++;
     }
     // bottom right
     if (checkCell(x+1, y+1)) {
       liveCells++;
     }
     // applly rules of life
     // dies of loneliness or overcrowding
     if (liveCells < 2 || liveCells > 3) {
       tempGrid[x][y] = false;
     } 
     // comes alive
     else if (liveCells == 3) {
       tempGrid[x][y] = true;
     } 
     // stays the same
     else {
       tempGrid[x][y] = gridOfLife[x][y];
     }
   }
 }
 // replace old state with new state
 gridOfLife = tempGrid;
}


boolean checkCell(int cellx, int celly)
{
 // check to see if neighbour is out of bounds
 if (cellx < 0 || celly < 0 || cellx >= gridWidth || celly >= gridHeight) {
   return false;
 } 
 // if not then return the cells state
 else {
   return gridOfLife[cellx][celly];
 }
}


Some of the examples above are based on Glenn Mitchell's Game Programming Principles course notes for Flash, 2006.