My ELEC2645 project. Nikollao Sulollari. 200804685

Dependencies:   N5110 SoftPWM mbed

Fork of Treasure_Hunt by ELEC2645 (2015/16)

main.cpp

Committer:
Nikollao
Date:
2016-05-04
Revision:
21:6b02ef341358
Parent:
20:59aa6189a47d

File content as of revision 21:6b02ef341358:

/**
@file main.cpp
@brief Game implementation

*/
#include "main.h"
#include "stdlib.h"

int main(void)
{
    lcd.init(); ///initialise LED
    init_K64F(); ///init K64F 
    init_serial(); ///initiate connection with PC port
    init_game(); ///initialize game
    led_output = fsm[fsm_state]; ///set FSM to turn on LEDs
    calibrateJoystick(); ///calibrate joystick

    game_ticker.attach(&game_timer_isr,0.2); ///attach ticker for the menu different from the main ticker
    menu();
    game_ticker.detach();
    //timer.start();

    ticker.attach(&timer_isr,game_speed); ///attach ticker with ISR. Speed is selected by the user
    reset = level; ///set reset = level to check later if level has increased
    g_button1_flag = 0;
    timer.start();
    while (1) {
        
        if (g_timer_flag) {///if timer flag is UP

            g_timer_flag = 0; ///reset flag
            lcd.clear();
            if (reset < level) { ///if level has increased
                g_button1_flag = 0; ///reset weapon button
                reset = level; ///update reset
                rectY = 0; ///set enemies to default position
                circleX = 0;
            }
            guidance(); ///get guidance
            hero(); ///call hero
            enemies(); ///generate enemies 
            obstacles(); ///generate obstacles
            //float count_time = timer.read();
            
            if (g_button1_flag) { ///the blue LED indicates if the weapon is ready to use or not
                blue_led = 0;    
            } else {
                blue_led = 1;
            }
                
            checkOverlap(); ///check is hero has overlapped with enemies or obstacles 
            updateJoystick(); ///update joystick
            lcd.refresh();
        }
        sleep();///use sleep and timer triggered interrupt to save power 
    }
}


//mbed functions


void init_serial()
{
    // set to highest baud - ensure terminal software matches
    pc.baud(115200);
}

void init_K64F()
{
    // on-board LEDs are active-low, so set pin high to turn them off.
    r_led = 1;
    g_led = 1;
    b_led = 1;

    blue_led = 1;

    // since the on-board switches have external pull-ups, we should disable the internal pull-down
    // resistors that are enabled by default using InterruptIn
    sw2.mode(PullNone);
    sw3.mode(PullNone);
    
    button.rise(&button_isr); ///assign rise with ISR
    button1.rise(&button1_isr);
    button.mode(PullDown); ///use PullDown mode
    button1.mode(PullDown);
}


///ISR functions
void timer_isr ()
{
    g_timer_flag = 1;
}

void game_timer_isr()
{
    g_game_timer_flag = 1;
}

void sw2_isr()
{
    g_sw2_flag = 1;
}

void sw3_isr()
{
    g_sw3_flag = 1;
}

void button_isr()
{
    g_button_flag =1;
}

void button1_isr()
{

    g_button1_flag =1;
}

void timeout_isr()
{
    if (button) {
        pc.printf("timeout \n");
    }
}

///game functions

void enemies()
{
    /// generate enemies in the screen depending on the level of difficulty
    if (level == 0) { ///generate enemies at level 0

        enemyRect();
        if (g_button1_flag == 0) {
            enemyCircle();
        }
    } else if (level == 1) {///generate enemies at level 1

        enemyRect();
        if (g_button1_flag == 0) {
            enemyCircle();
        }
    } else if (level == 2) {///generate enemies at level 2

        enemyRocket();
        if (g_button1_flag == 0) {
            enemyCircle();
        }
    } else if (level == 3) {///generate enemies at level 3

        enemyRect();
        if (g_button1_flag == 0) {
            enemyCircle();
        }
    } else if (level == 4) {///generate enemies at level 4

        enemyRect();
        if (g_button1_flag == 0) {
            enemyCircle();
        }
    } else if (level == 5) {///generate enemies at level 5
        enemyRocket();
        if (g_button1_flag == 0) {
            enemyCircle();
        }
    } else if (level == 6) {///generate enemies at level 6
        enemyRocket();
        if (g_button1_flag == 0) {
            enemyCircle();
        }
    } else if (level == 7) {///generate enemies at level 7
        enemyRocket();
        enemyCircle();
        if (g_button1_flag == 1) {///if button1 is pressed don't allow to use at level 7
            g_button1_flag = 0;
             lcd.clear();
            lcd.printString("Can't use now!",0,0);
            lcd.refresh();
            wait(1);
            lcd.clear();
        }
    }

}

void enemyRect()
{
    ///generate rectangular shape enemy
    lcd.drawRect(rectX,rectY,5,4,1);

    rectX = rectX + rand()%4 - 2;
    rectY++; ///enemy moving towards hero

    if (rectY > 50) {///set boundaries for enemy position
        rectY = 0;
    }
    if (rectX > 75 || rectX < 25) {
        rectX = 40+rand()%6 - 3;
    }
}

void enemyRocket() { ///generate a "rocket-like" enemy
    
    lcd.drawRect(rectX,rectY,2,7,1);
    lcd.drawCircle(rectX+1,rectY+1,2,1);
    lcd.drawLine(rectX-2,rectY+2,rectX,rectY-1,1);
    lcd.drawLine(rectX+2,rectY+2,rectX,rectY-1,1);

    rectX = rectX + rand()%4 - 2;
    rectY++; ///enemy moving towards hero

    if (rectY > 50) {///set boundaries for position of enemy
        rectY = 0;
    }
    if (rectX > 75 || rectX < 10) {
        rectX = 40+rand()%6 - 3;
    }
}

void enemyCircle()
{
    ///generate circle shape enemy
    lcd.drawCircle(circleX,circleY,4,1);
    circleY = circleY + rand() %4 - 2;

    if (circleY <= 10) { ///set the boundaries of the enemy
        circleY = 20;
    }
    if (circleY >= 35) {
        circleY = 35;
    }
    if (circleX > 84) {
        circleX = 0;
    }
    circleX++; ///enemy moving towards hero
}
void hero()
{
    ///cotrol hero
    if (joystick.direction == RIGHT) { ///joystick direction points to the right
        heroX--;
    } else if (joystick.direction == LEFT) {///joystick direction points to the left
        heroX++;
    } else {
        heroX = heroX;
    }

    if (joystick.direction == UP) {///joystick direction points to the top
        heroY--;
    } else if (joystick.direction == DOWN) {///joystick direction points down
        heroY++;
    } else {
        heroY = heroY; ///joystick is centred
    }

    if (joystick.direction == UP_LEFT) { ///joystick direction points up and left
        heroY--;
        heroX++;
    } else if (joystick.direction == UP_RIGHT) { ///joystick direction points up and right
        heroY--;
        heroX--;
    } else if (joystick.direction == DOWN_RIGHT) {///joystick direction points down and right
        heroY++;
        heroX--;
    } else if (joystick.direction == DOWN_LEFT) {///joystick direction points down and left
        heroY++;
        heroX++;
    }

    ///set x-axis boundaries so hero does not go out of screen
    if (heroX > 40) {
        heroX = -40;
    }
    if (heroX < -45) {
        heroX = 35;
    }
    if (heroY < -45) { ///if hero has reached the top of the screen
        heroY = 0; ///hero goes back to the bottom of the screen
        g_button1_flag = 0;
        level++; ///increase level of the game
    }

    if (heroY >= 0) {/// hero cannot go to previous level
        heroY = 0;
    }
    ///draw hero
    lcd.drawLine(40+heroX, 47+heroY, 48+heroX, 43+heroY,1); ///variables heroX and heroY are used to control the direction of the hero
    lcd.drawLine(40+heroX, 43+heroY,48+heroX, 47+heroY,1);
    lcd.drawLine(44+heroX, 45+heroY,44+heroX, 41+heroY,1);
    lcd.drawCircle(44+heroX, 39+heroY,2,0);
}

void init_game()
{
    ///initialise game
    srand(time(NULL)); /// generate random numbers
    rectY = 0; /// init rectX, rectY
    rectX = rand() %40 + 20;
    circleY = rand() %20 + 10; /// init circleX, circleY
    circleX = 0;

    lcd.setBrightness(0.5); // put LED backlight on 50%
    lcd.printString("Welcome to",11,1);
    lcd.printString("Treasure Hunt!",1,3);
    lcd.refresh();
    //timeout.attach(&timeout_isr,3);
   // sleep();
    wait(3); ///small delay prints welcome message
    lcd.clear();

}
void guidance()
{
    if (level < 7) {
        lcd.drawLine(42,0,40,2,1);
        lcd.drawLine(42,0,44,2,1);
        lcd.drawLine(42,0,42,3,1);   
    }
    /// function acts as guidance towards the treasure
     else if (level == 7) {

        lcd.printString("F",42,0); /// print the treasure icon
    } else if (level == 8) {
        
        timer.stop(); ///stop timer
        timer.reset();
        float win_time = timer.read();///value reads the time taken to win the game
        char win[80]; ///create an array of chars
        sprintf(win,"Time:%.2f sec",win_time); ///create string
        ticker.detach();
        game_ticker.attach(&game_timer_isr,0.2); 
        lcd.clear();
        lcd.printString("Well done!",0,0);
        lcd.refresh();
        wait(2);
        lcd.clear();
        lcd.printString(win,0,0); ///print the time taken to win the game on screen
        wait(3);
        lcd.clear();
        lcd.printString("Play again!",0,0); ///provide play again option
        lcd.drawCircle(70,4,2,1);
        lcd.refresh();
        g_button_flag = 0;

        while(1) {
            if  (g_button1_flag) { ///if button1 is pressed
                ///reset
                g_button1_flag = 0;
                level = 0;
                lcd.clear();
                main();
                r_led = 0;
                lcd.refresh();
            }
            sleep();
        }
    }
}

void obstacles()
{
    /// place obstacles in the screen
    /// as level difficulty increases, more obstacles are added
    
    if (level == 0) { ///obstacles are located in the ground and they change from one level to another

        lcd.drawRect(10,15,2,2,1);
        lcd.drawRect(74,15,2,2,1);
    } else if (level == 1) {

        lcd.drawRect(10,15,2,2,1);
        lcd.drawRect(74,15,2,2,1);
        lcd.drawRect(10,28,2,2,1);
        lcd.drawRect(74,28,2,2,1);
    } else if (level == 2) {

        lcd.drawCircle(25,25,5,0);
        lcd.drawCircle(65,25,5,0);
        lcd.drawCircle(45,11,3,1);
        lcd.drawCircle(25,25,3,1);
        lcd.drawCircle(65,25,3,1);
        lcd.drawRect(80,2,2,42,1);
        lcd.drawRect(2,2,2,42,1);

    } else if (level == 3) {

        lcd.drawRect(5,12,2,2,1);
        lcd.drawRect(79,12,2,2,1);
        lcd.drawRect(5,30,2,2,1);
        lcd.drawRect(79,30,2,2,1);
        lcd.drawRect(28,12,2,2,1);
        lcd.drawRect(52,12,2,2,1);
        lcd.drawRect(28,30,2,2,1);
        lcd.drawRect(52,30,2,2,1);
    } else if (level == 4) {

        lcd.drawRect(5+rand() %4 - 2 ,12+rand() %4 - 2,2,2,1); ///make obstacles moveable by adding a small random variance in position
        lcd.drawRect(79 + rand() %4 - 2,12 + rand() %4 - 2,2,2,1);
        lcd.drawRect(5+ rand() %4 - 2,30+rand() %4 - 2 ,2,2,1);
        lcd.drawRect(79 + rand() %4 - 2,30+rand() %4 - 2,2,2,1);
        lcd.drawRect(28 + rand() %4 - 2,12+ rand() %4,2,2,1);
        lcd.drawRect(52+rand() %4 - 2,12 + rand() %4 - 2,2,2,1);
        lcd.drawRect(28+rand() %4 - 2,30 + rand() %4 - 2,2,2,1);
        lcd.drawRect(52 + rand() %4 - 2,30+ rand() %4,2,2,1);
    }
    if (objectX == 0) { ///check position of obstacle
        state = 0; ///assign states to the position of the obstacle
    } else if (objectX == 60) {
        state = 1;
    } else {
        state = state;
    }
    if (state == 0) { ///if state is 0 increase position on x-axis
        objectX++;
    } else {
        objectX--; ///else if state is 1 decrease position on x-axis
    }

    if (objectX1 == 68) {

        state1 = 1;
    } else if (objectX1 == 10) {
        state1 = 0;
    }
    if (state1 == 1) {
        objectX1--;
    } else if (state1 == 0) {
        objectX1++;
    }
    objectY = objectY + rand() %4 - 2; ///set poistion of obstacle on y-axis to be valuable
    ///keep moving object within boundaries
    if (objectY <= 10) {
        objectY = 10;
    }
    if (objectY >= 37) {
        objectY = 37;
    }
    if ( level == 5) {

        lcd.drawLine(15,10,15,37,1);
        lcd.drawLine(71,10,71,37,1);

        lcd.drawRect(11+objectX,objectY,2,2,1); ///draw obstacle

        lcd.drawRect(80,10,2,2,1);
        lcd.drawRect(5,10,2,2,1);
        lcd.drawRect(80,20,2,2,1);
        lcd.drawRect(5,20,2,2,1);
        lcd.drawRect(80,30,2,2,1);
        lcd.drawRect(5,30,2,2,1);

    } else if (level == 6) {

        lcd.drawLine(15,10,15,37,1); ///draw boundaries
        lcd.drawLine(71,10,71,37,1);

        lcd.drawRect(11+objectX,objectY,2,2,1); /// draw moving obstacles on screen
        lcd.drawRect(objectX1,10+objectY,2,2,1);
        lcd.drawRect(80,10,2,2,1); ///draw stable obstacles
        lcd.drawRect(5,10,2,2,1);
        lcd.drawRect(80,20,2,2,1);
        lcd.drawRect(5,20,2,2,1);
        lcd.drawRect(80,30,2,2,1);
        lcd.drawRect(5,30,2,2,1);
    } else if (level == 7) {
        lcd.printString("??",65,0);

       lcd.drawRect(1,23,82,2,1);
       if (button && heroX <-30) {
            g_button_flag = 0;
            heroX = -30;
            heroY = -30;  
        }
           
        pc.printf("x = %d , y = %d \n",heroX,heroY);
    }
}


void calibrateJoystick()
{
    // 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 if (joystick.y > DIRECTION_TOLERANCE  && joystick.x  < DIRECTION_TOLERANCE) {
        joystick.direction = UP_LEFT;
    } else if (joystick.y > DIRECTION_TOLERANCE && joystick.x > DIRECTION_TOLERANCE) {
        joystick.direction = UP_RIGHT;
    } else if (joystick.y < DIRECTION_TOLERANCE && joystick.x < DIRECTION_TOLERANCE) {
        joystick.direction = DOWN_LEFT;
    }   else if (joystick.y < DIRECTION_TOLERANCE && joystick.x > DIRECTION_TOLERANCE) {
        joystick.direction = DOWN_RIGHT;
    }
}

void menu()
{
    while(1) {
        if (g_game_timer_flag) {
            g_game_timer_flag = 0;

            updateJoystick();
            lcd.clear();

            lcd.printString("Start Game",0,0); ///print the main
            lcd.printString("Settings",0,2);
            lcd.printString("Exit",0,4);
            //lcd.drawCircle(70,4,2,1);
            lcd.refresh();
            switch (joystick.direction) { ///check the direction of joystick
                case UP:
                    option--;
                    break;
                case DOWN:
                    option++;
                    break;
            }
            if (option < 0) { /// if the last (down) option is set for selection and user presses joystick down, selector moves at the top
                option = 2;
            }
            if (option > 2) { /// if the first (up) option is set for selection and user presses joystick up, selector moves at the bottom
                option = 0;
            }

            if (option == 0) { ///selection in menu depends on the value of int option
                lcd.drawCircle(70,4,2,1);
            } else if (option == 1) {
                lcd.drawCircle(55,20,2,1);
            } else if (option == 2) {
                lcd.drawCircle(35,35,2,1);
            }

            if(g_button_flag) { /// if button is pressed

                g_button_flag = 0; ///reset flag

                if (option == 0) { ///break the while loop, start game
                    break;
                }

                else if (option == 1) { ///enter settings menu

                    option = 0;

                    while(1) {
                        if (g_game_timer_flag) {
                            g_game_timer_flag = 0;

                            updateJoystick(); ///update joystick position
                            lcd.clear();
                            if (normal) {
                                if (sound) {
                                    lcd.printString("Game speed",0,0);  ///print settings menu
                                    lcd.printString("Lcd:Inverse",0,1);
                                    lcd.printString("Sound:ON",0,2);
                                    lcd.printString("Back",0,4);
                                } else {
                                    lcd.printString("Game speed",0,0);  ///print settings menu
                                    lcd.printString("Lcd:Inverse",0,1);
                                    lcd.printString("Sound:OFF",0,2);
                                    lcd.printString("Back",0,4);
                                }
                            } else {
                                if (sound) {
                                    lcd.printString("Game speed",0,0);  ///print settings menu
                                    lcd.printString("Lcd:Normal",0,1);
                                    lcd.printString("Sound:ON",0,2);
                                    lcd.printString("Back",0,4);
                                } else {
                                    lcd.printString("Game speed",0,0);  ///print settings menu
                                    lcd.printString("Lcd:Normal",0,1);
                                    lcd.printString("Sound:OFF",0,2);
                                    lcd.printString("Back",0,4);
                                }
                            }
                            switch (joystick.direction) {
                                case UP:
                                    option--;
                                    break;
                                case DOWN:
                                    option++;
                                    break;
                                case CENTRE:
                                    option = option;
                                    break;
                            }
                            if (option < 0) { ///if selector is on the top of the screen and UP is pressed, selector goes to the bottom
                                option = 3;
                            }
                            if (option > 3) { ///if selector is on the bottom of the screen and DOWN is pressed, selector goes to the top
                                option = 0;
                            }

                            /// menu selection depends on the position of the Joystick
                            if (option == 0) {
                                lcd.drawCircle(70,4,2,1);
                            } else if (option == 1) {
                                lcd.drawCircle(70,12,2,1);
                            } else if (option == 2) {
                                lcd.drawCircle(70,20,2,1);
                            } else {
                                lcd.drawCircle(35,36,2,1);
                            }
                            if (g_button_flag) { ///if button is pressed
                                g_button_flag = 0; ///reset button

                                if (option == 0) { /// if user selects to modify speed of the game

                                    while(1) { ///set speed of the game

                                        if (g_game_timer_flag) {
                                            g_game_timer_flag = 0;
                                            updateJoystick();
                                            lcd.clear();
                                            if (speed == 0) {
                                                lcd.printString("Slow<",0,0); ///print game speed menu
                                                lcd.printString("Normal",0,1);
                                                lcd.printString("Fast",0,2);
                                                lcd.printString("Back",0,4);
                                            } else if (speed == 1) {
                                                lcd.printString("Slow",0,0); //print game speed menu
                                                lcd.printString("Normal<",0,1);
                                                lcd.printString("Fast",0,2);
                                                lcd.printString("Back",0,4);
                                            } else if (speed == 2) {
                                                lcd.printString("Slow",0,0); //print game speed menu
                                                lcd.printString("Normal",0,1);
                                                lcd.printString("Fast<",0,2);
                                                lcd.printString("Back",0,4);
                                            }

                                            switch (joystick.direction) {
                                                case UP:
                                                    option--;
                                                    break;
                                                case DOWN:
                                                    option++;
                                                    break;
                                                case CENTRE:
                                                    option = option;
                                                    break;
                                            }
                                            if (option < 0) {
                                                option = 3;
                                            }
                                            if (option > 3) {
                                                option = 0;
                                            }

                                            if (option == 0) {
                                                lcd.drawCircle(70,4,2,1);
                                            } else if (option == 1) {
                                                lcd.drawCircle(55,12,2,1);
                                            } else if (option == 2) {
                                                lcd.drawCircle(35,20,2,1);
                                            } else {
                                                lcd.drawCircle(35,36,2,1);
                                            }

                                            if (g_button_flag) {
                                                g_button_flag = 0;

                                                if (option == 0) {
                                                    game_speed = 0.1; ///slow
                                                    speed = 0;
                                                } else if (option == 1) {
                                                    game_speed = 0.05; ///normal
                                                    speed = 1;
                                                } else if (option == 2) {
                                                    game_speed = 0.04; ///fast
                                                    speed = 2;
                                                } else if (option == 3) {
                                                    break;
                                                }
                                            }
                                            lcd.refresh();
                                        }
                                        sleep();
                                    }
                                } else if (option == 1) { /// Lcd inverse mode
                                    normal =! normal;
                                    if (normal) {
                                        lcd.inverseMode();
                                    } else {
                                        lcd.normalMode();
                                    }
                                } else if (option == 2) { ///select  sound or not

                                    sound =! sound;

                                    if (sound) {
                                        //buzzer.write(0.5);
                                       // buzzer.period(1/4000);
                                    }
                                    else {
                                        buzzer.write(0.0);
                                    }
                                    // buzzer.period(1/400);
                                } else if(option == 3) { ///go back to main menu
                                    break;
                                }
                            }
                            lcd.refresh();
                        }
                        sleep();
                    }
                } else if (option == 2) { ///turn off LED
                    lcd.clear();
                    lcd.turnOff();
                    while(1) {
                        deepsleep();
                    }
                }
            }
            lcd.refresh();
        }
        sleep();
    }
}

int intersection(int i, int j)
{
    /// check for overlap between enemies and hero
    n=0;

    if (lcd.getPixel(i-1,j-1)!=0) //pixel to the top-left
        n++; // increase n by 1
    if (lcd.getPixel(i-1,j)!=0) //pixel to the left
        n++; // increase n by 1
    if (lcd.getPixel(i-1,j+1)!=0) //pixel to the bottom-left
        n++; // increase n by 1
    if (lcd.getPixel(i,j-1)!=0) // pixel to the top
        n++; // increase n by 1
    if (lcd.getPixel(i,j+1)!=0) //pixel to the bottom
        n++; // increase n by 1
    if (lcd.getPixel(i+1,j-1)!=0) //pixel to the top-right
        n++; // increase n by 1
    if (lcd.getPixel(i+1,j)!=0) // pixel to the right
        n++; // increase n by 1
    if (lcd.getPixel(i+1,j+1)!=0) //pixel to the bottom right
        n++; // increase n by 1
    return n;
}

void checkOverlap()
{

    for (int i=40+heroX; i<50+heroX; i++) { ///loop follows the hero and checks for overlap around him
        for (int j=35+heroY; j<48+heroY; j++) {

            int check = intersection(i,j); ///int gets number of pixels around the hero
            //lcd.setPixel(i,j);
            char bit[50];
            sprintf(bit,"Pixels: %d",check);


            for(int i = 40; i < 50; i++) { ///provides safety if hero is in default position he doesn't get killed by enemies
                for (int j = 35; j < 47; j++) {

                    if (lcd.getPixel(i,j) && check > 6) { ///6 is the offset of the neigbours, as hero has his own neighbours pixels 
                        check = 6;
                    }
                }
            }
            if (check > 7) {
                tries--;
                //if tries
                lcd.printString("BANG!",0,0); ///Bang message is displayed when overlap has occured
                if (sound) {
                    buzzer.write(0.5);
                    //buzzer.pulsewidth(0.9);
                } else {
                    buzzer.write(0.0);
                }
                lcd.refresh();
                wait(2);
                lcd.clear();

                if (tries == 2) {
                    
                    g_button1_flag = 0;
                    lcd.printString("Ready.",20,1);
                    lcd.refresh();
                    wait(0.5);
                    lcd.printString("Ready..",20,1);
                    lcd.refresh();
                    wait(0.5);
                    lcd.printString("Ready...",20,1);
                    lcd.refresh();
                    wait(1);
                    lcd.printString("GO!",31,3);
                    lcd.refresh();
                    wait(1);
                    lcd.clear();
                    fsm_state = 1; ///2 lives left
                } else if (tries == 1) {
                    
                    g_button1_flag = 0;
                    lcd.clear();
                    lcd.printString("Last Chance!",10,2);
                    lcd.refresh();
                    wait(1);
                    fsm_state = 2; //1 life left
                } else if (tries == 0) {
                    
                    g_button1_flag = 0;
                    fsm_state = 3;
                    led_output=fsm[fsm_state];
                    lcd.clear();
                    lcd.printString("Game Over!",10,2);
                    timer.stop();
                    timer.reset();
                    lcd.refresh();
                    wait(2);

                    ticker.detach();
                    game_ticker.attach(&game_timer_isr,0.2); ///attach a slower ticker to save power while not playing
                    lcd.clear();
                    lcd.printString("Play again!",0,0);
                    lcd.drawCircle(70,4,2,1);
                    lcd.refresh();
                    g_button_flag = 0;

                    while(1) {
                        if  (g_button1_flag) { ///if button1 is pressed

                            g_button1_flag = 0; ///reset button1 flag
                            level = 0; ///reset parameters
                            tries = 3;
                            fsm_state = 0;
                            led_output=fsm[fsm_state];
                            buzzer.write(0.0);
                            lcd.clear();
                            ///reset values
                            heroX = 0;
                            heroY = 0;
                            rectY = 0;
                            circleX = 0;
                            main(); ///call main
                        }
                        sleep();
                    }

                }
                heroX = 0;
                heroY = 0;
                rectY = 0;
                circleX = 0;
                led_output=fsm[fsm_state];
                buzzer.write(0.0);
            }

        }
    }
}