Completed Snake Program

Dependencies:   N5110 PinDetect PowerControl mbed

Fork of DocTest by Craig Evans

main.cpp

Committer:
MBirney
Date:
2015-04-27
Revision:
6:1de103a19681
Parent:
5:1bfc306466db
Child:
7:2942e97924f0

File content as of revision 6:1de103a19681:

#include "main.h"

// create enumerated type (0,1,2,3 etc. for direction)
enum DirectionName {
    UP,
    DOWN,
    LEFT,
    RIGHT,
    CENTRE,
    UNKNOWN
};

// create enumerated type (0,1,2 for difficulty)
enum Difficulty {
    EASY,
    MEDIUM,
    HARD,
};

Difficulty currentDifficulty=EASY;


// struct for Joystick
typedef struct JoyStick Joystick;
struct JoyStick {
    float x;    // current x value
    float x0;   // 'centred' x value
    float y;    // current y value
    float y0;   // 'centred' y value
    int button; // button state (assume pull-down used, so 1 = pressed, 0 = unpressed)
    DirectionName direction;  // current direction
};
// create struct variable
Joystick joystick;

DirectionName previousDirection =RIGHT;

// read default positions of the joystick to calibrate later readings
void calibrateJoystick()
{
    button.mode(PullDown);
    // must not move during calibration
    joystick.x0 = xPot;  // initial positions in the range 0.0 to 1.0 (0.5 if centred exactly)
    joystick.y0 = yPot;
}
void updateJoystick()
{
    // read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred)
    joystick.x = xPot - joystick.x0;
    joystick.y = yPot - joystick.y0;
    // read button state
    joystick.button = button;

    // calculate direction depending on x,y values
    // tolerance allows a little lee-way in case joystick not exactly in the stated direction
    if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = CENTRE;
    } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = DOWN;
    } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = UP;
    } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = RIGHT; // remember switched this with right
    } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = LEFT;
    } else {
        joystick.direction = UNKNOWN;
    }
}

//GAME FUNCTIONS

//For start MENU

void displaySplash()
{
    // these are default settings so not strictly needed
    lcd.inverseMode();      // normal colour mode
    lcd.setBrightness(0.5); // put LED backlight on 50%

    //Draw S
    lcd.drawRect(28,10,2,5,1);
    lcd.drawRect(15,10,15,2,1);
    lcd.drawRect(15,10,2,10,1);
    lcd.drawRect(15,20,15,2,1);
    lcd.drawRect(28,20,2,10,1);
    lcd.drawRect(15,28,15,2,1);
    lcd.drawRect(15,25,2,3,1);

    lcd.printString("NAKE ",34,3);
    lcd.printString("By M.Birney",10,5);
    lcd.drawRect(10,5,65,30,0);

    // need to refresh display after setting pixels

    lcd.refresh();
}



void easySelected() // display when easy is selected
{
    currentDifficulty=EASY;
    lcd.clear();
    lcd.printString("Please Select",2,0);
    lcd.printString("Difficulty:",2,1);
    lcd.printString("Easy",20,3);
    lcd.printString("Medium",20,4);
    lcd.printString("Hard",20,5);
    lcd.refresh();
    lcd.drawCircle(10,27,2,1);
    lcd.drawCircle(10,35,2,0);
    lcd.drawCircle(10,43,2,0);

    gameSpeed= 0.5;
}
void mediumSelected() // display when medium is selected
{
    currentDifficulty=MEDIUM;
    lcd.clear();
    lcd.printString("Please Select",2,0);
    lcd.printString("Difficulty:",2,1);
    lcd.printString("Easy",20,3);
    lcd.printString("Medium",20,4);
    lcd.printString("Hard",20,5);
    lcd.refresh();
    lcd.drawCircle(10,27,2,0);
    lcd.drawCircle(10,35,2,1);
    lcd.drawCircle(10,43,2,0);
    gameSpeed=0.5;
}

void hardSelected() // display when hard is selected
{
    currentDifficulty=HARD;
    lcd.clear();
    lcd.printString("Please Select",2,0);
    lcd.printString("Difficulty:",2,1);
    lcd.printString("Easy",20,3);
    lcd.printString("Medium",20,4);
    lcd.printString("Hard",20,5);
    lcd.refresh();
    lcd.drawCircle(10,27,2,0);
    lcd.drawCircle(10,35,2,0);
    lcd.drawCircle(10,43,2,1);
    gameSpeed=1.0/32;
}

void checkSelectedDifficulty()
{

    switch(currentDifficulty) {
        case EASY:

            switch (joystick.direction) {

                case UP:
                    hardSelected();
                    break;


                case DOWN:
                    mediumSelected();
                    break;
            }
            break;


        case MEDIUM:

            switch (joystick.direction) {

                case UP:
                    easySelected();
                    break;


                case DOWN:
                    hardSelected();
                    break;
            }



            break;
        case HARD:
            switch (joystick.direction) {

                case UP:
                    mediumSelected();
                    break;


                case DOWN:
                    easySelected();
                    break;
            }
            break;
    }
    wait(0.2);
}




//for gamePLAY



void startingSnake()
{
    snakeX[0]=20;
            snakeX[1]=22;
            snakeX[2]=24;
           snakeX[3]=26;
            snakeX[4]=28;

   for (int i=0; i<5; i++) {
       // lcd.setPixel(snakeX[i],snakeY[i]);
         lcd.drawRect(snakeX[i],snakeY[i],1,1,1);
    }
    
     
     wait(5);
}


void randomiseFood()
{

    srand(time(NULL));

    int randomX = rand() % (83-1)+1; // generate random number between 1 and 82  // spaces within boundar

    int randomY = rand() %(46-9)+9;// generate random number betwwen 9 and 46

    // int r = rand() % (21 - 10) + 10 // 10 -21 inclusive

    while(lcd.getPixel(randomX,randomY)==1) { // if that pixel is already filled

        int randomX = rand() % (83-1)+1; // generate random number between 1 and 82  // spaces within boundar

        int randomY = rand() %(46-9)+9;


    }
   // lcd.setPixel(randomX,randomY) ;// set the food
   lcd.drawRect(randomX,randomY,1,1,1);
    food[0]=randomX; // update food position
    food[1]=randomY;// update food position
    lcd.refresh();

}

void Boundary()
{


    for(int x = 0; x< 84; x++) {
        lcd.setPixel(x,8);
    }
    for(int x = 0; x< 84; x++) {
        lcd.setPixel(x,47);
    }
    for(int y = 8; y< 48; y++) {
        lcd.setPixel(0,y);
    }
    for(int y = 8; y< 48; y++) {
        lcd.setPixel(83,y);
    }

    lcd.refresh();

}





void updateSnakeArray()
{

    if (joystick.direction==LEFT && previousDirection==RIGHT) {
        joystick.direction=RIGHT;
    }

    if (joystick.direction==RIGHT && previousDirection==LEFT) {
        joystick.direction=LEFT;
    }

    if (joystick.direction==UP && previousDirection==DOWN) {
        joystick.direction=DOWN;
    }

    if (joystick.direction==DOWN && previousDirection==UP) {
        joystick.direction=UP;
    }

    if (joystick.direction==UNKNOWN || joystick.direction==CENTRE) {
        joystick.direction= previousDirection;
    }


   // lcd.clearPixel(snakeX[0],snakeY[0]);//delete tail
      lcd.drawRect(snakeX[0],snakeY[0],1,1,2);

    for (int i =0; i<snakeX.size(); i++) {  // shift elements
        snakeX[i]=snakeX[i + 1]; // apart from head
        snakeY[i]=snakeY[i+ 1];
    }

    switch(joystick.direction) {

        case UP:
            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2];
            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2]-2;
            break;

        case DOWN:
            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2];
            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2]+2;
            break;

        case LEFT:
            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]-2;
            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];
            break;

        case RIGHT:
            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]+2;
            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];
            break;

        case CENTRE:
            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]+2;
            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];
            break;
        case UNKNOWN:
            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]+2;
            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];
            break;

    }
}

void gameOver()
{
    startGame.detach();
    lcd.clearPixel(snakeX.back(),snakeY.back());
    wait(0.2);
    lcd.refresh();
    lcd.setPixel(snakeX.back(),snakeY.back());
    wait(0.3);
    lcd.refresh();
    lcd.clearPixel(snakeX.back(),snakeY.back());
    wait(0.2);
    lcd.refresh();
    lcd.setPixel(snakeX.back(),snakeY.back());
    wait(0.2);
    lcd.refresh();
    lcd.clear();
    lcd.inverseMode();

    
    lcd.printString("Your Score" ,12,0);
     lcd.printString("=" ,34,1);
     
     int updatedScore=score;
     int length = sprintf(buffer,"%2d",updatedScore);

        if (length <= 14)  // if string will fit on display
            lcd.printString(buffer,40,1);
            
             lcd.printString("Press Reset" ,2,3);
             lcd.printString("Button To" ,10,4);
             lcd.printString("Play Again" ,20,5);
           // 
            lcd.refresh();
    gamePlaying=0;
    
    

}

void checkForCollision()
{

    if (snakeX.back()<=0 || snakeX.back()>=82 || snakeY.back()<=8 ||snakeY.back()>=47) {
        
        gameOver();
    }
}



void checkForFood()
{

    if (snakeX.back()+1==food[0] && snakeY.back()==food[1]) {   // if  x and y of head match food


        switch(joystick.direction) {

            case RIGHT:
                snakeX.push_back(food[0]+2);
                snakeY.push_back(food[1]);
                break;
            case LEFT:

                snakeX.push_back(food[0]-2);
                snakeY.push_back(food[1]);
                break;


            case UP:
                snakeX.push_back(food[0]);
                snakeY.push_back(food[1]-2);
                break;

            case DOWN:
                snakeX.push_back(food[0]);
                snakeY.push_back(food[1]+2);
                break;
        }

        int updatedScore;
        // snakeX.insert (snakeX.begin() + 0, );
        //snakeY.insert (snakeY.begin() + 0, );

        updatedScore= score+5;
        score=updatedScore;
        int length = sprintf(buffer,"%2d",updatedScore);

        if (length <= 14)  // if string will fit on display
            lcd.printString(buffer,0,0);
        // lcd.refresh();

        randomiseFood();

    }


}

void startButtonPressed()
{
    gamePlaying=1;
   // myleds=15;
}




void updateGameISR()
{
    updateGameFlag=1;
}

void printVectorContent()
{

    for( int i=0; i<snakeX.size(); i++)
        serial.printf( "%d \n \r"  ,snakeX[i]);

}



void pauseButtonPressed()
{

    if (gamePaused==0) {

        startGame.detach();

        gamePaused=1;
    }

    else {


        startGame.attach(&updateGameISR,gameSpeed);

        gamePaused=0;
    }



}

void checkForCollisionWithSelf(int i)
{

        if(snakeX.back()==snakeX[i] && snakeY.back()==snakeY[i]) {


            gameOver();

        
    }


}
void startUpMenu()
{

    // first need to initialise display
    
    displaySplash();
    wait(4);
    easySelected();
    joystick.direction=UNKNOWN;
    calibrateJoystick();  // get centred values of joystick
    pollJoystick.attach(&updateJoystick,1.0/5.0);
    startGame.attach(&updateGameISR,gameSpeed); // read joystick 10 times per second
    


}

void resetButtonPressed()
{
  // myleds=0;
   easySelected();
   pollJoystick.attach(&updateJoystick,1.0/5.0);
}


int main()
{
    lcd.init();
    startUpMenu();
    resetButton.mode(PullDown);
    startButton.mode(PullDown);
    button.mode(PullDown);
    startButton.rise(&startButtonPressed);
    resetButton.rise(&resetButtonPressed);
    button.rise(&pauseButtonPressed);
serial.printf("starting");
    while(1) {
        if (gamePlaying==0) {
            checkSelectedDifficulty();
            serial.printf("check difficulty loop");
        }

        else if (gamePlaying==1) {
            lcd.clear();
            lcd.normalMode();      // normal colour mode
            Boundary();
            
            pollJoystick.detach();
            startGame.attach(&updateGameISR,gameSpeed);
            startingSnake();
            randomiseFood();
            if (length <= 14)  // if string will fit on display
                lcd.printString(buffer,0,0);
            // lcd.drawRect(0,0,83,7,0);
            lcd.refresh();
            serial.printf("gameplaying=1 game init");

            //init game start time back food
            while (1) {
                serial.printf("enter game loop");
                if(updateGameFlag==1) {
                    //updateJoystick();
                    updateGameFlag=0;
                    updateJoystick();
                    // lcd.clearPixel(snakeX[0],snakeY[0]);
                    // updateSnakeDirection();
                    updateSnakeArray();
                    for (int i=0; i<snakeX.size(); i++) {
                        lcd.drawRect(snakeX[i],snakeY[i],1,1,1);
                       // lcd.setPixel(snakeX[i],snakeY[i]);
                        

                    }
                    lcd.refresh();
                    previousDirection=joystick.direction;
                    
                    checkForFood();
                    checkForCollision();
                    
                    for (int i=0; i<snakeX.size()-1; i++) {
                        checkForCollisionWithSelf(i);
                    }


                    //serial.printf("%d",snakeX.size());
                    // printVectorContent();

                }

            }

        }
    }



}