Arduino Snake Game

by rayankiwan63 in Circuits > Arduino

458 Views, 0 Favorites, 0 Comments

Arduino Snake Game

Arduino Snake game using max7219 and joystick

Here's the first of our mini projects that you can build from (max7219,buzzer,arduinouno & joystick). It's a take on the old 'Snake' game that you might have seen on old Nokia phones or even earlier on Atari. There's nothing difficult about this project but we'd recommend that you've built a few of the designs from the book before attempting it.

Components Needed

Arduino UNO

buzzer

joystick

breadboard

wires

MAX7219

USB CABLE

Connections

snake game.png

D2- Joystick(SW)

D3-BUZZER(S)

D4-MATRIX(DIN)

D5-MATRIX(CS)

D6-MATRIX(CLK)

A0-joystick(VRx)

A1-joystick(VRy)

5V-VCC +5V

GND-GND-GND

Code

#define MAX7219DIN 4
#define MAX7219CS 5
#define MAX7219CLK 6
#define JOYX A1
#define JOYY A0
#define BUTTON 2
#define SPEAKER 3

byte p[8]={0,0,0,0,0,0,0,0};      //bitmap to display
byte nums[10][3]={                   //bitmap of numbers
  {28,34,28},
  {36,62,32},
  {50,42,36},
  {42,42,20},
  {28,18,62},
  {46,42,18},
  {28,42,18},
  {50,10,6},
  {54,42,54},
  {4,42,28}
};

byte marquee1[]={0,0,0,0,0,0,0,0,0,127,9,9,6,120,4,4,56,84,84,24,0,72,84,36,0,72,84,36,0,0, 0,  62, 68, 68, 56, 68, 68, 56, 0,  0,  72, 84, 36, 0,  62, 68, 68, 0,  116,  84, 120,  0,  120,  4,  4,  0,  62, 68, 68, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0};
byte marquee2[]={0,0,0,0,0,0,70,73,49,0,56,68,68,0,56,68,68,56,0,120,4,4,0,60,84,92,0,40,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};

char sx[64];                        
char sy[64];                      //snake positions, zeroth is front of snake, first slen are valid
char dir=0;                       //1=up, 2=right, 3=down, 4=left
char slen=0;
int score=0;
char gamestate=0;                 //0=idle, 1=play, 2 =game over
unsigned long tc=80; //menu             //time between game cycles (~speed/difficulty)
unsigned long ts=250;//snake
void setup() {
  MAX7219init();
  MAX7219brightness(1);
  pinMode(BUTTON,INPUT_PULLUP);
  pinMode(SPEAKER,OUTPUT);
  tone(SPEAKER, 100,500);
}

void loop() {
  switch(gamestate){
    case 0: doidle(); break;
    case 1: dogame(); break;
    case 2: dogameover(); break;
    case 3: dogameend(); break;
  }
  
  delay(gamestate ==1 ? ts : tc);
}

void dogameend(){
  gamestate=2;
  tone(SPEAKER,100,500);
}

void dogameover(){
  //tc=80;
  static int n=0;
  marquee2[30]=nums[(score/100)%10][0];
  marquee2[31]=nums[(score/100)%10][1];
  marquee2[32]=nums[(score/100)%10][2];
  marquee2[34]=nums[(score/10)%10][0];
  marquee2[35]=nums[(score/10)%10][1];
  marquee2[36]=nums[(score/10)%10][2];
  marquee2[38]=nums[(score/1)%10][0];
  marquee2[39]=nums[(score/1)%10][1];
  marquee2[40]=nums[(score/1)%10][2];
  MAX7219sendbm(marquee2+n);
  n++;
  if(n>sizeof(marquee2)-8){n=0;}
  if(digitalRead(BUTTON)==LOW){   //change modes,
    gamestate=0;
    MAX7219sendbm(marquee1);        //blank screen
    while(digitalRead(BUTTON)==LOW){}// wait til released
  }

}

void dogame(){
  int i;                //loop variable
  char newx,newy;
  int a;
  if(slen==0){        //game is reset > initialise
    score=0;
    dir=1;
    sx[0]=3;
    sy[0]=3;
    sx[1]=3;
    sy[1]=4;
    sx[2]=3;
    sy[2]=5;
    slen=3;    
  }
  newx=sx[0];
  newy=sy[0];     //new snake head position
  a=analogRead(JOYX);
  if(a<256){dir=2;}
  if(a>768){dir=4;}
  a=analogRead(JOYY);
  if(a<256){dir=1;}
  if(a>768){dir=3;}
  switch(dir){
    case 1: newy=newy-1;break;
    case 2: newx=newx+1;break;
    case 3: newy=newy+1;break;
    case 4: newx=newx-1;break;
  }
  if((newx<0)||(newx>7)||(newy<0)||(newy>7)){     //outside walls > game over
    gamestate=3;
  }
  for(i=0;i<slen;i++){
    if((newx==sx[i])&&(newy==sy[i])){gamestate=3;}  //collided with self > game over
  }
  for(i=63;i>0;i--){                             //move old positions
    sx[i]=sx[i-1];
    sy[i]=sy[i-1];
  }
  sx[0]=newx;
  sy[0]=newy;
  for(i=0;i<8;i++){p[i]=0;}                   //clear display
  for(i=0;i<slen;i++){                        //draw snake
    p[sx[i]]=p[sx[i]]|(1<<(sy[i]));
  }
  
  MAX7219sendbm(p);
  score++;                //increase score
  slen=(score+50)/25;    //increase length
  tone(SPEAKER,440,10);  //chirp for game rhythm
}

void doidle(){
  //tc=80;
  static int n=0;
  MAX7219sendbm(marquee1+n);
  n++;
  if(n>sizeof(marquee1)-8){n=0;}
  if(digitalRead(BUTTON)==LOW){   //change modes,
    gamestate=1;
    MAX7219sendbm(marquee1);        //blank screen
    //tc=200;                         //slow down
    slen=0;                         //reset game
    while(digitalRead(BUTTON)==LOW){}// wait til released
  }
}

void MAX7219shown(byte n){
  byte s[8];
  s[0]=nums[(n/10)%10][0];
  s[1]=nums[(n/10)%10][1];
  s[2]=nums[(n/10)%10][2];
  s[3]=0;
  s[4]=nums[n%10][0];
  s[5]=nums[n%10][1];
  s[6]=nums[n%10][2];
  s[7]=0;
  MAX7219sendbm(s);
}

void MAX7219sendbm(byte p[]){
  for(int i=0;i<8;i++){
    MAX7219senddata(i+1,p[i]);
  }
}

void MAX7219brightness(byte b){  //0-15 is range high nybble is ignored
  MAX7219senddata(10,b);        //intensity  
}

void MAX7219init(){
  pinMode(MAX7219DIN,OUTPUT);
  pinMode(MAX7219CS,OUTPUT);
  pinMode(MAX7219CLK,OUTPUT);
  digitalWrite(MAX7219CS,HIGH);   //CS off
  digitalWrite(MAX7219CLK,LOW);   //CLK low
  MAX7219senddata(15,0);        //test mode off
  MAX7219senddata(12,1);        //display on
  MAX7219senddata(9,0);         //no decode
  MAX7219senddata(11,7);        //scan all
  for(int i=1;i<9;i++){
    MAX7219senddata(i,0);       //blank all
  }
}

void MAX7219senddata(byte reg, byte data){
  digitalWrite(MAX7219CS,LOW);   //CS on
  for(int i=128;i>0;i=i>>1){
    if(i&reg){
      digitalWrite(MAX7219DIN,HIGH);
    }else{
      digitalWrite(MAX7219DIN,LOW);      
    }
  digitalWrite(MAX7219CLK,HIGH);   
  digitalWrite(MAX7219CLK,LOW);   //CLK toggle    
  }
  for(int i=128;i>0;i=i>>1){
    if(i&data){
      digitalWrite(MAX7219DIN,HIGH);
    }else{
      digitalWrite(MAX7219DIN,LOW);      
    }
  digitalWrite(MAX7219CLK,HIGH);   
  digitalWrite(MAX7219CLK,LOW);   //CLK toggle    
  }
  digitalWrite(MAX7219CS,HIGH);   //CS off
}