aerodynamics
Published © GPL3+

Arduino LED Matrix Game of Life

A Conway's Game of Life running of an Arduino and displayed on the 32x16 RGB LED matrix.

IntermediateShowcase (no instructions)5 hours14,516
Arduino LED Matrix Game of Life

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
Works on any Arduino board
×1
Adafruit 32x16 RGB LED MATRIX
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Code

ARDUINO CONWAY'S GAME OF LIFE

Arduino
Arduino Code to display a Game of Life on a LED Matrix (memory light to be able to work with the matrix)
/*****************************************************************
 *****************************************************************

  CONWAY'S GAME OF LIFE V1

  DATE : 19 JAN 2018

  CONCEPTOR : AERODYNAMICS

  This program intends to run a CONWAYS'S Game of Life on an Arduino
  and to display it on a 16x32 LED MATRIX


* *****************************************************************
*******************************************************************/

//////////////////////////
//      LIBRARIES       //
//////////////////////////

#include <Adafruit_GFX.h>   // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library
#include <EEPROM.h> // To store on EEPROM Memory


//////////////////////////
//       VARIABLES      //
//////////////////////////

//Definition of the pattern if you use the pattern initialization
int pattern_size[] = {7, 22}; // row x Column
char pattern_init[] =
  ".........*,\
.......*.*,\
......*.*,\
**...*..*...........**,\
**....*.*...........**,\
.......*.*,\
.........*!";

bool WORLD[16][32]; // Creation of the wordl
int step_GOL; //used to know the generation

//////////////////////////
//       OBJECTS        //
//////////////////////////


//Definition of the LED Matrix Object
#define CLK 8  // MUST be on PORTB! (Use pin 11 on Mega)
#define LAT A3
#define OE  9
#define A   A0
#define B   A1
#define C   A2
// Last parameter = 'true' enables double-BUFFER_WORLDing, for flicker-free,
// buttery smooth animatrixion.  Note that NOTHING WILL SHOW ON THE DISPLAY
// until the first call to swapBuffers().  This is normal.

RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false); //I couldn't use double buffering because it uses
//too much memory

/*************************************************************************************************************/
//////////////////////////
//          SETUP       //
//////////////////////////
void setup() {
  //Serial.begin(115200); //use to print the game on the serial monitor (to debug)

  //Randomly initialazing the world for the first step
  randomSeed(analogRead(5));
  for (byte i = 0; i < 16; i++) {
    for (byte j = 0; j < 32; j++) {
      WORLD[i][j] = random(0, 2);
    }
  }

  //init_WORLD(); // Uncomment if you want to init with a specific pattern

  step_GOL = 0;
  matrix.begin();
  print_WORLD(); //Display the first generation

}


/*************************************************************************************************************/
//////////////////////////
//    LOOP FUNCTION     //
//////////////////////////
void loop() {
  if (step_GOL == 60) { // This if reboot the world after 60 generation to avoid static world
    step_GOL = 0;
    matrix.fillScreen(0);
    delay(500);
    randomSeed(analogRead(5));
    for (byte i = 0; i < 16; i++) {
      for (byte j = 0; j < 32; j++) {
        WORLD[i][j] = random(0, 2);
      }
    }
  }
  //This double "for" is used to update the world to the next generation
  //The buffer state is written on the EEPROM Memory

  for (byte i = 0; i < 16; i++) {
    for (byte j = 0; j < 32; j++) {

      if (i == 0 || i == 15 || j == 0 || j == 31) // I choose to keep the border at 0
      {
        EEPROM.write(i * 31 + j , 0);
      }
      else {
        byte num_alive = WORLD[i - 1][j - 1] + WORLD[i - 1][j] + WORLD[i - 1][j + 1] + WORLD[i][j - 1] + WORLD[i][j + 1] + WORLD[i + 1][j - 1] + WORLD[i + 1][j] + WORLD[i + 1][j + 1];
        bool state = WORLD[i][j];

        //RULE#1 if you are surrounded by 3 cells --> you live
        if (num_alive == 3) {
          EEPROM.write(i * 31 + j , 1);
        }
        //RULE#2 if you are surrounded by 2 cells --> you stay in your state
        else if (num_alive == 2) {
          EEPROM.write(i * 31 + j , state);
        }
        //RULE#3 otherwise you die from overpopulation or subpopulation
        else {
          EEPROM.write(i * 31 + j , 0);
        }
      }
    }
  }

  //Updating the World
  for (byte i = 0; i < 16; i++) {
    for (byte j = 0; j < 32; j++) {
      WORLD[i][j] = EEPROM.read(i * 31 + j);
    }
  }

  //Displaying the world
  print_WORLD();

  //Increasing the generation
  step_GOL++;

}

/*************************************************************************************************************/
//////////////////////////
//       FUNCTIONS      //
//////////////////////////


// PRINT THE WORLD
void print_WORLD()
{
  for (byte j = 0; j < 32; j++) {
    for (byte i = 0; i < 16; i++) {
      if (WORLD[i][j] == 0) {
        matrix.drawPixel(j, i, matrix.Color333(0, 0, 0));
      }
      else
      {
        matrix.drawPixel(j, i, matrix.Color333(0, 1, 2));
      }
    }
  }
}

//Those two function are used to display the world on the serial monitor
//Not beautiful but useful to debug

void print_WORLD_SERIAL()
{
  clearscreen();
  Serial.print("Step = "); Serial.println(step_GOL);
  for (int i = 0; i < 16; i++) {
    for (int j = 0; j < 32; j++) {
      if (WORLD[i][j] == 0) {
        Serial.print(".");
        Serial.print(" ");
      }
      else
      {
        Serial.print("*");
        Serial.print(" ");
      }
    }
    Serial.println("");
  }
  Serial.println("");

}

void clearscreen() {
  for (int i = 0; i < 10; i++) {
    Serial.println("\n\n\n\n");
  }
}

//This function is used to init the world with a know pattern
//It read . and * to convert them to 0 and 1.
//Inspired from life 1.05 format
// NB : this function needs improvment to center the pattern

void init_WORLD() {
  int k = 0;
  int row = 0;
  int column = 0;
  while (pattern_init[k] != '!') {
    if (pattern_init[k] == ',') {
      row++;
      k++;
      column = 0;
    }
    else if (pattern_init[k] == '.') {
      WORLD[row + 2][column + 4] = 0;
      k++;
      column ++;
    }
    else  {
      WORLD[row + 2][column + 4] = 1;
      k++;
      column ++;
    }
  }
}

Credits

aerodynamics

aerodynamics

4 projects • 27 followers

Comments