C++ code for snake game

Dependencies:   4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player

Fork of MPR121_Demo by jim hamblen

main.cpp

Committer:
ykuris3
Date:
2017-03-13
Revision:
2:97ec9d79e015
Parent:
1:2eaf4c475fde

File content as of revision 2:97ec9d79e015:

#include "mbed.h"
#include "mpr121.h"
#include "uLCD_4DGL.h"
#include "rtos.h"
#include "SDFileSystem.h"
#include "wave_player.h"
#include <ctime>
// code developed by Lotanna Okoli and Yusuf Ziya Kuris
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
// Create the interrupt receiver object on pin 26
InterruptIn interrupt(p26);
// Setup the i2c bus on pins 9 and 10
I2C i2c(p28, p27);
uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin;
// Setup the Mpr121:
// constructor(i2c object, i2c address of the mpr121)
Mpr121 mpr121(&i2c, Mpr121::ADD_VSS);
volatile int  bnum = 0;
SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card
AnalogOut DACout(p18);
wave_player waver(&DACout);
Timer timer;

Mutex stdio_mutex;

Thread t1;
Thread t2;
Thread t3;

struct node {
    int x;
    int y;
    node *next;
};

void drawNodes(node *nodes, int color);
node* getFoodNode(node *snake);
bool nodeCollision(node *nodes, node *snake, int start);

void startscreen() {
    FILE *wave_file;
    stdio_mutex.lock();
    wave_file=fopen("/sd/startscreen.wav","r");
    stdio_mutex.unlock();
    waver.play(wave_file);
    fclose(wave_file);
}

void gameover() {
    FILE *wave_file;
    stdio_mutex.lock();
    wave_file=fopen("/sd/gameover.wav","r");
    stdio_mutex.unlock();
    waver.play(wave_file);
    fclose(wave_file);
}

void snakedie() {
    FILE *wave_file;
    stdio_mutex.lock();
    wave_file=fopen("/sd/snakedie.wav","r");
    stdio_mutex.unlock();
    waver.play(wave_file);
    fclose(wave_file);
}

void eategg() {
    FILE *wave_file;
    stdio_mutex.lock();
    wave_file=fopen("/sd/eategg2.wav","r");
    stdio_mutex.unlock();
    waver.play(wave_file);
    fclose(wave_file);
}

void stagebegin() {
    FILE *wave_file;
    stdio_mutex.lock();
    wave_file=fopen("/sd/stagebegin.wav","r");
    stdio_mutex.unlock();
    waver.play(wave_file);
    fclose(wave_file);
}
 
// Key hit/release interrupt routine
void fallInterrupt() {
    int key_code = 0;
    int i = 0;
    int value = mpr121.read(0x00);
    value += mpr121.read(0x01)<<8;
    // LED demo mod
    i = 0;
    // puts key number out to LEDs for demo
    for (i = 0; i < 12; i++) {
        if (((value>>i)&0x01) == 1) {
            key_code=i;
        }
        if (key_code != 0) {
            bnum = key_code;
        }
  
        led4=key_code & 0x01;
        led3=(key_code>>1) & 0x01;
        led2=(key_code>>2) & 0x01;
        led1=(key_code>>3) & 0x01;
    }
}
 
int main() {
    timer.start();
    interrupt.fall(&fallInterrupt);
    interrupt.mode(PullUp);
    uLCD.baudrate(3000000);
    int state = 0;
    int score;
    int deltax;
    int deltay;
    float waitTime;
    node *snake;
    node *start;
    node *end;
    node *food;
    bool foodEaten;
    bool pause;   
    while (1) {    
        srand((unsigned)timer.read_us());    
        if (state == 0) {
            t1.start(startscreen);
            uLCD.cls();
            uLCD.media_init();
            uLCD.set_sector_address(0x0000, 0x0104);
            uLCD.display_video(0,0);
            bnum = 0;
            uLCD.cls();
            uLCD.media_init();
            uLCD.set_sector_address(0x0000, 0x0000);
            uLCD.display_image(0,0);
            while (state == 0) {
                if (bnum == 6) {
                    state = 1;
                    break;
                }
                uLCD.filled_rectangle(0, 100, 127, 127, BLACK);
                wait(1);
                if (bnum == 6) {
                    state = 1;
                    break;
                }
                uLCD.locate(0, 14);
                uLCD.printf("    Press Key 6");
                wait(1);
            }
        }
        if (state == 1) {
            t1.start(stagebegin);
            bnum = 0;
            uLCD.cls(); 
            uLCD.filled_rectangle(0, 0, 127, 5, GREEN);
            uLCD.filled_rectangle(0, 122, 127, 127, GREEN);
            uLCD.filled_rectangle(0, 0, 5, 127, GREEN);
            uLCD.filled_rectangle(122, 0, 127, 127, GREEN);
            uLCD.text_width(2);
            uLCD.text_height(2);
            uLCD.text_string("LEVEL 1", 1, 3, FONT_12X16, GREEN);               
            wait(4);
            uLCD.cls();
            score = 0;
            waitTime = 0.4;
            uLCD.printf("Score: %d", score);
            uLCD.filled_rectangle(0, 10, 127, 15, 0xEF4400);
            uLCD.filled_rectangle(0, 122, 127, 127, 0xEF4400);
            uLCD.filled_rectangle(0, 10, 5, 127, 0xEF4400);
            uLCD.filled_rectangle(122, 10, 127, 127, 0xEF4400);
            snake = new node;
            start = snake;
            for (int i = 4; i >= 0; i--) {
                snake->x = 60 + (4*i);
                snake->y = 60;
                snake->next = new node;
                if (i != 0) {
                    snake = snake->next;
                }
            }
            snake->next = 0;
            end = snake;
            drawNodes(start, 0x00FF00);
            food = getFoodNode(start);
            drawNodes(food, 0xFFCC00);
            deltax = -1;
            deltay = 0;
            state = 1;
            foodEaten = false;
            pause = false;
            while (state == 1) {
                if (bnum == 6) {
                    pause = !pause;
                    bnum = 0;
                }
                if (!pause) {
                    if (bnum == 2 && deltax != 1 && deltay != 0) {
                        deltax = -1;
                        deltay = 0;
                    } else if (bnum == 10 && deltax != -1 && deltay != 0) {
                        deltax = 1;
                        deltay = 0;
                    } else if (bnum == 5 && deltax != 0 && deltay != -1) {
                        deltax = 0;
                        deltay = 1;
                    } else if (bnum == 7 && deltax != 0 && deltay != 1) {
                        deltax = 0;
                        deltay = -1;
                    }
                    snake = new node;
                    snake->x = end->x + (deltax * 4);
                    snake->y = end->y + (deltay * 4);
                    snake->next = 0;
                    if (!(snake->x > 5 && snake->x < 122 && snake->y > 15 && snake->y < 122) || nodeCollision(snake, start, 0)) {
                        t1.start(snakedie);
                        bnum = 0;
                        state = 2;
                        break;
                    } else if (nodeCollision(food, snake, 0)) {
                        t1.start(eategg);
                        if (waitTime > 0) {
                            waitTime -= 0.01;
                        }
                        foodEaten = true;
                        uLCD.filled_rectangle(food->x, food->y, food->x + 3, food->y + 3, 0x000000);
                        end->next = snake;
                        end = snake;
                        drawNodes(end, 0x00FF00);
                        food = getFoodNode(start);
                        drawNodes(food, 0xFFCC00);
                        score += 10;
                        uLCD.filled_rectangle(0, 0, 127, 9, 0x000000);
                        uLCD.locate(0, 0);
                        uLCD.printf("Score: %d", score); 
                                       
                    }
                    if (!foodEaten) {
                        end->next = snake;
                        end = snake;
                        drawNodes(end, 0x00FF00);
                        uLCD.filled_rectangle(start->x, start->y, start->x + 3, start->y + 3, 0x000000);
                        start = start->next;
                    }
                    foodEaten = false;
                    wait(waitTime);
                }
            }
        }
        if (state == 2) {
            uLCD.cls(); 
            uLCD.filled_rectangle(0, 0, 127, 5, GREEN);
            uLCD.filled_rectangle(0, 122, 127, 127, GREEN);
            uLCD.filled_rectangle(0, 0, 5, 127, GREEN);
            uLCD.filled_rectangle(122, 0, 127, 127, GREEN);
            uLCD.text_width(2);
            uLCD.text_height(2);
            uLCD.text_string("SCORE", 2, 2, FONT_12X16, GREEN);
            char n_str[10];
            sprintf(n_str, "%d", score);            
            int loc = 3;
            if (score == 0) {
                loc = 4;                
            }
            uLCD.text_string(n_str, loc, 4, FONT_12X16, GREEN);                 
            wait(6);
            t1.start(gameover);
            uLCD.cls();
            uLCD.media_init();
            uLCD.set_sector_address(0x0000, 0x00C3);
            uLCD.display_image(0,0);
            while (state == 2) {               
                if (bnum == 6) {
                    state = 1;
                    break;
                }
                uLCD.filled_rectangle(0, 100, 127, 127, BLACK);
                wait(1);
                if (bnum == 6) {
                    state = 1;
                    break;
                }
                uLCD.locate(0, 14);
                uLCD.printf("    Press Key 6");
                wait(1);
            }
        }
      /*
      mySpeaker.PlayNote(200.0, 0.25, 0.1);
      mySpeaker.PlayNote(100.0, 0.80, 0.5);
      mySpeaker.PlayNote(300.0, 0.95, 0.6);
      mySpeaker.PlayNote(400.0, 0.25, 0.9);
      switch (bnum) {
        case 6: //number button 1
          uLCD.cls();
          uLCD.printf("The number is %d", bnum);
          uLCD.filled_rectangle(50, 50, 100, 90, 0xFF0000);
          t1.start(sound3);
          break;        
        case 1: //number button 1
          uLCD.cls();
          uLCD.printf("The number is %d", bnum);
          uLCD.filled_rectangle(50, 50, 100, 90, 0x0000FF);
          t1.start(sound1);
          break;
        case 2: //number button 1 //snake color
          uLCD.cls();
          uLCD.printf("The number is %d", bnum);
          uLCD.filled_rectangle(50, 50, 100, 90, 0x00FF00);
          t1.start(sound2);
          break;
        case 3: //number button 1 //food color
          uLCD.cls();
          uLCD.printf("The number is %d", bnum);
          uLCD.filled_rectangle(50, 50, 100, 90, 0xFFCC00);
          break;
        case 4: //number button 1
          uLCD.cls();
          uLCD.printf("The number is %d", bnum);
          uLCD.filled_rectangle(50, 50, 100, 90, 0x777777);
          break;  
        case 5: //number button 1
          uLCD.cls();
          uLCD.printf("The number is %d", bnum);
          uLCD.filled_rectangle(50, 50, 100, 90, 0xEF4400);
          break;
        default:
          break;        
      }
      */    
  }
}

void drawNodes(node *nodes, int color) {
    while (nodes != 0) {
        uLCD.filled_rectangle(nodes->x, nodes->y, nodes->x + 3, nodes->y + 3, color);
        //uLCD.rectangle(nodes->x - 1, nodes->y - 1, nodes->x + 4, nodes->y + 4, BLACK);
        nodes = nodes->next;
    }
}

node* getFoodNode(node *snake) {
    bool leave = false;
    bool check = false;
    node *food = new node;
    food->next = 0;
    while (!leave) {
        food->x = rand()%111 + 6;
        food->y = rand()%101 + 16;
        check = false;
        check = nodeCollision(food, snake, -3);
        if (!check) {
            leave = true;
        }
    }
    return food;
}

bool nodeCollision(node *nodes, node *snake, int start) {
    while (snake != 0) {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                for (int a = start; a < 4; a++) {
                    for (int b = start; b < 4; b++) {
                        if (((snake->x + i) == (nodes->x + a)) && ((snake->y + j) == (nodes->y + b))) {
                            return true;
                        }
                    }
                }
            }
        }    
        snake = snake->next;
    }
    return false;
}