Game Project by Mauro Aguiar/el14mma

Dependencies:   N5110 mbed

main.cpp

Committer:
el14mma
Date:
2016-05-05
Revision:
1:32905b0858ac
Parent:
0:026fa541af7a

File content as of revision 1:32905b0858ac:

/* Maze Escape

Mauro Aguiar
*/

#include "mbed.h"
#include "N5110.h"

// change this to alter tolerance of joystick direction
#define DIRECTION_TOLERANCE 0.05

// connections for joystick
DigitalIn button(PTB11);
AnalogIn xPot(PTB2);
AnalogIn yPot(PTB3);

N5110 lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3);

// timer to regularly read the joystick
Ticker pollJoystick;

// timer to move the obstacle
Ticker ticker;

// timer to increase score and discharge energy
Ticker ticker2;

// Serial for debug
Serial serial(USBTX,USBRX);

// menu is on mode

        int loading = 0;

// origin coordinates for the cercle
        int a = 41; 
        int b = 23;

// Save variables 

        int save1 = 1;
        int save2 = 1;
        int save3 = 1;
        int save4 = 1;
        int save5 = 1;
        
// Initial obstacle speed

        float speed = 0.5;
// Game Score

        int score = 0;
        
// origin coordinates for obstacles
        
        int d1 = 1;
        
        int d2 = 1;
        
        int d3 = 1;
        
        int d4 = 83;
        
        int d5;
        
        int d6;
        
        int b1;
        
        int b2;
        
        int b3 = 0;
        
        int b4 = 47;
        
// Energy needed for the player to use slow mode (must discharge to one)
        
        int energy = 20;
        
// Random Obstacle decision by random variable and obstacles states

        int r = 0;
        
        int state1 = 0;
        int state2 = 0;
        int state3 = 0;
        int state4 = 0;
        int state5 = 0;
        int state6 = 0;
        
// Variables used to check if the player touched an obstacle

        int hit = 0;
        int hit1 = 0;
        int hit2 = 0;
        int hit3 = 0;
        int hit4 = 0;
        int hit5 = 0;
        int hit6 = 0;
        int hit7 = 0;
        int hit8 = 0;
        

// create enumerated type (0,1,2,3 etc. for direction)
// could be extended for diagonals etc.
enum DirectionName {
    UP,
    DOWN,
    LEFT,
    RIGHT,
    CENTRE,
    DIAGONAL_RIGHT_UP,
    DIAGONAL_RIGHT_DOWN,
    DIAGONAL_LEFT_UP,
    DIAGONAL_LEFT_DOWN,
    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 printFlag = 0;

// function prototypes
void calibrateJoystick();
void updateJoystick();
void obstacle();
void lost();
void erase();
void erase2();
void erase3();
void erase4();
void erase5();
void update();
void menu();

int main()
{       
    calibrateJoystick();  // get centred values of joystick
    pollJoystick.attach(&updateJoystick,1.0/11.0);  // read joystick 12 times per second (faster than obstacle max speed )
    lcd.init();
    
    lcd.printString("Welcome to",0,1);
    lcd.printString("Maze Escape",0,2);
    lcd.printString("Press Button",0,3);
    lcd.printString("to Play",0,4);
    
 while ( button == 0 ) {
     
     sleep();
}

    lcd.clear();
    lcd.drawCircle(a,b,2,0);
    
    // draw a line across the display at y = 47 pixels
        for (int i = 0; i < WIDTH; i++) {
            lcd.setPixel(i,47);
        }
        
        // draw a line across the display at x = 0 pixels
        for (int i = 0; i < WIDTH; i++) {
            lcd.setPixel(0,i);
        }
        
        // draw a line across the display at y = 0 pixels 
        for (int i = 0; i < WIDTH; i++) {
            lcd.setPixel(i,0);
        }
        
        // draw a line across the display at x = 83 pixels 
        for (int i = 0; i < WIDTH; i++) {
            lcd.setPixel(83,i);
        }
        
    ticker.attach(&obstacle,speed); // Obstacle speed
    ticker2.attach(&update,1); // points gain and energy discharge speed
    
    lcd.refresh();
    

    while(1) {
        
        if (button == energy) { // Button pressed <=> Slow mode activated
            
         speed = 2;
         
         ticker.detach();
         
         ticker.attach(&obstacle,speed); // New Obstacle speed
         
         energy = 20; // energy is recharged so the slow mode can only be used in 20 seconds.
         
        // reset saves 
        save1 = 1;
        save2 = 1;
        save3 = 1;
        save4 = 1;
        save5 = 1;
        }

        if (printFlag) {  // if flag set, clear flag and print joystick values to serial port
            printFlag = 0;
            serial.printf("x = %f y = %f button = %d ",joystick.x,joystick.y,joystick.button);

            // check joystick direction
            if (joystick.direction == DOWN)
                {
            if (loading == 0) {       
                serial.printf(" DOWN\n");
                erase();
                b=b-2;
                lost();
                if (hit ==0) {
                lcd.drawCircle(a,b,2,0);
                }
                lcd.refresh();}}
                
            if (joystick.direction == UP)
               {
            if (loading == 0) {    
                serial.printf(" UP\n");
                erase();
                b=b+2;
                lost();
                if (hit ==0) {
                lcd.drawCircle(a,b,2,0);
                }
                lcd.refresh();}}
                
            if (joystick.direction == RIGHT)
               {
            if (loading == 0) {    
                serial.printf(" RIGHT\n");
                erase();
                a=a+2;
                lost();
                if (hit ==0) {
                lcd.drawCircle(a,b,2,0);
                }
                lcd.refresh();}}
                
            if (joystick.direction == LEFT)
                {
            if (loading == 0) {        
                serial.printf(" LEFT\n");
                erase();
                a=a-2;
                lost();
                if (hit ==0) {
                lcd.drawCircle(a,b,2,0);
                }
                lcd.refresh();}}
                
            if (joystick.direction == DIAGONAL_RIGHT_UP)
                {
            if (loading == 0) {        
                serial.printf(" DIAGONAL-RIGHT-UP\n");
                erase();
                a=a+2;
                b=b+2;
                lost();
                if (hit ==0) {
                lcd.drawCircle(a,b,2,0);
                }
                lcd.refresh();}}
                
            if (joystick.direction == DIAGONAL_RIGHT_DOWN)
                {
            if (loading == 0) {    
                serial.printf(" DIAGONAL-RIGHT-DOWN\n");
                erase();
                a=a+2;
                b=b-2;
                lost();
                if (hit ==0) {
                lcd.drawCircle(a,b,2,0);
                }
                lcd.refresh();}}
                
            if (joystick.direction == DIAGONAL_LEFT_UP)
                {
            if (loading == 0) {        
                serial.printf(" DIAGONAL-LEFT-UP\n");
                erase();
                a=a-2;
                b=b+2;
                lost();
                if (hit ==0) {
                lcd.drawCircle(a,b,2,0);
                }
                lcd.refresh();}}
                
            if (joystick.direction == DIAGONAL_LEFT_DOWN)
                {
            if (loading == 0) {        
                serial.printf(" DIAGONAL-RIGHT-UP\n");
                erase();
                a=a-2;
                b=b-2;
                lost();
                if (hit ==0) {
                lcd.drawCircle(a,b,2,0);
                }
                lcd.refresh();}}
                
            if (joystick.direction == CENTRE)
               { 
            if (loading == 0) {   
                serial.printf(" CENTRE\n");
                erase();
                b=b-1;
                lost();
                if (hit ==0) {
                lcd.drawCircle(a,b,2,0);
                }
                lcd.refresh();
               }}
                
                
            if (joystick.direction == UNKNOWN)
                {serial.printf(" Unsupported direction\n");}
                

        }
        
      }

}

// 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; // inverted because of screen
        
    } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = UP; // inverted because of screen
        
    } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = LEFT; 
        
    } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = RIGHT;
        
    } else if ( joystick.x < DIRECTION_TOLERANCE && joystick.y < DIRECTION_TOLERANCE) {
        joystick.direction = DIAGONAL_RIGHT_UP;
        
    } else if ( joystick.x < DIRECTION_TOLERANCE && joystick.y > DIRECTION_TOLERANCE) {
        joystick.direction = DIAGONAL_RIGHT_DOWN;
        
    } else if ( joystick.x > DIRECTION_TOLERANCE && joystick.y < DIRECTION_TOLERANCE) {
        joystick.direction = DIAGONAL_LEFT_UP;
    }
    
    else if ( joystick.x > DIRECTION_TOLERANCE && joystick.y > DIRECTION_TOLERANCE) {
        joystick.direction = DIAGONAL_LEFT_DOWN;
    }
    
    else {
        joystick.direction = UNKNOWN; // In case the reading is not accurate
    }

    // set flag for printing
    printFlag = 1;
}
void obstacle()
{    
     if (score > 15 && score <= 30 ) { 
     
     if (save1 == 1) { // only happens once
     
         save1 = 0;
         
         speed = 0.4;
         
         ticker.detach();
         
         ticker.attach(&obstacle,speed); // New Obstacle speed
         
         }
         
         }
         
    else if (score >30 && score<=50) {
         
    if (save2 == 1) {
         
         save2 = 0;
         
         speed = 0.3;
         
         ticker.detach();
         
         ticker.attach(&obstacle,speed); // New Obstacle speed
         
         }
         }
         
    else if (score>50 && score<=80) {
         
    if (save3 == 1); {
         
         save3 = 0;
         
         speed = 0.2;
         
         ticker.detach();
         
         ticker.attach(&obstacle,speed); // New Obstacle speed
         
         }
         }
         
else if (score>80 && score<=110) {
          
    if (save4 == 1) {
          
         save4 = 0;
          
         speed = 0.15;
         
         ticker.detach();
         
         ticker.attach(&obstacle,speed); // New Obstacle speed
          
          }
        }
else if (score>110) { // Fastest mode
    
    if (save5 == 1) {
    
         save5 = 0;
          
         speed = 0.1;
         
         ticker.detach();
         
         ticker.attach(&obstacle,speed); // New Obstacle speed
         
         }
          
    }
        
if (d2-d1>10 || d1-d2>10) { // minimun distance
        
 r = rand() %6; // generate random number between 0 and 5 for obstacle   
 
}
    
 if (r == 0 || state1 == 1) { // obstacle 1
 
 if (state1 == 0) { // once
 
// draw a line across the display at y = 0 pixels 
        for (int i = 0; i < WIDTH; i++) {
            lcd.setPixel(i,0);
        }
        
}
        
        if (d1<47) { // less than maximun vertical pixels
        
        state1 = 1; // on
        
        // erase previous line
        for (int i = 41; i < 83; i++) {
            lcd.clearPixel(i,d1);
        }
        
        d1=d1+1;
        
        lcd.drawLine(83,d1,41,d1,1);  
        
        lcd.refresh();
        
        
        }
        
        else {
            
            d1 = 1;
            
            state1 = 0; // off
            
             }
        }
    
 if (r==1 || state2 == 1) { // obstacle 2 
        
        if (d2<47) { // less than maximun vertical pixels
        
        state2 = 1; // on
        
        // erase previous line
        for (int i = 1; i < 42; i++) {
            lcd.clearPixel(i,d2);
        }
        
        d2=d2+1;
        
        lcd.drawLine(41,d2,0,d2,1);  
        
        lcd.refresh();
        
        
        }
        
        else {
            
            d2 = 1;
            
            state2 = 0; // off
        
        }   
}

if (r==2 || state3 == 1) { // obstacle 3

if (state3 == 0) { // Only happens once inside the loop
    
    b1 = b;
}
    
    if (d3<84) { // less than maximun horizontal pixels
        
        state3 = 1; // on
        
        // erase previous circle
        erase2();
        
        d3=d3+2;
        
        lcd.drawCircle(d3,b1,2,0); 
        
        lcd.refresh();
        
        
        }
        
        else {
            
            d3 = 1;
            
            state3 = 0; // off
        
        }
        
    }
    
if (r==3 || state4 == 1) { // obstacle 4

if (state4 == 0) { // Only happens once inside the loop
    
    b2 = b;
}
    
    if (d4>=0) { // minimun horizontal pixels
        
        state4 = 1; // on
        
        // erase previous circle
        erase3();
        
        d4=d4-2;
        
        lcd.drawCircle(d4,b2,2,0); 
        
        lcd.refresh();
        
        
        }
        
        else {
            
            d4 = 83;
            
            state4 = 0; // off
        
        }
        
    }
    
if (r==4 || state5 == 1) { // obstacle 5

if (state5 == 0) { // Only happens once inside the loop
    
    d5 = a;
}
    
    if (b3<47) { // minimun vertical pixels
        
        state5 = 1; // on
        
        // erase previous circle
        erase4();
        
        b3=b3+2;
        
        lcd.drawCircle(d5,b3,2,0); 
        
        lcd.refresh();
        
        
        }
        
        else {
            
            b3 = 0;
            
            state5 = 0; // off
        
        }
        
    }
    
if (r==5 || state6 == 1) { // obstacle 6

if (state6 == 0) { // Only happens once inside the loop
    
    d6 = a;
}
    
    if (b4>=0) {
        
        state6 = 1; // on
        
        // erase previous circle
        erase5();
        
        b4=b4-2;
        
        lcd.drawCircle(d6,b4,2,0); 
        
        lcd.refresh();
        
        
        }
        
        else {
            
            b4 = 47;
            
            state6 = 0; // off
        
        }
        
    }
    
}



void lost() // Check if player lost
{
            int x = 2;
            
            int y = 0;
            
            int radiusError = 1-x;
            
            while(x >= y) {
                
           // Check if the pixels where the player move to are clear
            
           hit1 = lcd.getPixel( x + a,  y + b); 
           hit2 = lcd.getPixel(-x + a,  y + b);
           hit3 = lcd.getPixel( y + a,  x + b);
           hit4 = lcd.getPixel(-y + a,  x + b);
           hit5 = lcd.getPixel(-y + a, -x + b);
           hit6 = lcd.getPixel( y + a, -x + b);
           hit7 = lcd.getPixel( x + a, -y + b);
           hit8 = lcd.getPixel(-x + a, -y + b);
            
            
            y++;
            
        if (radiusError<0) {
            radiusError += 2 * y + 1;
        } else {
            x--;
            radiusError += 2 * (y - x) + 1;
        }
        
        }
        
        hit = hit1+hit2+hit3+hit4+hit5+hit6+hit7+hit8;
        
        if (hit != 0) { // touched obstacle
        
                  ticker.detach();
                  ticker2.detach();
                  
                  loading = 1;
        
                  lcd.clear();
                  
                  lcd.printString("Game Over",0,1);
                  lcd.printString("Press Button",0,3);
                  lcd.printString("to exit",0,4);
                  
                  char buffer[14];  // each character is 6 pixels wide, screen is 84 pixels (84/6 = 14)
                  
                  int length = sprintf(buffer,"Score %2d",score);
                  lcd.printString(buffer,0,2);
                  lcd.refresh();
                  
                  while (button == 0) { // button not pressed
                  
                      sleep();
                      
                    }
                    
                    menu();
            
            }
    
    
}

void erase() 
{
            int x = 2;
            
            int y = 0;
            
            int radiusError = 1-x;
            
            while(x >= y) {
            
            lcd.clearPixel( x + a,  y + b);
            lcd.clearPixel(-x + a,  y + b);
            lcd.clearPixel( y + a,  x + b);
            lcd.clearPixel(-y + a,  x + b);
            lcd.clearPixel(-y + a, -x + b);
            lcd.clearPixel( y + a, -x + b);
            lcd.clearPixel( x + a, -y + b);
            lcd.clearPixel(-x + a, -y + b);
            
            
            y++;
            
        if (radiusError<0) {
            radiusError += 2 * y + 1;
        } else {
            x--;
            radiusError += 2 * (y - x) + 1;
        }
        
        } 
         
         lcd.refresh();   
}

void erase2() {
    
            int x = 2;
            
            int y = 0;
            
            int radiusError = 1-x;
            
            while(x >= y) {
            
            lcd.clearPixel( x + d3,  y + b1);
            lcd.clearPixel(-x + d3,  y + b1);
            lcd.clearPixel( y + d3,  x + b1);
            lcd.clearPixel(-y + d3,  x + b1);
            lcd.clearPixel(-y + d3, -x + b1);
            lcd.clearPixel( y + d3, -x + b1);
            lcd.clearPixel( x + d3, -y + b1);
            lcd.clearPixel(-x + d3, -y + b1);
            
            
            y++;
            
        if (radiusError<0) {
            radiusError += 2 * y + 1;
        } else {
            x--;
            radiusError += 2 * (y - x) + 1;
        }
        
        } 
         
         lcd.refresh();   
}

void erase3(){
    
            int x = 2;
            
            int y = 0;
            
            int radiusError = 1-x;
            
            while(x >= y) {
            
            lcd.clearPixel( x + d4,  y + b2);
            lcd.clearPixel(-x + d4,  y + b2);
            lcd.clearPixel( y + d4,  x + b2);
            lcd.clearPixel(-y + d4,  x + b2);
            lcd.clearPixel(-y + d4, -x + b2);
            lcd.clearPixel( y + d4, -x + b2);
            lcd.clearPixel( x + d4, -y + b2);
            lcd.clearPixel(-x + d4, -y + b2);
            
            
            y++;
            
        if (radiusError<0) {
            radiusError += 2 * y + 1;
        } else {
            x--;
            radiusError += 2 * (y - x) + 1;
        }
        
        } 
         
         lcd.refresh(); 
}

void erase4(){
    
            int x = 2;
            
            int y = 0;
            
            int radiusError = 1-x;
            
            while(x >= y) {
            
            lcd.clearPixel( x + d5,  y + b3);
            lcd.clearPixel(-x + d5,  y + b3);
            lcd.clearPixel( y + d5,  x + b3);
            lcd.clearPixel(-y + d5,  x + b3);
            lcd.clearPixel(-y + d5, -x + b3);
            lcd.clearPixel( y + d5, -x + b3);
            lcd.clearPixel( x + d5, -y + b3);
            lcd.clearPixel(-x + d5, -y + b3);
            
            
            y++;
            
        if (radiusError<0) {
            radiusError += 2 * y + 1;
        } else {
            x--;
            radiusError += 2 * (y - x) + 1;
        }
        
        } 
         
         lcd.refresh(); 
}

void erase5(){
    
            int x = 2;
            
            int y = 0;
            
            int radiusError = 1-x;
            
            while(x >= y) {
            
            lcd.clearPixel( x + d6,  y + b4);
            lcd.clearPixel(-x + d6,  y + b4);
            lcd.clearPixel( y + d6,  x + b4);
            lcd.clearPixel(-y + d6,  x + b4);
            lcd.clearPixel(-y + d6, -x + b4);
            lcd.clearPixel( y + d6, -x + b4);
            lcd.clearPixel( x + d6, -y + b4);
            lcd.clearPixel(-x + d6, -y + b4);
            
            
            y++;
            
        if (radiusError<0) {
            radiusError += 2 * y + 1;
        } else {
            x--;
            radiusError += 2 * (y - x) + 1;
        }
        
        } 
         
         lcd.refresh(); 
}

void update() {
    
    score = score+1;
    
    if (energy > 1) {
    
    energy = energy-1;
    
    }
    
}

void menu() { // reset game
    
// origin coordinates for the cercle
        a = 41; 
        b = 23;

// Save variables 

        save1 = 1;
        save2 = 1;
        save3 = 1;
        save4 = 1;
        save5 = 1;
        
// Initial obstacle speed

        speed = 0.5;
// Game Score

        score = 0;
        
// origin coordinates for obstacles
        
        d1 = 1;
        
        d2 = 1;
        
        d3 = 1;
        
        d4 = 83;
        
        d5 = 0;
        
        d6 = 0;
        
        b1 = 0;
        
        b2 = 0;
        
        b3 = 0;
        
        b4 = 47;
        
// Energy needed for the player to use slow mode (must discharge to one)
        
        energy = 20;
        
// Random Obstacle decision by random variable and obstacles states

        r = 0;
        
        state1 = 0;
        state2 = 0;
        state3 = 0;
        state4 = 0;
        state5 = 0;
        state6 = 0;
        
// Variables used to check if the player touched an obstacle

        hit = 0;
        hit1 = 0;
        hit2 = 0;
        hit3 = 0;
        hit4 = 0;
        hit5 = 0;
        hit6 = 0;
        hit7 = 0;
        hit8 = 0;
        
    lcd.clear();
    
    wait(1);
    
    loading = 0;
        
    main();
                  
}