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-02
Revision:
19:70d40dac5ae0
Parent:
18:5405ee7e243b
Child:
20:59aa6189a47d

File content as of revision 19:70d40dac5ae0:

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

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

int main()
{
    lcd.init();
    init_K64F();
    init_serial();
    init_game(); ///initialize game
    led_output = fsm[fsm_state];
    calibrateJoystick(); ///calibrate joystick
    button.rise(&button_isr); ///assign rise with ISR
    button1.rise(&button1_isr);

    game_ticker.attach(&game_timer_isr,0.2);
    menu();
    game_ticker.detach();

    ticker.attach(&timer_isr,game_speed); ///attach ticker with ISR every 0.1 sec
    reset = level; ///set reset = level to check later if level has increased

    while (1) {

        if (g_timer_flag) {

            g_timer_flag = 0; ///reset flag
            lcd.clear();
            guidance();
            hero();
            enemies();
            obstacles();

            if (reset < level) { ///if level has increased

                reset = level; ///update reset
                rectX = rand() % 84; ///set the position of rect enemy
                rectY = 0;
                circleX = 0; ///set position of circle enemy
                circleY = rand() % 47;
            }
            pc.printf("x = %f y = %f button = %d \n",joystick.x,joystick.y,joystick.button);
            pc.printf("heroY = %d , heroX = %d , n = %d \n",heroY, heroX, n);
            checkOverlap();
            updateJoystick();
            lcd.refresh();
        }
        sleep();
    }
}

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.mode(PullDown);
    button1.mode(PullDown);
}

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");
    }
}

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

        enemyRect();
        enemyCircle();
    } else if (level == 1) {

        enemyRect();
        enemyCircle();
    } else if (level == 2) {
        
        enemyRocket();
    } else if (level == 3) {
        
        enemyRect();
        enemyCircle();
    } else if (level == 4) {
        
         enemyRect();
        enemyCircle();  
    } else if (level == 5) {
        enemyRocket();
    } else if (level == 6) {
        enemyRocket();
        enemyCircle();   
    }
    else if (level == 7) {
           
    }
}

void enemyRect()
{
    ///generate rect shape enemy
    lcd.drawRect(rectX,rectY,5,4,1);
    rectX = rectX + rand()%4 - 2;
    rectY++; ///enemy moving towards hero
    if (rectY == 50) {
        rectY = 0;
    }
    if (rectX > 75 || rectX < 25) {
        rectX = 40+rand()%6 - 3;
    }
}

void enemyRocket() {
    
    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) {
        rectY = 0;
    }
    if (rectX > 75 || rectX < 10) {
        rectX = 40+rand()%6 - 3;
    }
}
void hero()
{
    ///cotrol hero
    if (joystick.direction == RIGHT) {
        heroX--;
    } else if (joystick.direction == LEFT) {
        heroX++;
    } else {
        heroX = heroX;
    }

    if (joystick.direction == UP) {
        heroY--;
    } else if (joystick.direction == DOWN) {
        heroY++;
    } else {
        heroY = heroY;
    }

    if (joystick.direction == UP_LEFT) {
        heroY--;
        heroX++;
    } else if (joystick.direction == UP_RIGHT) {
        heroY--;
        heroX--;
    } else if (joystick.direction == DOWN_RIGHT) {
        heroY++;
        heroX--;
    } else if (joystick.direction == DOWN_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
        level++; ///level increases by 1
    }

    if (heroY >= 0) {/// hero cannot go to previous level
        heroY = 0;
    }
    ///draw hero
    lcd.drawLine(40+heroX, 47+heroY, 48+heroX, 43+heroY,1);
    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 enemyCircle()
{
    ///generate circle shape enemy
    lcd.drawCircle(circleX,circleY,4,1);
    circleY = circleY + rand() %4 - 2;

    if (circleY <= 10) {
        circleY = 20;
    }
    if (circleY >= 35) {
        circleY = 35;
    }
    if (circleX > 84) {
        circleX = 0;
    }
    circleX++; ///enemy moving towards hero
}

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);
    lcd.clear();

}
void guidance()
{
    /// show arrow to act as guidance towards the treasure
    if (level < 7) { ///check level of difficulty

        lcd.drawLine(42,0,42,4,1);
        lcd.drawLine(42,0,40,2,1);
        lcd.drawLine(42,0,44,2,1);
    } else if (level == 7) {

        lcd.printString("F",42,0); /// print the treasure icon
    } else if (level == 8) {

        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("Play again!",0,0);
        lcd.drawCircle(70,4,2,1);
        lcd.refresh();
        g_button_flag = 0;

        while(1) {
            if  (g_button1_flag) {

                g_button1_flag = 0;
                level = 0;
                // play++;
                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) {

        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(37,25,5,0);
        lcd.drawCircle(47,25,5,0);
        lcd.drawCircle(42,11,3,1);
        lcd.drawCircle(37,25,3,1);
        lcd.drawCircle(47,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);
        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.drawLine(50,15,30,15,1);
        lcd.drawLine(30,15,30,35,1);
        lcd.drawLine(30,25,45,25,1);
        */
    }
}


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

int 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) {
                option = 2;
            }
            if (option > 2) {
                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,3);
                                } 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,3);
                                }
                            } 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,3);
                                } 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,3);
                                }
                            }
                            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,27,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,3);
                                            } 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,3);
                                            } 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,3);
                                            }

                                            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,27,2,1);
                                            }

                                            if (g_button_flag) {
                                                g_button_flag = 0;

                                                if (option == 0) {
                                                    game_speed = 0.1;
                                                    speed = 0;
                                                } else if (option == 1) {
                                                    game_speed = 0.05;
                                                    speed = 1;
                                                } else if (option == 2) {
                                                    game_speed = 0.04;
                                                    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);
                                    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++) {
        for (int j=35+heroY; j<48+heroY; j++) {

            int check = intersection(i,j);
            //lcd.setPixel(i,j);
            char bit[50];
            sprintf(bit,"Pixels: %d",check);


            for(int i = 40; i < 50; i++) {
                for (int j = 35; j < 47; j++) {

                    if (lcd.getPixel(i,j) && check > 6) {
                        check = 6;
                    }
                }
            }
            if (check > 7) {
                tries--;
                //if tries

                lcd.printString("BANG!",0,0);
                lcd.refresh();
                wait(2);
                lcd.clear();

                if (tries == 2) {

                    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,2);
                    lcd.refresh();
                    wait(1);
                    lcd.clear();
                    fsm_state = 1; ///2 lives left
                } else if (tries == 1) {

                    lcd.clear();
                    lcd.printString("Last Chance!",10,2);
                    lcd.refresh();
                    wait(1);
                    fsm_state = 2; //1 life left
                } else if (tries == 0) {

                    fsm_state = 3;
                    led_output=fsm[fsm_state];
                    lcd.clear();
                    lcd.printString("Game Over!",10,2);
                    lcd.refresh();
                    wait(2);

                    ticker.detach();
                    game_ticker.attach(&game_timer_isr,0.2);
                    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) {

                            g_button1_flag = 0;
                            level = 0;
                            tries = 3;
                            fsm_state = 0;
                            led_output=fsm[fsm_state];
                            lcd.clear();
                            heroX = 0;
                            heroY = 0;
                            rectY = 0;
                            circleX = 0;
                            main();
                        }
                        sleep();
                    }

                }
                heroX = 0;
                heroY = 0;
                rectY = 0;
                circleX = 0;
                led_output=fsm[fsm_state];
            }

        }
    }
}

void error()
{
    /// display error message
    while (1) {

        lcd.printString("Error!",0,0);
        r_led = 0;
        wait(0.2);
        r_led = 1;
        wait(0.2);
    }
}