Game Of Life Visualizer

processingjava3daudio

Last updated: December 10th. 2022

Description

I'm not sure how many people are familiar with the Game of Life algorithm by British mathematician John Conway, which he devised in 1970, but when I came across it, it mezmerized me. It's really something special. I'm not going to go into detail on how it works, there are plenty of articles about it online, but the basic principle is that you start with a 2d matrix and an initial state of live and dead cells. After each iteration, the algorithm decides whether a cell lives or dies, based on the following criteria of the surrounding cells:

  • any live cell with two or three live neighbors survives
  • any dead cell with three live neighbors becomes a live cell
  • all other live cells die in the next generation
  • all other dead cells stay dead

There are some really interesting effects to these specific rules. All kinds of patterns appear. One of the coolest, I think, is the Gosper glider gun:

game-of-life-visualizer_glider-gun

It is a self-sustaining pattern that spawns gliders, kind of like a little factory.

Implementation

For this project, I used Processing, which is a Java-based software sandbox aimed at visual art. I started using it when I was studying Audio Design at the Utrecht School of the Arts and It is a great tool for working with audio and visuals. I thought it would be cool to do something with the Game of Life algorithm in 3d space so that's how this project came to life.

Simulation

The rules for the simulation can be represented in code like this:

void calculatePixels()
{
  int state = -1;
  int totalgrid = 0;
  int random = int(random(-16777261, -1));
  for (int i=1; i<h; i++)
  {
    for (int j=1; j<w; j++)
    {
      state = grid[(w*j)+i];
      totalgrid = 0;
      // check how much surrounding cells are alive.
      if (grid[((w*j)+i)-(w-1)] < -1) totalgrid++; // left upper box
      if (grid[((w*j)+i)-w]< -1) totalgrid++; // upper box
      if (grid[((w*j)+i)-(w+1)]< -1) totalgrid++; // right upper box
      if (grid[((w*j)+i)-1]< -1) totalgrid++; // left box
      if (grid[((w*j)+i)+1]< -1) totalgrid++; // right box
      if (grid[((w*j)+i)+(w-1)]< -1) totalgrid++; // left lower box
      if (grid[((w*j)+i)+w]< -1) totalgrid++; // lower box
      if (grid[((w*j)+i)+(w+1)]< -1) totalgrid++;  // right lower box

      // execute the algorithm
      if (grid[(w*j)+i] < -1 && totalgrid<2) state = -1;
      else if (grid[(w*j)+i] < -1 && totalgrid>3) state = -1;
      else if (grid[(w*j)+i] < -1 && (totalgrid==2 || totalgrid==3)) state = random;
      else if (grid[(w*j)+i] == -1 && totalgrid==3) state = random;

      // write the state of the current cell to a temporary grid
      tempGrid[(w*j)+i] = state;
    }
  }

  // only after the entire array has been iterated through, refresh the grid.
  for (int i=0; i<arraySize; i++)
  {
    grid[i] = tempGrid[i];
  }
}

With the simulation working, we then render a grid in the center of a 3d space, and then draw the cells as cuboids, where the height of the cuboids is determined by the output of an FFT analyzed audio signal aimed at the low-end. A camara and a few lights make for an interesting visualizer. The result can be seen here.

back