Introduction: NeoPixels Matrix:Snake Game

About: ElecFreaks is an open design house founded in March 2011. Our goal is to create rapid prototypes and give small-batch manufacture solution for makers and startups. With over 50% staff as engineers and expanded…

Do you still remember snake game we played on our game box or mobile during our childhood? Today we are going to learn how to make a snake game with 8*8 NeoPixels Matrix. We choose Arduino uno as the control center and Joystick breakout module to control the snake.


Step 1: Components List:

Step 2: Hardware Connection

Connect NeoPixels to pin D2.

"X" on Joystick breakout module connect pin A0 on Arduino UNO board, "Y" connect pin A1, "K" connect pin A2.

Step 3: Programming

<span style="color: black; font-family: Arial; font-size: 12pt;">P#include <Adafruit_NeoPixel.h>


#define PIN 2           //Output Pin
#define MAX_LED 64       //Quantity of bead
uint32_t c;
int a = 0 , number;
unsigned char huan = 0, ci = 0;
unsigned char  u = 40; //The font size of word group
unsigned char x = 0;
unsigned char Colour[3];
unsigned char go[] = {2, 3, 4, 5, 9, 14, 17, 20, 22, 26, 27, 29, 34, 35, 36, 37, 41, 46, 49, 54, 58, 59, 60, 61}; //24
unsigned char light[8][8] = {
  {0, 1, 2, 3, 4, 5, 6, 7},
  {15, 14, 13, 12, 11, 10, 9, 8},
  {16, 17, 18, 19, 20, 21, 22, 23},
  {31, 30, 29, 28, 27, 26, 25, 24},
  {32, 33, 34, 35, 36, 37, 38, 39},
  {47, 46, 45, 44, 43, 42, 41, 40},
  {48, 49, 50, 51, 52, 53, 54, 55},
  {63, 62, 61, 60, 59, 58, 57, 56},
} ;
unsigned char character[][8] =  //Set the word to be sent
{
  {0, 1, 1, 1, 1, 1, 0, 0},
  {0, 1, 0, 0, 0, 1, 0, 0}, // 0
  {0, 1, 1, 1, 1, 1, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},


  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0}, // 1
  {0, 1, 1, 1, 1, 1, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},


  {0, 1, 0, 1, 1, 1, 0, 0},
  {0, 1, 0, 1, 0, 1, 0, 0}, // 2
  {0, 1, 1, 1, 0, 1, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},


  {0, 1, 0, 1, 0, 1, 0, 0},
  {0, 1, 0, 1, 0, 1, 0, 0}, // 3
  {0, 1, 1, 1, 1, 1, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},


  {0, 1, 1, 1, 0, 0, 0, 0},
  {0, 0, 0, 1, 0, 0, 0, 0}, // 4
  {0, 1, 1, 1, 1, 1, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},


  {0, 1, 1, 1, 0, 1, 0, 0},
  {0, 1, 0, 1, 0, 1, 0, 0}, // 5
  {0, 1, 0, 1, 1, 1, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},


  {0, 1, 1, 1, 1, 1, 0, 0},
  {0, 1, 0, 1, 0, 1, 0, 0}, // 6
  {0, 1, 0, 1, 1, 1, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},


  {0, 1, 0, 0, 0, 0, 0, 0},
  {0, 1, 0, 0, 0, 0, 0, 0}, // 7
  {0, 1, 1, 1, 1, 1, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},


  {0, 1, 1, 1, 1, 1, 0, 0},
  {0, 1, 0, 1, 0, 1, 0, 0}, // 8
  {0, 1, 1, 1, 1, 1, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},


  {0, 1, 1, 1, 0, 1, 0, 0},
  {0, 1, 0, 1, 0, 1, 0, 0}, // 9
  {0, 1, 1, 1, 1, 1, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
};


unsigned char displayscore [8][8];


int speedS = 400;                                                         // Initial speed of snake
int score;                                                              // Game score
int xValue;                                                             // JoyStick-X
int yValue;                                                             // JoyStick-Y
int zValue;                                                             // JoyStick-Z
int FX, FY;                                                             // Coordinate of food
int SX, SY;                                                             // Coordinate of snake head
int KEY, K;
int Enabled;                                                            // Enable to restart game


char sx[64] ;                                                     //Coordinate of snake body 
char sy[64];
Adafruit_NeoPixel strip = Adafruit_NeoPixel( MAX_LED, PIN, NEO_RGB + NEO_KHZ800 );






void RANDOM() {
A:
  FX = random(0, 7);
  FY = random(0, 7);


  for (int i = 0; i < 3 + score; i++)          //Prevent food display on snake body
  {
    if ( FX == sx[i] && FY == sy[i])
      goto A;
  }
}
void myDelay( unsigned int Time) {                             // During the delay period of snake movement, we have to do something like food glitter and read the direction of Joystick


  for (int t = 1; t <= Time; t++)
  {
    joyStick();
    delay(1);                                     //Read the direction of Joystick 
  }
}
void joyStick() {


  xValue = analogRead(A0);                             // JoyStick-X   The leftmost value is 0, the rightmost value is 1023, and the middle value is 515.
  yValue = analogRead(A1);                             // JoyStick-Y   The bottom value is 0, the top value is 1023, the middle value is 510.


  if (yValue > 950 && KEY != 5) {
    K = 8;
  }
  else if (yValue < 50 && KEY != 8) {
    K = 5;
  }
  else if (xValue < 50  && KEY != 6 && K != 0) {       // Before operate Joystic for the first time, you can't move snake to the left direction. 
    K = 4;
  }
  else if (xValue > 950 && KEY != 4) {
    K = 6;
  }
}
// Here you can compare whether the direction of keypad is opposite to the snake move direction. If it is opposite, then give up the keypad. 
/***************************************************************************************************************************************************************************************************************/
void gameover() {                                      // Once Gameover program stopped, press the central button to restart the game.
  unsigned char value, y;


  Colour[0] = random(3 , 18); // Set color.Parameter is R G B, range 0-255.
  Colour[1] = random(3, 18);
  Colour[2] = random(3, 18);
  c = strip.Color(Colour[1], Colour[0], Colour[2]);
  value = score / 10;
  value = value * 4;
  y = 0;


  for (number = value; number < value + 4; number++)
  {
    for (unsigned char vertical = 0; vertical < 8; vertical++)
    {
      displayscore[y][vertical] = character[number][vertical];




    }
    y++;
  }


  value = score % 10;
  value = value * 4;


  for (number = value; number < value + 4; number++)
  {
    for (unsigned char vertical = 0; vertical < 8; vertical++)
    {
      displayscore[y][vertical] = character[number][vertical];


    }
    y++;
  }


  for (unsigned char horizontal = 0; horizontal < 8; horizontal++)
  {
    for (unsigned char vertical = 0; vertical < 8; vertical++)
    {


      if (displayscore[horizontal][vertical] == 1) //Judge whether the light is on.
      {
        strip.setPixelColor(light[horizontal][vertical],  c);
      }
      else
        strip.setPixelColor(light[horizontal][vertical],  0);


    }
  }


  strip.show();//Send data
  delay(5000);
  K = 0;                  // Reset Joystick direction
  sx[0] = 2;
  sx[1] = 1;
  sx[2] = 0;
  sy[0] = 1;
  sy[1] = 1;
  sy[2] = 1;               // Reset snake coordinate
  score = 0;              // Reset game score
  speedS = 400;                                                         // The initial speed of snake


}
void setup() {
  Serial.begin(9600);
  // Initialize library
  strip.begin();
  // Send data. Default the color of each point as 0. So every point is not illuminated at the beginning. 
  strip.show();
  K = 0;                  // Reset the direction of Joystick
  sx[0] = 2;
  sx[1] = 1;
  sx[2] = 0;
  sy[0] = 1;
  sy[1] = 1;
  sy[2] = 1;               // Reset snake coordinate
  score = 0;              // Reset game score
  Colour[0] = random(3 , 18); // Set color.Parameter is R G B, range 0-255.
  Colour[1] = random(3, 18);
  Colour[2] = random(3, 18);
  c = strip.Color(Colour[1], Colour[0], Colour[2]); //Green  Red Blue // Set color
  for (number = 0; number < 24; number++)
  {
    strip.setPixelColor(go[number],  c);
  }
  strip.show();// Send data
  delay(2000);
  RANDOM();     //Produce food
}
void mobile()
{


  KEY = K;                                      //Every movement of snake makes the direction change for once. 




  if (KEY == 8)                                 // Snake upward movement
  {
    for (int i = 2 +  score; i > 0; i--)
    {
      sx[i] = sx[i - 1];
      sy[i] = sy[i - 1];
    }
    sy[0] = sy[0] - 1;
    if (sy[0] < 0)                               // Go beyond the border and continue on the other side
      sy[0] = 7;
  }
  else if (KEY == 5)                            // Snake downward movement
  {
    for (int i = 2 +  score; i > 0; i--)
    {
      sx[i] = sx[i - 1];
      sy[i] = sy[i - 1];
    }
    sy[0] = sy[0] + 1;
    if (sy[0] > 7)                               // Go beyond the border and continue on the other side
      sy[0] = 0;
  }
  else if (KEY == 4)                            // Snake left movement
  {
    for (int i = 2 +  score; i > 0; i--)
    {
      sx[i] = sx[i - 1];
      sy[i] = sy[i - 1];
    }
    sx[0] = sx[0] - 1;
    if (sx[0] < 0)                               // Go beyond the border and continue on the other side
      sx[0] = 7;
  }
  else if (KEY == 6)                            // Snake right movement
  {
    for (int i = 2 +  score; i > 0; i--)
    {
      sx[i] = sx[i - 1];
      sy[i] = sy[i - 1];
    }
    sx[0] = sx[0] + 1;
    if (sx[0] > 7)                               // Go beyond the border and continue on the other side
      sx[0] = 0;
  }
  // Move snake body with button
}
void displays()
{
  for (number = 0; number < 64; number++)   //Clear the screen
  {
    strip.setPixelColor(number,  0);
  }
  strip.show();


  Colour[0] = 40; // Set color. Parameter is R G B, range 0-255.
  Colour[1] = 0;
  Colour[2] = 0;
  c = strip.Color(Colour[1], Colour[0], Colour[2]); //Green Red Blue    // Set color
  x = light[FX][FY];                                              //Display food
  strip.setPixelColor(x, c);


  Colour[0] = random(3 , 18); // Set color. Parameter is R G B, range 0-255.
  Colour[1] = random(3, 18);
  Colour[2] = random(3, 18);
  c = strip.Color(Colour[1], Colour[0], Colour[2]); //Green Red Blue  // Set color


  for (int i = 2 +  score; i > 0; i--)                   //Display snake body
  {


    x = light[sx[i]][sy[i]];
    strip.setPixelColor(x,  c);
  }


  Colour[0] = 0; // Set color. Parameter is R G B, range 0-255.
  Colour[1] = 40;
  Colour[2] = 0;
  c = strip.Color(Colour[1], Colour[0], Colour[2]); //Green Red Blue    // Set color
  x = light[sx[0]][sy[0]];                                        //Display snake head
  strip.setPixelColor(x,  c);


  strip.show();//Send data
}
void loop() {




  mobile();
  myDelay(speedS);                                // Within() is delay time.
  displays();
  SX = sx[0];
  SY = sy[0];
  // Get coordinate of snake head


  for (int i = 1; i <= 2 + score; i++)
  {
    if ( SX == sx[i] && SY == sy[i])
      gameover();
  }
  // Judge whether snake head touched its body. If touched, then forward to GameOver.


  if (SY == FY && SX == FX)
  {
    RANDOM();
    score ++;
    Colour[0] = 40; // Set color. Parameter is R G B, range 0-255.
    Colour[1] = 0;
    Colour[2] = 0;
    c = strip.Color(Colour[1], Colour[0], Colour[2]); //Green Red Blue  // Set color
    x = light[FX][FY];                                              //Display food
    strip.setPixelColor(x, c);
    strip.show();//Send data
    if ( !(score % 5)) {                      // Accerlerate snake speed according to the score. Every 5 foods eaten, accerlerate 100ms.  
      speedS = speedS - 50;
      if (speedS < 150)                         // The bottom limit is 200ms. If speed lower than 200ms, the speed stays 200ms.
        speedS = 150;
    }
  }
  // Judge whether food are eaten. If snake ate food, then plus scores and regenerate food randomly. 
}

Experiment Result

Step 4: Experiment Result