renhao dai / Mbed 2 deprecated Joystick_snake_game

Dependencies:   N5110 mbed

main.cpp

Committer:
el14rd
Date:
2015-05-10
Revision:
10:67e13dfaa10d
Parent:
9:c8ea9b4af873

File content as of revision 10:67e13dfaa10d:

/**
@file main.cpp
@brief Program implementation
@brief cpp file containing total program include main function, functions prototypes, defines and global variables.
@brief hand-held joystick snake gmae 
@author Renhao Dai
@date   MAY 2015
*/
#include "mbed.h"
#include "N5110.h"
#define DIRECTION_TOLERANCE 0.05

/**  
@namespace lcd 
@brief GPIO output for LCD 
*/                                     //pins in
N5110 lcd(p7,p8,p9,p10,p11,p13,p26);
PwmOut blacklight(p26);

/**  
@namespace joystick
@brief GPIO input for joystick
*/    
InterruptIn button(p17);
AnalogIn xPot(p15);                   // connections for joystick
AnalogIn yPot(p16);

/**  
@namespace buttonA
@brief GPIO input for button 
*/    
DigitalIn buttonA(p19);

/**  
@namespace pot
@brief GPIO input for potentiometer 
*/    
AnalogIn pot(p20);

/**  
@namespace buzzer
@brief GPIO output for buzzer 
*/    
PwmOut buzzer(p21);

/**  
@namespace led
@brief GPIO output for LED 
*/    
PwmOut led1(p24);
PwmOut led2(p23);
BusOut leds(LED4,LED3,LED2,LED1);

float ain;  /*!< variable in potentiometer */
int i;      /*!< variable in coordinate of snake */
int j;
int X;      /*!< variable in coordinate of nut */
int Y;
char buffer[14];  /*!< array for character */

int snakeX[100];  /*!< array for x axis coordinate */
int snakeY[100];  /*!< array for y axis coordinate */

// timer to regularly read the joystick
Ticker pollJoystick;
// Serial for debug
Serial serial(USBTX,USBRX);

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

/// 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;

int pause = 0; /*!< pause flag set in ISR */
int buttonFlag = 0; /*!< button flag set in ISR */                                                    
int printFlag = 0;  /*!< print flag set in ISR */
int nutFlag =1; /*!< nut flag set in ISR */
int lifeFlag =0; /*!< lifet flag set in ISR */
float frequency[]= {659,554,659,554,550,494,554,587,494,659,554,440}; /*!< array for the tone frequency */
float beat[]= {1,1,1,1,1,0.5,0.5,1,1,1,1,2}; /*!< array for time span */

/// struct for nut
typedef struct Nut Nut;
struct Nut {
    int X; /// coordinate in x axis
    int Y; /// coordinate in y axis
};
/// create struct variable
Nut nut;

/// struct for snake
typedef struct Snake Snake;
struct Snake {
    int snakeX[100]; /// array in x axis
    int snakeY[100]; /// array in y axis
    int node; /// number of node
    DirectionName direction;  /// direction virable
};
/// create struct variable
Snake snake;

/// definition for snake direction
DirectionName snakeDirection;


void initNut()
{   ///set the coordinate of nut randomly
    nut.X=rand()%84;
    nut.Y=rand()%48;
}

void drawNut()
{   ///draw nut
    if(nutFlag==1) {
        lcd.drawCircle(nut.X,nut.Y,1,1);
    }
}

void moveSnake()
{

    if(joystick.direction == CENTRE) {
    ///does not make any changes
        joystick.direction = CENTRE;
    } else if(joystick.direction == UNKNOWN) {
    //does not make any changes
        joystick.direction = UNKNOWN;

    } else if(joystick.direction != UNKNOWN&&joystick.direction != CENTRE) {

        if((joystick.direction == DOWN)&&(snake.direction!=LEFT)) {
            ///sent rightward direction to snake.direction
            snake.direction= RIGHT;

        } else if((joystick.direction == UP)&&(snake.direction!=RIGHT)) {
            ///sent leftward direction to snake.direction
            snake.direction=LEFT;

        } else if((joystick.direction == LEFT)&&(snake.direction!=DOWN)) {
            ///sent upward direction to snake.direction
            snake.direction=UP;
           
        } else if((joystick.direction == RIGHT)&&(snake.direction!=UP)) {
            ///sent downward direction to snake.direction
            snake.direction=DOWN;

        }

    }

}

void initSnake()
{
    ///define initial coordinate of snake
    snake.snakeX[0] = 16; ///coordinate of head
    snake.snakeY[0] = 10;
    snake.snakeX[1] = 14;
    snake.snakeY[1] = 10;
    snake.snakeX[2] = 12;
    snake.snakeY[2] = 10;
    snake.snakeX[3] = 10;
    snake.snakeY[3] = 10;
    snake.node = 5; ///node of snake
    snake.direction = RIGHT;///initialize the direction of snake

}


void drawSnake()
{
    ///each node is a circle with 1 pixel radius
    for(i=0; i<snake.node-1; i++) {
        lcd.drawCircle(snake.snakeX[i],snake.snakeY[i],1,1);
    }

}

void startGmae()
{
    ///occasion that snake eats nut
    if((snake.snakeX[0]==nut.X)&&(snake.snakeY[0]==nut.Y)) {                                
        snake.node+=1;
        nutFlag=0; /// new nut appear
        buzzer.period(1/frequency[1]); /// set PWM period
        buzzer=0.1; /// set duty cycle
    }

    if((snake.snakeX[0]!=nut.X)||(snake.snakeY[0]!=nut.Y)) {
        ///if snake gets nut, play a beep
        buzzer=0;
    }

    if(nutFlag==0) { 
    ///reset nut randomly
        nut.X = rand()%83;
        nut.Y = rand()%47;
        nutFlag = 1;
    }


    for(i=3; i<snake.node; i++) { 
    ///if snake collide itself snake die
        if(snake.snakeX[i]==snake.snakeX[0] && snake.snakeY[i]==snake.snakeY[0]) {
            lifeFlag=1;
        }
    }


    for(i=snake.node-1; i>0; i--) { 
        ///move snake
        if(snake.snakeX[0]>1||snake.snakeX[0]<83||snake.snakeY[0]>1||snake.snakeY[0]<47) {
            snake.snakeX[i]=snake.snakeX[i-1];
            snake.snakeY[i]=snake.snakeY[i-1];
        } else {
            snake.snakeX[i]=snake.snakeX[i];
            snake.snakeY[i]=snake.snakeY[i];
        }
    }


    if(snake.snakeX[0]<1||snake.snakeX[0]>83||snake.snakeY[0]<1||snake.snakeY[0]>47) {
        /// snake collide the corrider snake die
        lifeFlag=1; 
    }

}

void printScore()
{   ///print characters on map at coordiante 0,0
    lcd.printString("Your Score is",0,0);
    ///print score
    int score=snake.node-4;
    int length = sprintf(buffer," SCORE=%2d ",score);
    lcd.printString(buffer,0,2 );
    ///print characters on map at coordiante 0,4
    lcd.printString("Press to start",0,4);
}

void buttonPressed()
{   ///button Flag set
    buttonFlag =1;
}

void snakeModel()
{   ///set moving snake model
    for(int i=0; i<25; i+=5) {
        lcd.clear();
        lcd.printString("Press to start",1,1);

        lcd.drawRect(44-i,21,1,1,1);
        lcd.drawRect(46-i,21,1,1,1);
        lcd.drawRect(48-i,21,1,1,1);

        lcd.drawRect(42-i,23,1,1,1);
        lcd.drawRect(44-i,23,1,1,1);
        lcd.drawRect(46-i,23,1,1,1);
        lcd.drawRect(48-i,23,1,1,1);

        lcd.drawRect(40-i,25,1,1,1);
        lcd.drawRect(42-i,25,1,1,1);
        lcd.drawRect(44-i,25,1,1,1);
        lcd.drawRect(46-i,25,1,1,1);
        lcd.drawRect(48-i,25,1,1,1);
        lcd.drawRect(50-i,25,1,1,1);

        lcd.drawRect(40-i,27,1,1,1);
        lcd.drawRect(42-i,27,1,1,1);
        lcd.drawRect(44-i,27,1,1,1);
        lcd.drawRect(46-i,27,1,1,1);
        lcd.drawRect(48-i,27,1,1,1);
        lcd.drawRect(50-i,27,1,1,1); ///head

        lcd.drawRect(38-i,29,1,1,0); ///tougue
        lcd.drawRect(40-i,31,1,1,0);

        lcd.drawRect(46-i,29,1,1,1);
        lcd.drawRect(48-i,29,1,1,1);
        lcd.drawRect(50-i,29,1,1,1);

        lcd.drawRect(46-i,31,1,1,1);
        lcd.drawRect(48-i,31,1,1,1);
        lcd.drawRect(50-i,31,1,1,1);

        lcd.drawRect(44-i,33,1,1,1);
        lcd.drawRect(46-i,33,1,1,1);
        lcd.drawRect(48-i,33,1,1,1);

        lcd.drawRect(44-i,35,1,1,1);
        lcd.drawRect(46-i,35,1,1,1);
        lcd.drawRect(48-i,35,1,1,1);

        lcd.drawRect(42-i,37,1,1,1);
        lcd.drawRect(44-i,37,1,1,1);
        lcd.drawRect(46-i,37,1,1,1);

        lcd.drawRect(42-i,39,1,1,1);
        lcd.drawRect(44-i,39,1,1,1);
        lcd.drawRect(46-i,39,1,1,1);

        lcd.drawRect(44-i,41,1,1,1);
        lcd.drawRect(46-i,41,1,1,1);
        lcd.drawRect(48-i,41,1,1,1);
        lcd.drawRect(50-i,41,1,1,1);///neck

        lcd.drawRect(80-i,41,1,1,1);///tail
        lcd.drawRect(82-i,41,1,1,1);
        lcd.drawRect(84-i,41,1,1,1);

        lcd.drawRect(82-i,39,1,1,1);
        lcd.drawRect(84-i,39,1,1,1);

        lcd.drawRect(82-i,37,1,1,1);

        lcd.drawRect(80-i,35,1,1,1);///tail

        lcd.drawRect(46-i,43,1,1,1);
        lcd.drawRect(48-i,43,1,1,1);
        lcd.drawRect(50-i,43,1,1,1);
        lcd.drawRect(52-i,43,1,1,1);
        lcd.drawRect(54-i,43,1,1,1);
        lcd.drawRect(56-i,43,1,1,1);
        lcd.drawRect(58-i,43,1,1,1);
        lcd.drawRect(60-i,43,1,1,1);
        lcd.drawRect(62-i,43,1,1,1);
        lcd.drawRect(64-i,43,1,1,1);
        lcd.drawRect(66-i,43,1,1,1);
        lcd.drawRect(68-i,43,1,1,1);
        lcd.drawRect(70-i,43,1,1,1);
        lcd.drawRect(72-i,43,1,1,1);
        lcd.drawRect(74-i,43,1,1,1);
        lcd.drawRect(76-i,43,1,1,1);
        lcd.drawRect(78-i,43,1,1,1);
        lcd.drawRect(80-i,43,1,1,1);
        lcd.drawRect(82-i,43,1,1,1);

        lcd.drawRect(48-i,45,1,1,1);
        lcd.drawRect(50-i,45,1,1,1);
        lcd.drawRect(52-i,45,1,1,1);
        lcd.drawRect(54-i,45,1,1,1);
        lcd.drawRect(56-i,45,1,1,1);
        lcd.drawRect(58-i,45,1,1,1);
        lcd.drawRect(60-i,45,1,1,1);
        lcd.drawRect(62-i,45,1,1,1);
        lcd.drawRect(64-i,45,1,1,1);
        lcd.drawRect(66-i,45,1,1,1);
        lcd.drawRect(68-i,45,1,1,1);
        lcd.drawRect(70-i,45,1,1,1);
        lcd.drawRect(72-i,45,1,1,1);
        lcd.drawRect(74-i,45,1,1,1);
        lcd.drawRect(76-i,45,1,1,1);
        lcd.drawRect(78-i,45,1,1,1);
        lcd.drawRect(80-i,45,1,1,1);
        wait(0.5);
        //lcd.refresh();
    }

}

/// 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 = UP;
    } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = DOWN;
    } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = RIGHT;
    } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = LEFT;
    } else {
        joystick.direction = UNKNOWN;
    }
    /// set flag for printing
    printFlag = 1;
}

void updateSnake()
{
    /// get direction of joystick and update snake
    if (snake.direction == LEFT) {
        snake.snakeX[0]-=1;
        ///will stop at the top edge
        if(snake.snakeX[0]<1) {
            snake.snakeX[0]=1;
        }
    }
    if (snake.direction == RIGHT) {
        snake.snakeX[0]+=1;
        ///will stop at the bottom edge
        if(snake.snakeX[0]>83) {
            snake.snakeX[0]=83;
        }
    }
    if (snake.direction == UP) {
        snake.snakeY[0]-=1;
        ///will stop at the left edge
        if(snake.snakeY[0]>47) {
            snake.snakeY[0]=47;
        }
    }
    if (snake.direction == DOWN) {
        snake.snakeY[0]+=1;
        ///will stop at the right edge
        if(snake.snakeY[0]<1) {
            snake.snakeY[0]=1;
        }
    }
    if(snake.direction == CENTRE) {
        snake.snakeX[0]+=1;
    }
    if(snake.direction == UNKNOWN) {
        snake.snakeX[0]+=1;
    }
}


///main code
int main()
{
    /// function prototypes
    lcd.init();             /// initialize the lcd
    lcd.setBrightness(0.5); /// put LED backlight on 50%
    calibrateJoystick();  /// get centred values of joystick
    pollJoystick.attach(&updateJoystick,1.0/10.0);  /// read joystick 10 times per second
    lcd.refresh(); /// refresh the screen
    initNut();   /// create a nut
    initSnake(); /// create a snake 
    button.rise(&buttonPressed); ///event generated on rising edge
    buttonA.mode(PullDown); ///
    
///infinite while loop to execute the game
    while(1) {
        
        if(buttonFlag==0) { ///joystick button unpressed
            lcd.printString("Press to start",1,1);
            snakeModel();
            led1=1; ///red LED illuminate
        } else {
            
            led1=0; ///red LED off
            led2=1; ///green LED on
            leds = 0; /// all status LED off

            if(buttonA) { ///if button pressed, toggle pause
                wait_ms(50);
                pause = !pause; ///pause the game
                leds = 15;
                led2=0; /// green LED off        
                led1=1; /// red LED on
            }

            while(pause) {///if pause==1
                leds = 3;
                if(buttonA) { /// if button pressed, toggle pause
                    wait_ms(50);
                    pause = 0; ///set pause to 0
                    leds = 1; /// one status LED on
                    led2=1;  /// green LED on
                    led1=0; /// red LED off

                }
            }
        }
        lcd.clear();
        lifeFlag=0;
        updateSnake();
        drawSnake();
        drawNut();
        moveSnake();
        startGmae();
        lcd.refresh();
        wait(0.08);
        if(lifeFlag==1) { ///snake die
            led1=1;
            led2=0;
            lcd.clear();
            lcd.refresh();
            printScore();
            for(int i=0; i<=11; i++) {
                buzzer.period(1/(frequency[i])); /// set PWM period
                buzzer=0.1; /// set duty cycle
                wait(0.5*beat[i]);
            }
            buzzer=0; ///close buzzer
        }

        ain = pot.read(); /// read value of potentiometer
        lcd.setBrightness(ain);
        lcd.refresh();
    }
}