ELEC2645 Embedded Systems Project (JOYSTICK)

Dependencies:   N5110 SDFileSystem mbed

main.cpp

Committer:
wuchyi
Date:
2016-05-07
Revision:
4:f17082a43006
Parent:
2:537b8388dc6a

File content as of revision 4:f17082a43006:


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

#include "main.h"

int main()
{
    Butt1.rise(butt1_isr); ///initializes the buttons IntterruptIn
    Butt1.mode(PullDown);
    Butt2.rise(butt2_isr);
    Butt2.mode(PullDown);
    init_display();
    joystickTimer.attach(joystick_pos,0.1);
    calibrate_joystick();
    gamemode = 0;
    LED = 0;
    level = 2.0; ///default level
    levelcalc = 0.4; /// default speed
    main_menu();
}

void init_display()
{
    lcd.init();
    lcd.normalMode();      /// normal colour mode
    lcd.setBrightness(0.5); /// put LED backlight on 50%
    lcd.clear(); /// clear screen (init)
}


void draw_screen()
{
    lcd.clear();

    lcd.drawRect(0,1,83,45,0);    /// borders square

    for (int q = 0; q < snake.length ; q++) { ///print snake
        
        lcd.drawRect ((snake.tailx[q]*2),(snake.taily[q]*2),1,1,1);

    }
    
    lcd.drawRect ((fx * 2), (fy * 2), 1,1,1); /// print food position
    
    lcd.refresh();  /// update display

}


void calibrate_joystick()
{
    ///get initial joystick position as offset
    joystick.x0 = xAxis;
    joystick.y0 = yAxis;

}

void joystick_pos()
{
    joystick.x = xAxis - joystick.x0;
    joystick.y = yAxis - joystick.y0;

    if ( fabs(joystick.y) <= JOYSTICK_TOLERANCE && fabs(joystick.x) < JOYSTICK_TOLERANCE) {
        joystick.direction = CENTRE;
    } else if ( joystick.y > JOYSTICK_TOLERANCE && fabs(joystick.x) < JOYSTICK_TOLERANCE) {
        joystick.direction = UP;
    } else if ( joystick.y < JOYSTICK_TOLERANCE && fabs(joystick.x) < JOYSTICK_TOLERANCE) {
        joystick.direction = DOWN;
    } else if ( joystick.x > JOYSTICK_TOLERANCE && fabs(joystick.y) < JOYSTICK_TOLERANCE) {
        joystick.direction = RIGHT;
    } else if ( joystick.x < JOYSTICK_TOLERANCE && fabs(joystick.y) < JOYSTICK_TOLERANCE) {
        joystick.direction = LEFT;
    } else {
        joystick.direction = UNKNOWN;
    }

}


void snake_move() ///move the coordinate of the snake head, if CENTRE, checks for pdirection and repeats.
{
    if (pdirection == 0 && ( joystick.direction == RIGHT || joystick.direction == UNKNOWN ) ) { /// disable going backwards
        snake.hx--;
    } else if (pdirection == 1 && ( joystick.direction == DOWN || joystick.direction == UNKNOWN ) ) {
        snake.hy++;
    } else if (pdirection == 2 && ( joystick.direction == LEFT || joystick.direction == UNKNOWN ) ) {
        snake.hx++;
    } else if (pdirection == 3 && ( joystick.direction == UP || joystick.direction == UNKNOWN ) ) {
        snake.hy--;
    } else {

        if (joystick.direction == CENTRE) {
            if (pdirection == 0)  {
                snake.hx-- ;
            } else if (pdirection == 1) {
                snake.hy++ ;
            } else if (pdirection == 2) {
                snake.hx++ ;
            } else if (pdirection == 3) {
                snake.hy-- ;
            } else {
            }
        } else {
            if (joystick.direction == LEFT)  {
                snake.hx-- ;
                pdirection = 0;
            } else if (joystick.direction == UP) {
                snake.hy++ ;
                pdirection = 1;
            } else if (joystick.direction == RIGHT) {
                snake.hx++ ;
                pdirection = 2;
            } else if (joystick.direction == DOWN) {
                snake.hy-- ;
                pdirection = 3;
            } else if (joystick.direction == UNKNOWN) {
            } else {
            }

        }
    }
}

void game()
{

    joystickTimer.detach();
    gameTimer.detach();
    gameTimer1.detach();
    gameTimer2.detach();
    joystick.direction = CENTRE;
    gamemode = 0;
    gameOver = false;
    snake.hx = width / 2; /// initial position of snake head
    snake.hy = height / 2;
    food_pos();
    score = 0;
    pdirection = 1;
    snake.length = 4; ///length including head and tail
    for (int w = 0 ; w < snake.length  ; w++) { ///set initial snake position
        snake.tailx[w] = (snake.hx - w) ;
        snake.taily[w] = snake.hy;

    }

    if (gamemode == 0) {
        joystickTimer.attach(&joystick_pos, 0.1);
        gameTimer1.attach(&snake_logic_1, levelcalc);
        gameTimer2.attach(&draw_screen, 0.1);

        while (!gameOver) {
            butt2_flag = 0;
            sleep();

            if (butt2_flag == 1) {
                butt2_flag = 0;
                gameTimer1.detach();
                gameTimer2.detach();
                gamePaused_screen();
            }

        }
        if (gameOver == true) {
            gameTimer1.detach();
            gameTimer2.detach();
            gameOver_screen();
        }
    }
}

void snake_logic_1()
{

    snake_move();
    for (int d = (snake.length) ; d > 0 ; d--) { ///move all snake body one position back
        snake.tailx[d] = snake.tailx[d - 1];
        snake.taily[d] = snake.taily[d - 1];

    }
    snake.tailx[0] = snake.hx;
    snake.taily[0] = snake.hy;

    for (int p = 1; p < snake.length + 1; p++) { ///snake dies when come in contact with tail
        if (snake.tailx[0] == snake.tailx[p] && snake.taily[0] == snake.taily[p]) {
            gameOver = true;
        }


    }

    if (snake.tailx[0] == 0 || 
        snake.tailx[0] == width || 
        snake.taily[0] == 1 || 
        snake.taily[0] == height) { /// snake dies when hit wall
        gameOver = true;
    }


    if (snake.tailx[0] == fx && snake.taily[0] == fy) { // snake grows when in contact with food
        score++;
        food_pos();
        snake.length++;
    }
}


void food_pos()
{
    srand(time(NULL));
    fx = rand() % (width - 3) + 2; // random x from 4 to width - 3 for x coordinate
    fy = rand() % (height - 3) + 2; // random y from 4 to height - 3 for y coordinate

}

void main_menu()
{
    lcd.clear();
    joystickTimer.detach();
    gameTimer1.detach();
    gameTimer2.detach();
    joystickTimer.attach(joystick_pos,0.15);
    butt1_flag = 0;
    int select = 0;
    while (1) {
        switch(select) {
            case 0:
                switch(joystick.direction) {
                    case UP:
                        select = 1;
                        break;
                    case DOWN:
                        select = 2;
                        break;
                }
                break;
            case 1:
                switch(joystick.direction) {
                    case UP:
                        select = 2;
                        break;
                    case DOWN:
                        select = 0;
                        break;
                }
                break;
            case 2:
                switch(joystick.direction) {
                    case UP:
                        select = 0;
                        break;
                    case DOWN:
                        select = 1;
                        break;
                }
                break;
        }
        wait(0.1);
        if (select == 0) {
            lcd.clear();
            lcd.printString("SNAKE",27,0);
            lcd.printString("Start Game",7,2);
            lcd.printString("High Scores",7,3);
            lcd.printString("Settings",7,4);
            lcd.drawCircle(3,19,2,1);
            lcd.refresh();
            wait(0.15);
            if (butt1_flag == 1) {
                butt1_flag = 0;
                joystickTimer.detach();
                game();
            }
        } else if (select == 1) {
            lcd.clear();
            lcd.printString("SNAKE",27,0);
            lcd.printString("Start Game", 7,2);
            lcd.printString("High Scores",7,3);
            lcd.printString("Settings",7,4);
            lcd.drawCircle(3,27,2,1);
            lcd.refresh();
            wait(0.15);
            if (butt1_flag == 1) {
                butt1_flag = 0;
                HiScoreScreen();
            }
        } else if (select == 2) {
            lcd.clear();
            lcd.printString("SNAKE",27,0);
            lcd.printString("Start Game", 7,2);
            lcd.printString("High Scores",7,3);
            lcd.printString("Settings",7,4);
            lcd.drawCircle(3,35,2,1);
            lcd.refresh();
            wait(0.15);
            if (butt1_flag == 1) {
                butt1_flag = 0;
                settingsScreen();
            }


        }
    }
}

void HiScoreScreen()
{
    lcd.clear();
    fp = fopen("/sd/hiscore.txt","r");
    while (butt2_flag == 0) {

        if (fp == NULL) { /// if high scores file not found
            lcd.printString("High Scores:", 9,0);

            lcd.printString("No high", 21,3);
            lcd.printString("scores found",9,4);

            sleep();

            fclose(fp);
        } else {
            lcd.printString("High Scores:", 9,0);
            lcd.printString("Level 1:", 9,1);
            lcd.printString("Level 2:", 9,2);
            lcd.printString("Level 3:", 9,3);
            lcd.printString("Level 4:", 9,4);
            lcd.printString("Level 5:", 9,5);

            int o; ///index of file
            while (fscanf(fp, "%d,%d \n", &level_array[o],&HiScoreTable[o]) != EOF) {
                o++;
            }

            for (int lvl2 = 0; lvl2 <5 ; lvl2++) {
                char lvlscore[14]; ///char to print highscore
                sprintf(lvlscore,"%d",HiScoreTable[lvl2]); ///print highscore to char
                lcd.printString ( lvlscore, 64, (lvl2+1)); ///print highscore on screen
            }
        }
        fclose(fp);
        lcd.refresh();
        sleep();

    }

    if (butt2_flag == 1) {
        butt2_flag = 0;
        main_menu();
        butt1_flag = 0;
    }



}

void settingsScreen()
{
    lcd.clear();
    lcd.printString("Settings",18,0);
    int levelsel = 2;
    while (butt2_flag == 0) {
        switch(levelsel) {
            case 1:
                switch(joystick.direction) {
                    case RIGHT:
                        level = 2.0;
                        levelsel = 2;
                        break;
                    case LEFT:
                        level = 5.0;
                        levelsel = 5;
                        break;
                }
                break;
            case 2:
                switch(joystick.direction) {
                    case RIGHT:
                        level = 3.0;
                        levelsel = 3;
                        break;
                    case LEFT:
                        level = 1.0;
                        levelsel = 1;
                        break;
                }
                break;
            case 3:
                switch(joystick.direction) {
                    case RIGHT:
                        level = 4.0;
                        levelsel = 4;
                        break;
                    case LEFT:
                        level = 2.0;
                        levelsel = 2;
                        break;
                }
                break;
            case 4:
                switch(joystick.direction) {
                    case RIGHT:
                        level = 5.0;
                        levelsel = 5;

                        break;
                    case LEFT:
                        level = 3.0;
                        levelsel = 3;
                }
                break;
            case 5:
                switch(joystick.direction) {
                    case RIGHT:
                        level = 1.0;
                        levelsel = 1;
                        break;
                    case LEFT:
                        level = 4.0;
                        levelsel = 4;
                        break;
                }
                break;
        }

        if (level == 1) {
            lcd.printString("Level: < 1 >",6,3);
            levelcalc = 0.4;
            lcd.refresh();
            sleep();
        } else if (level == 2) {
            lcd.printString("Level: < 2 >",6,3);
            levelcalc = 0.33;
            lcd.refresh();
            sleep();
        } else if (level == 3) {
            lcd.printString("Level: < 3 >",6,3);
            levelcalc = 0.25;
            lcd.refresh();
            sleep();
        } else if (level == 4) {
            lcd.printString("Level: < 4 >",6,3);
            levelcalc = 0.15;
            lcd.refresh();
            sleep();
        } else if (level == 5) {
            lcd.printString("Level: < 5 >",6,3);
            levelcalc = 0.1;
            lcd.refresh();
            sleep();
        }

    }

    if (butt2_flag == 1) {
        butt2_flag = 0;
        lcd.clear();
        butt1_flag = 0;
        main_menu();
    }
}

void gameOver_screen()
{
    gameTimer1.detach();
    gameTimer2.detach();

    while (butt2_flag == 0) {
        fp = fopen("/sd/hiscore.txt","r"); //read high score
        wait(0.5);
        lcd.clear();

        lcd.printString("Game Over",15,1);
        char scorebuffer[14];
        int length = sprintf(scorebuffer, "Score = %d",score);
        if (length <=14) {
            lcd.printString(scorebuffer,12,2);
        }

        if (fp == NULL) { ///if high score file doesnt exist
            fp = fopen("/sd/hiscore.txt","w"); /// create new high score
            for (int lvl = 1; lvl < 6; lvl ++) { ///prints all level score as zero (initialize)
                fprintf(fp,"%d,0 \n", lvl);
            }
            fprintf(fp,"%d,%d \n", level, score); /// print the score of the current game according to level

            lcd.printString("New Highscore!",0,4);
            fclose(fp);
            sleep();

            if (butt2_flag == 1) {
                butt2_flag = 0;
                main_menu();
                gameTimer1.detach();
                gameTimer2.detach();
                butt1_flag = 0;
            }

        } else { /// if file exists
            rewind(fp);
            int o; ///index of file, just for counter
            while (fscanf(fp, "%d, %d \n", &level_array[o],&HiScoreTable[o]) != EOF) { //read file data into array
                o++;
            }

            if (score > HiScoreTable[(level - 1)]) { ///if current score is higher than HiScore(current level)
                lcd.printString("New Highscore!",0,4);

                HiScoreTable[(level - 1)] = score; ///save high score in table
            }


            fp = fopen("/sd/hiscore.txt","w"); /// overwrite score file
            for (int b = 0; b < 5; b++) { ///write table to SD file
                fprintf(fp, "%d,%d \n",b,HiScoreTable[b]);
                fclose(fp);
                sleep();
            }

            if (butt2_flag == 1) {
                butt2_flag = 0;
                main_menu();
                gameTimer1.detach();
                gameTimer2.detach();
                butt1_flag = 0;
            }
        }

    }
}

void gamePaused_screen()
{
    while(butt2_flag == 0) {
        gameTimer1.detach();
        gameTimer2.detach();
        LED = 1; /// toggle LED to show game is paused
        butt2_flag = 0;
        lcd.drawRect (4,4,74,38,2);
        lcd.drawRect (4,4,74,38,0);
        lcd.printString ("Game Paused",8,1);
        lcd.printString ("Press button",6,3);
        lcd.printString ("to unpause.",9,4);
        sleep();
    }
    if (butt2_flag == 1) {
        butt2_flag = 0;
        lcd.clear();
        draw_screen();
        wait(0.5);
        gameTimer1.attach(&snake_logic_1,(levelcalc));
        gameTimer2.attach(&draw_screen, 0.1);
        LED = 0;
    }

}


void butt1_isr()
{
    butt1_flag = 1;
}

void butt2_isr()
{
    butt2_flag = 1;
}