ELEC2645 Embedded Systems Project (JOYSTICK)

Dependencies:   N5110 SDFileSystem mbed

Revision:
2:537b8388dc6a
Parent:
1:06958b7bbf65
Child:
4:f17082a43006
--- a/main.cpp	Thu May 05 15:03:15 2016 +0000
+++ b/main.cpp	Sat May 07 14:35:21 2016 +0000
@@ -1,99 +1,27 @@
-/*
-Progress update:
-Easter -- Added ticker for joystick update
-            joystick initial position checker
-
-week 22 -- main logic behind snake game added
-            to do : wraparound (optional in main menu)
-                    menu system - play game, settings(joy calibration, wraparound on//off) ; game over screen
-*/
-
-
-#include "mbed.h"
-#include "N5110.h"
-#include "SDFileSystem.h"
-#define JOYSTICK_TOLERANCE 0.1 //direction tolerance of joystick
-
-//          VCC,    SCE,  RST,    D/C,   MOSI,  SCLK,   LED
-N5110 lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3);
-SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd");
-
-void init_display();
-void draw_screen();
-void calibrate_joystick();
-void joystick_pos();
-void game_timer_isr();
-void food_pos();
-void snake_move();
-void snake_logic_1();
-float refresh_rate = 10; //refresh screen in Hz
-volatile int g_timer_flag = 0;
-bool gameOver; //if game has ended
-int pdirection;
-int gamemode;
-
-const int width = (84 - 2) / 2 ; // screen width (playable area due to 2x size of snake)
-const int height = (48 - 4) / 2 ; // screen height
+#include "main.h"
 
-Ticker gameTimer;
-Ticker gameTimer1;
-Ticker gameTimer2;
-Ticker joystickTimer; // ticker timer for joystick poisition update
-int fx,fy,Button,score; // global variables to hold data (control)
-AnalogIn xAxis(A0);
-AnalogIn yAxis(A1);
-AnalogIn pot(A2);
-DigitalOut red_led(LED_RED);
-
-
-
-enum DirectionName { //joystick directions
-    CENTRE,
-    UP,
-    LEFT,
-    DOWN,
-    RIGHT,
-    UNKNOWN
-};
-
-;
-// struct for joystick
-typedef struct joystick1 Joystick;
-struct joystick1 {
-    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
-};
-
-Joystick joystick;
-
-typedef struct snake1 Snake;
-struct snake1 {
-    int hx; // head x value
-    int hy; // head y value
-    int length; // snake length
-    int tailx[100],taily[100]; //tail coordinates array
-};
-
-Snake snake;
-
-
+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 adjust_brightness()
-{
-    int x = pot;
-    lcd.setBrightness(x);
+    lcd.normalMode();      /// normal colour mode
+    lcd.setBrightness(0.5); /// put LED backlight on 50%
+    lcd.clear(); /// clear screen (init)
 }
 
 
@@ -101,29 +29,24 @@
 {
     lcd.clear();
 
-    lcd.drawRect(0,1,83,45,0);    // borders square
+    lcd.drawRect(0,1,83,45,0);    /// borders square
 
-    for (int q = 0; q < snake.length ; q++) { //print snake
-        //lcd.setPixel (snake.tailx[q],snake.taily[q]);
+    for (int q = 0; q < snake.length ; q++) { ///print snake
+        
         lcd.drawRect ((snake.tailx[q]*2),(snake.taily[q]*2),1,1,1);
-        // red_led = 0;
 
     }
-    //lcd.setPixel(snake.hx,snake.hy); //print snake head position
-    lcd.drawRect ((fx * 2), (fy * 2), 1,1,1);
-    //lcd.setPixel (fx,fy); //print food position
-    lcd.refresh();  // update display
+    
+    lcd.drawRect ((fx * 2), (fy * 2), 1,1,1); /// print food position
+    
+    lcd.refresh();  /// update display
 
 }
 
-void game_timer_isr()
-{
-    g_timer_flag = 1;
-}
 
 void calibrate_joystick()
 {
-    //get initial joystick position as offset
+    ///get initial joystick position as offset
     joystick.x0 = xAxis;
     joystick.y0 = yAxis;
 
@@ -151,16 +74,15 @@
 }
 
 
-void snake_move() //move the coordinate of the snake head, if CENTRE, checks for pdirection and repeats.
+void snake_move() ///move the coordinate of the snake head, if CENTRE, checks for pdirection and repeats.
 {
-    // red_led = 0;
-    if (pdirection == 0 && joystick.direction == RIGHT) { // disable going backwards
+    if (pdirection == 0 && ( joystick.direction == RIGHT || joystick.direction == UNKNOWN ) ) { /// disable going backwards
         snake.hx--;
-    } else if (pdirection == 1 && joystick.direction == DOWN) {
+    } else if (pdirection == 1 && ( joystick.direction == DOWN || joystick.direction == UNKNOWN ) ) {
         snake.hy++;
-    } else if (pdirection == 2 && joystick.direction == LEFT) {
+    } else if (pdirection == 2 && ( joystick.direction == LEFT || joystick.direction == UNKNOWN ) ) {
         snake.hx++;
-    } else if (pdirection == 3 && joystick.direction == UP) {
+    } else if (pdirection == 3 && ( joystick.direction == UP || joystick.direction == UNKNOWN ) ) {
         snake.hy--;
     } else {
 
@@ -188,6 +110,7 @@
             } else if (joystick.direction == DOWN) {
                 snake.hy-- ;
                 pdirection = 3;
+            } else if (joystick.direction == UNKNOWN) {
             } else {
             }
 
@@ -197,170 +120,442 @@
 
 void game()
 {
-    //brightnessTimer.attach(adjust_brightness,0.1);
+
     joystickTimer.detach();
     gameTimer.detach();
     gameTimer1.detach();
     gameTimer2.detach();
     joystick.direction = CENTRE;
-    // gamemode = 0;
+    gamemode = 0;
     gameOver = false;
-    snake.hx = width / 2; // initial position of snake head
+    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.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;
 
     }
-    //draw_screen();
-
-
-
 
     if (gamemode == 0) {
+        joystickTimer.attach(&joystick_pos, 0.1);
+        gameTimer1.attach(&snake_logic_1, levelcalc);
+        gameTimer2.attach(&draw_screen, 0.1);
+
         while (!gameOver) {
-            joystickTimer.attach(&joystick_pos, 0.1);
-            // gameTimer.attach(&snake_move,0.2);
-            gameTimer1.attach(&snake_logic_1,0.1);
-            gameTimer2.attach(&draw_screen, 0.1);
+            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() {
-//red_led = 0;
-        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;
-        //  snake.hx = snake.tailx[0];
-        // snake.hy = snake.taily[0];
+void snake_logic_1()
+{
 
-        // snake_move();
-        // draw_screen();
+    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];
 
-        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;
-                red_led = 0;
-            }
+    }
+    snake.tailx[0] = snake.hx;
+    snake.taily[0] = snake.hy;
 
-
-
-        }
-
-        if (snake.tailx[0] == 0 || snake.tailx[0] == width || snake.taily[0] == 1 || snake.taily[0] == height-1) {
+    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] == fx && snake.taily[0] == fy) { // snake grows when in contact with food
-            score++;
-            food_pos();
-            snake.length++;
-            // draw_screen();
+    }
+
+    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;
         }
-        //snake_move();
+        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 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 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();
+        }
 
     }
 
-    void main_menu() {
-        //brightnessTimer.attach(adjust_brightness,0.1);
-        joystickTimer.attach(joystick_pos,0.1);
-        int select = 0;
-        while (1) {
-            switch(select) {
-                case 0:
-                    switch(joystick.direction) {
-                        case UP:
-                            select = 1;
-                            break;
-                        case DOWN:
-                            select = 1;
-                            break;
-                    }
-                    break;
-                case 1:
-                    switch(joystick.direction) {
-                        case UP:
-                            select = 0;
-                            break;
-                        case DOWN:
-                            select = 0;
-                            break;
-                    }
-                    break;
+    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);
             }
-            wait(0.1);
-            if (select == 0) {
-                lcd.clear();
-                lcd.printString("Start Game",7,0);
-                lcd.printString("Settings",7,1);
-                lcd.drawCircle(3,3,2,1);
-                lcd.refresh();
-            } else if (select == 1) {
-                lcd.clear();
-                lcd.printString("Start Game", 7,0);
-                lcd.printString("Settings",7,1);
-                lcd.drawCircle(3,11,2,1);
-                lcd.refresh();
+            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;
     }
 
-    int main() {
-        init_display();
-        //brightnessTimer.attach(adjust_brightness,0.1);
-        joystickTimer.attach(joystick_pos,0.1);
-        calibrate_joystick();
-        gamemode = 0;
-        //lcd.printString("Hello, World!",0,0);
-        //main_menu();
-        red_led = 1;
-        game();
-        /*while(1) {
-
-            lcd.clear();
-            if (joystick.direction == UP) {
-                lcd.printString ("UP",1,0);
-            } else if (joystick.direction == CENTRE) {
-                lcd.printString ("CENTRE",1,0);
-           } else if (joystick.direction == DOWN) {
-                lcd.printString ("DOWN",1,0);
-            } else if (joystick.direction == LEFT) {
-                lcd.printString ("LEFT",1,0);
-            } else if (joystick.direction == RIGHT) {
-                lcd.printString ("RIGHT",1,0);
-            } else {
-                lcd.printString ("UNKNOWN",1,0);
-            }
-            lcd.refresh();
-            wait(1);
-        }
-        */
+}
 
 
-    }
+void butt1_isr()
+{
+    butt1_flag = 1;
+}
+
+void butt2_isr()
+{
+    butt2_flag = 1;
+}