el15mh 200929957

Dependencies:   mbed

Revision:
9:960dfc71c224
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Menu/Menu.cpp	Thu May 04 14:43:29 2017 +0000
@@ -0,0 +1,1385 @@
+#include "Menu.h"
+
+// constructor function used when object is initialised
+Menu::Menu()
+{
+    
+}
+
+// destructor function
+Menu::~Menu()
+{
+    
+}
+
+/**
+ * @details - Initiases the game with default parameters before value specification
+*/
+void Menu::init()
+{
+    // set all default game parameters
+    _difficulty = 1;
+    _FPS = 50;
+    
+    _control = true;
+    _colour = true;
+    _tone = true;
+}
+
+/**
+ * @details - Main menu function.
+
+ */
+void Menu::main(N5110 &lcd, Gamepad &pad, FXOS8700CQ &device, Animations &animate)
+{
+    int selected = 0;
+    
+    while(1) {
+        
+        pad.leds_off();
+        
+        char d = pad.get_direction();
+        
+        if ((d == NW) ||
+            (d == N)  ||
+            (d == NE)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected -= 1;
+        }
+        
+        if ((d == SW) ||
+            (d == S)  ||
+            (d == SE)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected += 1;
+        }
+        
+        // lcd.printString("Testing", 0, 2);
+        switch (selected) {
+                
+            case 1:
+                
+                lcd.clear();
+                lcd.printString(" ROLLER MAZE ", 0, 0);
+                lcd.printString(">Play game", 0, 2);
+                lcd.printString(" Game options", 0, 3);
+                lcd.printString(" LCD settings", 0, 4);
+                lcd.printString(" Sound", 0, 5);
+                lcd.refresh();
+                
+                // either clicking joystick or pressing A selects function
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    playGame(lcd, pad, device, animate, _difficulty, _tone, _FPS);
+                    // call the game function
+                }
+                
+                wait_ms(250);    // 250ms propogation delay
+                
+                break;
+                
+            case 2:
+                
+                lcd.clear();
+                lcd.printString(" ROLLER MAZE ", 0, 0);
+                lcd.printString(" Play game", 0, 2);
+                lcd.printString(">Game options", 0, 3);
+                lcd.printString(" LCD settings", 0, 4);
+                lcd.printString(" Sound", 0, 5);
+                lcd.refresh();
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    options(lcd, pad, animate, _tone);
+                }
+                
+                wait_ms(250);    // 250ms propogation delay
+                
+                break;
+                
+            case 3:
+                
+                lcd.clear();
+                lcd.printString(" ROLLER MAZE ", 0, 0);
+                lcd.printString(" Play game", 0, 2);
+                lcd.printString(" Game options", 0, 3);
+                lcd.printString(">LCD settings", 0, 4);
+                lcd.printString(" Sound", 0, 5);
+                lcd.refresh();
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    lcdSettings(lcd, pad, animate);
+                }
+                
+                wait_ms(250);    // 250ms propogation delay
+                
+                break;
+                
+            case 4:
+                
+                lcd.clear();
+                lcd.printString(" ROLLER MAZE ", 0, 0);
+                lcd.printString(" Play game", 0, 2);
+                lcd.printString(" Game options", 0, 3);
+                lcd.printString(" LCD settings", 0, 4);
+                lcd.printString(">Sound", 0, 5);
+                lcd.refresh();
+                
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    soundSettings(lcd, pad, animate);
+                }
+                
+                wait_ms(250);    // 250ms propogation delay
+                
+                break;
+                
+            default:
+                
+                selected = 1;
+                
+                break;
+        }
+        
+        // printf("Joystick position = %c \n", d);
+        // printf("Selected = %i \n", selected);
+        
+    }
+}
+
+/**
+ * @details - Game introduction function.
+ */
+void Menu::intro(N5110 &lcd, Gamepad &pad, Animations &animate)
+{
+    // printf("intro started \n");
+    while (pad.check_event(Gamepad::START_PRESSED) == false){
+        
+        animate.intro(lcd, pad);
+    }
+}
+
+/**
+ * @details - Game Loop function.
+ */
+void Menu::playGame(N5110 &lcd,
+                    Gamepad &pad,
+                    FXOS8700CQ &device,
+                    Animations &animate,
+                    int difficulty,
+                    bool tone,
+                    float FPS)
+{
+    int x;
+    int y;
+    int radius;
+    
+    _mazeIndex = randomMazeIndexGenerator(_difficulty);
+    // generates random number for maze index between different
+    // pairs of values with corresponding difficulties
+    
+    _FPS = 100 - FPS;
+    // from game speed fuction (line , low FPS value corresponds to fast gameplay
+    // so perform basic inversion (works when value is between 25 - 75)
+    
+    if (difficulty == 1) {
+        
+        x = 5; // place ball in appropriate location for each difficulty
+        y = 5;
+        radius = 2; // set radius accordingly
+    }
+    
+    else if (difficulty == 2){
+        
+        x = 3;
+        y = 4;
+        radius = 1;
+    }
+    
+    else if (difficulty == 3){
+        
+        x = 5;
+        y = 3;
+        radius = 0;
+    }
+    
+    else {
+        
+        x = 2;
+        y = 2;
+        radius = 0;
+    }
+    
+    // now initialise game with correct game parameters for chosen difficulty
+    
+    _engine.init(_mazeIndex,    // selects maze difficulty
+                 x,             // defines starting x position for ball
+                 y,             // defines starting y position for ball
+                 radius,        // radius of ball
+                 _control,      // control method
+                 _colour);      // type of ball
+    
+    printGameParameters(_mazeIndex,
+                        x,
+                        y,
+                        radius,
+                        _control,
+                        _colour,
+                        _FPS);  // prints all game settings to serial port
+    
+    int exit = 0;
+    while (exit == 0){
+        
+        _engine._goal = false;
+        
+        // rendering screen
+        lcd.clear();
+        _engine.draw(lcd);
+        lcd.refresh();
+        
+        _engine.readInput(pad, device);
+        _engine.update(lcd);
+        
+        wait_ms(_FPS);
+        
+        if (_engine.checkGoal()){
+            
+            animateStickman(lcd, pad, animate);
+            exit ++;
+        }
+        
+        // get direction of the joystick
+        char d = pad.get_direction();
+        if  (pad.check_event(Gamepad::BACK_PRESSED)){
+            
+            exit++;
+        }
+    }
+}
+
+/**
+ * @details - Returns a random number between two set values
+ */
+int Menu::randomMazeIndexGenerator(int difficulty)
+{
+    // generates a random number between a pair of values
+    // based on the difficulty level chosen
+    
+    _difficulty = difficulty;
+    
+    if (_difficulty == 1) {
+        
+        _mazeIndex = rand() % 3;    // random number between 0 and 2
+    }
+    
+    else if (difficulty == 2){
+        
+        _mazeIndex = rand() % 3 + 3; // random number between 3 and 5
+    }
+    
+    else if (difficulty == 3){
+        
+        _mazeIndex = rand() % 3 + 6; // random number between 6 and 8
+    }
+    
+    else {
+        
+        _mazeIndex = 9; // no random number as only one maze at this level
+    }
+    
+    return _mazeIndex;
+}
+
+/**
+ * @details - Prints all chosen game parameters to serial port - used mostly for debugging.
+ */
+void Menu::printGameParameters(int mazeIndex,
+                               int x,
+                               int y,
+                               int radius,
+                               bool control,
+                               bool colour,
+                               float FPS)
+{
+    int _x = x;
+    int _y = y;
+    int _radius = radius;
+    bool _control = control;
+    bool _colour = colour;
+    float _fps = FPS;
+    
+    // printf out all game parameters
+    printf("Game parameters: \n");
+    printf("Difficulty = %i \n", _difficulty);
+    printf("Maze Index = %i \n", _mazeIndex);
+    printf("Ball position = (%i, %i)\n", _x, _y);
+    printf("Ball radius = %i \n", _radius);
+    printf("Game speed = %f \n", _fps);
+    
+    if (_colour){
+        printf("Ball colour: outline \n");
+    }
+    if (!_colour){
+        printf("Ball colour: black \n");
+    }
+    if (_control){
+        printf("Control method: Joystick \n");
+    }
+    if (!_control){
+        printf("Control method: Accelerometer \n");
+    }
+    printf("\n\n ---NEW LINE---\n\n");
+    
+}
+
+/**
+ * @details - Game Options Function to allow user to choose game style.
+ */
+void Menu::options(N5110 &lcd, Gamepad &pad, Animations &animate, bool tone)
+{
+    int exit = 0;
+    int selected = 0;
+    wait_ms(250);
+    
+    while(exit == 0) {
+        
+        // get direction of the joystick
+        char d = pad.get_direction();
+        
+        if ((d == NW) ||
+            (d == N)  ||
+            (d == NE)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected -= 1;
+        }
+        
+        if ((d == SW) ||
+            (d == S)  ||
+            (d == SE)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected += 1;
+        }
+        
+        // printf("While loop 1 \n");
+        // printf("Selected = %i \n", selected);
+        switch (selected) {
+                
+            case 1:
+                
+                lcd.clear();
+                // displays options page with indicator on first
+                lcd.printString("Game Options:", 0, 0);
+                lcd.printString(">Difficulty", 0, 2);
+                lcd.printString(" Ball Colour", 0, 3);
+                lcd.printString(" Control", 0, 4);
+                lcd.printString(" Game speed  ", 0, 5);
+                lcd.refresh();
+                
+                wait_ms(250);
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    difficultyOptions(lcd, pad);
+                }
+                
+                
+                break;
+                
+            case 2:
+                
+                lcd.clear();
+                // displays options page with indicator on second
+                lcd.printString("Game Options:", 0, 0);
+                lcd.printString(" Difficulty", 0, 2);
+                lcd.printString(">Ball Colour", 0, 3);
+                lcd.printString(" Control", 0, 4);
+                lcd.printString(" Game speed  ", 0, 5);
+                lcd.refresh();
+                
+                wait_ms(250);
+                
+                // if second option selected
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    ballColourOptions(lcd, pad, animate);
+                }
+                
+                
+                break;
+                
+            case 3:
+                
+                lcd.clear();
+                // displays options page with indicator on first
+                lcd.printString("Game Options:", 0, 0);
+                lcd.printString(" Difficulty", 0, 2);
+                lcd.printString(" Ball Colour", 0, 3);
+                lcd.printString(">Control", 0, 4);
+                lcd.printString(" Game speed  ", 0, 5);
+                lcd.refresh();
+                
+                wait_ms(250);
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    controlOptions(lcd, pad, animate);
+                }
+                
+                
+                break;
+                
+            case 4:
+                
+                lcd.clear();
+                // displays options page with indicator on first
+                lcd.printString("Game Options:", 0, 0);
+                lcd.printString(" Difficulty", 0, 2);
+                lcd.printString(" Ball Colour", 0, 3);
+                lcd.printString(" Control", 0, 4);
+                lcd.printString(">Game speed  ", 0, 5);
+                lcd.refresh();
+                
+                wait_ms(250);
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    speedSettings(lcd, pad);
+                }
+                
+                
+                break;
+                
+                
+                
+            default:
+                
+                selected = 1;
+                
+                break;
+        }
+        
+        if ((pad.check_event(Gamepad::BACK_PRESSED)) ||
+            (d == W)){
+            
+            exit++;
+        }
+    }
+}
+
+/**
+ * @details - LCD Settings Function to allow user to alter appearance of game on LCD.
+ */
+void Menu::lcdSettings(N5110 &lcd, Gamepad &pad, Animations &animate)
+{
+    int exit = 0;
+    int selected = 0;
+    wait_ms(250);
+    
+    while(exit == 0) {
+        
+        char d = pad.get_direction();
+        
+        if ((d == NW) ||
+            (d == N)  ||
+            (d == NE)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected -= 1;
+        }
+        
+        if ((d == SW) ||
+            (d == S)  ||
+            (d == SE)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected += 1;
+        }
+        
+        // printf("While loop 1 \n");
+        // printf("Selected = %i \n", selected);
+        switch (selected) {
+                
+            case 1:
+                
+                lcd.clear();
+                // displays options page with indicator on first
+                lcd.printString("LCD Settings:", 0, 0);
+                lcd.printString(">Brightness", 0, 2);
+                lcd.printString(" Invert Colour", 0, 3);
+                lcd.refresh();
+                
+                wait_ms(250);
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    lcdBackgroundColour(lcd, pad, animate);
+                }
+                
+                break;
+                
+            case 2:
+                
+                lcd.clear();
+                // displays options page with indicator on second
+                lcd.printString("LCD Settings:", 0, 0);
+                lcd.printString(" Brightness", 0, 2);
+                lcd.printString(">Invert Colour", 0, 3);
+                lcd.refresh();
+                
+                wait_ms(250);
+                
+                // if second option selected
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    lcdInverseColour(lcd, pad);
+                }
+                
+                break;
+                
+            default:
+                
+                selected = 1;
+                
+                break;
+        }
+        
+        if ((pad.check_event(Gamepad::BACK_PRESSED)) ||
+            (d == W)){
+            
+            exit++;
+        }
+        
+    }
+    
+    
+}
+
+/**
+ * @details - Sound Settings to allow user to turn sound on or off
+ */
+void Menu::soundSettings(N5110 &lcd, Gamepad &pad, Animations &animate)
+{
+    int exit = 0;
+    
+    while (exit == 0){
+        
+        // animate.soundSwitch(lcd, _tone);
+        
+        char d = pad.get_direction();
+        
+        if (d == E){
+            
+            _tone = false;
+        }
+        
+        if (d == W){
+            
+            _tone = true;
+            pad.tone(G_NOTE, 0.20);
+            
+        }
+        
+        lcd.clear();
+        // draw casing rectangle
+        lcd.drawRect(33, 27, 17, 9, FILL_TRANSPARENT);
+        
+        lcd.printString("Sound Settings", 0, 0);
+        lcd.printString("  ON     OFF  ", 0, 2);
+        
+        // casing rectangle is filled in one side
+        // depending on value of _tone
+        if (_tone){
+            lcd.drawRect(34, 28, 7, 7, FILL_BLACK);
+        }
+        else {
+            lcd.drawRect(42, 28, 7, 7, FILL_BLACK);
+        }
+        
+        lcd.refresh();
+        
+        wait_ms(10);
+        
+        
+        if ((pad.check_event(Gamepad::BACK_PRESSED)) ||
+            (pad.check_event(Gamepad::A_PRESSED))){
+            
+            if (_tone){
+                pad.tone(C_NOTE, 0.20);
+            }
+            exit++;
+        }
+    }
+    
+}
+
+/**
+ * @details - Control Options Function which allows user select control technique.
+ */
+void Menu::controlOptions(N5110 &lcd, Gamepad &pad, Animations &animate)
+{
+    int selected = 0;
+    int exit = 0;
+    
+    wait_ms(250);
+    
+    while (exit == 0){
+        
+        char d = pad.get_direction();
+        
+        if (d == W){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected--;
+        }
+        
+        if (d == E){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected++;
+        }
+        
+        switch(selected){
+                
+            case 1:
+                
+                lcd.clear();
+                lcd.printString("Control: ", 0, 0);
+                lcd.printString("   Joystick   ", 0, 2);
+                lcd.printString("             >", 0, 3);
+                animate.drawVerticalJoystick(lcd);
+                lcd.refresh();
+                
+                wait_ms(250);
+                
+                if (pad.check_event(Gamepad::A_PRESSED)||
+                    pad.check_event(Gamepad::JOY_PRESSED)){
+                    
+                    _control = true;
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    
+                    animateJoystick(lcd, animate);
+                    exit++;
+                }
+                
+                break;
+                
+                
+            case 2:
+                
+                lcd.clear();
+                lcd.printString("Control: ", 0, 0);
+                lcd.printString("   Gamepad    ", 0, 2);
+                lcd.printString("<             ", 0, 3);
+                animate.drawVerticalGamepad(lcd);
+                lcd.refresh();
+                
+                wait_ms(250);
+                
+                if (pad.check_event(Gamepad::A_PRESSED)||
+                    pad.check_event(Gamepad::JOY_PRESSED)){
+                    
+                    _control = false;
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    
+                    animateGamepad(lcd, animate);
+                    exit++;
+                }
+                
+                break;
+                
+            default:
+                
+                selected = 1;
+                
+                break;
+                
+        }
+        
+        if (pad.check_event(Gamepad::BACK_PRESSED)){
+            
+            exit++;
+        }
+        
+    }
+}
+
+/**
+ * @details - Difficulty Options Function to allow player to select difficulty level.
+ */
+void Menu::difficultyOptions(N5110 &lcd, Gamepad &pad)
+{
+    int selected = 0;
+    int exit = 0;
+    wait_ms(250);
+    
+    while(exit == 0){
+        
+        char d = pad.get_direction();
+        
+        if ((d == NW) ||
+            (d == N)  ||
+            (d == NE)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected -= 1;
+        }
+        
+        if ((d == SW) ||
+            (d == S)  ||
+            (d == SE)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected += 1;
+        }
+        
+        switch(selected){
+                
+            case 1:
+                
+                lcd.clear();
+                lcd.printString("Difficulty: ", 0, 0);
+                lcd.printString(">Easy", 0, 2);
+                lcd.printString(" Medium", 0, 3);
+                lcd.printString(" Hard", 0, 4);
+                lcd.printString(" Extreme", 0, 5);
+                lcd.refresh();
+                
+                wait_ms(250);   // 250ms propogation delay
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    _difficulty = 1;
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    
+                    lcd.clear();
+                    lcd.printString("     EASY", 0, 1);
+                    lcd.printString("     MODE", 0, 2);
+                    lcd.refresh();
+                    wait(2);
+                    
+                    exit++;
+                }
+                
+                break;
+                
+            case 2:
+                
+                lcd.clear();
+                lcd.printString("Difficulty: ", 0, 0);
+                lcd.printString(" Easy", 0, 2);
+                lcd.printString(">Medium", 0, 3);
+                lcd.printString(" Hard", 0, 4);
+                lcd.printString(" Extreme", 0, 5);
+                lcd.refresh();
+                
+                wait_ms(250);   // 250ms propogation delay
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    _difficulty = 2;
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    
+                    lcd.clear();
+                    lcd.printString("    MEDIUM", 0, 1);
+                    lcd.printString("     MODE", 0, 2);
+                    lcd.refresh();
+                    wait(2);
+                    
+                    exit++;
+                }
+                
+                break;
+                
+            case 3:
+                
+                lcd.clear();
+                lcd.printString("Difficulty: ", 0, 0);
+                lcd.printString(" Easy", 0, 2);
+                lcd.printString(" Medium", 0, 3);
+                lcd.printString(">Hard       ", 0, 4);
+                lcd.printString(" Extreme     ", 0, 5);
+                lcd.refresh();
+                
+                wait_ms(250);   // 250ms propogation delay
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    _difficulty = 3;
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    
+                    lcd.clear();
+                    lcd.printString("     HARD", 0, 1);
+                    lcd.printString("     MODE", 0, 2);
+                    lcd.refresh();
+                    wait(2);
+                    
+                    exit++;
+                }
+                
+                break;
+                
+            case 4:
+                
+                lcd.clear();
+                lcd.printString(" Easy", 0, 1);
+                lcd.printString(" Medium", 0, 2);
+                lcd.printString(" Hard", 0, 3);
+                lcd.printString(">Extreme", 0, 4);
+                lcd.refresh();
+                
+                
+                wait_ms(250);   // 250ms propogation delay
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    _difficulty = 4;
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    
+                    lcd.clear();
+                    lcd.printString("    EXTREME   ", 0, 1);
+                    lcd.printString("     MODE", 0, 2);
+                    lcd.refresh();
+                    wait(2);
+                    
+                    exit++;
+                }
+                
+                break;
+                
+            default:
+                
+                selected = 1;
+                
+                break;
+                
+        }
+        
+        if ((pad.check_event(Gamepad::BACK_PRESSED)) ||
+            (d == W)){
+            
+            exit++;
+        }
+    }
+}
+
+/**
+ * @details - Ball colour function to select the style of ball used in the game.
+ */
+void Menu::ballColourOptions(N5110 &lcd, Gamepad &pad, Animations &animate)
+{
+    int selected = 0;
+    int exit = 0;
+    wait_ms(250);
+    
+    while(exit == 0){
+        
+        char d = pad.get_direction();
+        
+        if ((d == NW) ||
+            (d == N)  ||
+            (d == NE)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected -= 1;
+        }
+        
+        if ((d == SW) ||
+            (d == S)  ||
+            (d == SE)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            selected += 1;
+        }
+        
+        switch(selected){
+                
+            case 1:
+                
+                // printf("case 2.1");
+                
+                lcd.clear();
+                lcd.printString("Ball colour: ", 0, 0);
+                lcd.printString(">Outline", 0, 2);
+                lcd.printString(" Solid", 0, 3);
+                lcd.refresh();
+                
+                wait_ms(250);   // 250ms propogation delay
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    
+                    _colour = true;     // true colour => outline
+                    animate.rollingEmptyBall(lcd);
+                    exit++;
+                }
+                
+                break;
+                
+            case 2:
+                
+                // printf("case 2.2");
+                
+                lcd.clear();
+                lcd.printString("Ball colour: ", 0, 0);
+                lcd.printString(" Outline", 0, 2);
+                lcd.printString(">Solid", 0, 3);
+                lcd.refresh();
+                
+                wait_ms(250);   // 250ms propogation delay
+                
+                
+                if  ((pad.check_event(Gamepad::A_PRESSED)     ||
+                      pad.check_event(Gamepad::JOY_PRESSED))  ||
+                     (d == E)) {
+                    
+                    if (_tone){
+                        pad.tone(C_NOTE, 0.20);
+                    }
+                    
+                    _colour = false;    // false colour => solid
+                    animate.rollingSolidBall(lcd);
+                    exit++;
+                }
+                
+                break;
+                
+            default:
+                
+                selected = 1;
+                
+                break;
+        }
+        
+        if ((pad.check_event(Gamepad::BACK_PRESSED)) ||
+            (d == W)){
+            
+            exit++;
+        }
+    }
+    
+    
+}
+
+/**
+ * @details - LCD Inverse Colour function which allows user to switch colours on the LCD.
+ */
+void Menu::lcdInverseColour(N5110 &lcd, Gamepad &pad)
+{
+    int exit = 0;
+    
+    while (exit == 0) {
+        
+        lcd.clear();
+        lcd.printString("Press A to", 0, 0);
+        lcd.printString("invert colours", 0, 1);
+        lcd.printString("Press B to", 0, 3);
+        lcd.printString("revert to", 0, 4);
+        lcd.printString("normal", 0, 5);
+        
+        if (pad.check_event(Gamepad::A_PRESSED)){
+            
+            lcd.inverseMode();
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            
+        }
+        
+        if (pad.check_event(Gamepad::B_PRESSED)){
+            
+            lcd.normalMode();
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+        }
+        
+        lcd.refresh();
+        
+        char d = pad.get_direction();
+        
+        if ((pad.check_event(Gamepad::BACK_PRESSED)) ||
+            (d == W)){
+            
+            exit++;
+        }
+    }
+    
+    
+}
+
+/**
+ * @details - LCD Inverse Colour function which changes the PWM value of the LCD backlight LED.
+ */
+void Menu::lcdBackgroundColour(N5110 &lcd, Gamepad &pad, Animations &animate)
+{
+    // method to change the brightness of the LED backlight
+    int exit = 0;
+    
+    while (exit == 0) {
+        
+        lcd.clear();
+        lcd.printString("BRIGHTNESS", 0, 0);
+        lcd.printString("Use DIAL --->", 0, 1);
+        lcd.printString("to adjust", 0, 2);
+        
+        double brightness = pad.read_pot(); // returns value between 0.0 - 1.0
+        
+        lcd.setBrightness(brightness);
+        
+        lcd.drawRect(10, 30, 41, 8, FILL_TRANSPARENT);
+        lcd.drawRect(11, 31, brightness * 40, 6, FILL_BLACK);
+        lcd.refresh();
+        
+        // animate.brightnessBar(lcd, brightness);
+        lcd.refresh();
+        
+        wait_ms(5);
+        
+        char d = pad.get_direction();
+        
+        if ((pad.check_event(Gamepad::BACK_PRESSED)) ||
+            (d == W)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            exit++;
+        }
+    }
+}
+
+/**
+ * @details - Game Speed function which changes the FPS used in the game loop.
+ */
+void Menu::speedSettings(N5110 &lcd, Gamepad &pad)
+{
+    int exit = 0;
+    
+    while (exit == 0){
+        
+        lcd.clear();
+        lcd.printString("Use dial to   ", 0, 0);
+        lcd.printString("adjust speed", 0, 1);
+        
+        double speed = pad.read_pot();  // returns value between 0.0 - 1.0
+        
+        // nominal value is 50 FPS, i.e speed of 0.5
+        // have values between 25 and 75
+        
+        // pot value of 0 corresponds to FPS of 25
+        // pot value of 1 cooresponds to FPS of 75
+        
+        // relationship between pot value and FPS:
+        _FPS = (speed * 50) + 25;
+        
+        // lcd.drawRect(10, 30, 41, 8, FILL_TRANSPARENT);
+        // lcd.drawRect(11, 31, _FPS, 6, FILL_BLACK);
+        
+        lcd.drawCircle(42, 31, 12, FILL_TRANSPARENT);
+        
+        // printf("input = %f \n", input);
+        
+        double x2 = 42 + (12 * sin(1.5 * 3.14159 * (speed - 0.5)));
+        double y2 = 31 - (12 * cos(1.5 * 3.14159 * (speed - 0.5)));
+        
+        lcd.drawLine(42, 31, x2, y2, FILL_BLACK);
+        
+        lcd.refresh();
+        
+        wait_ms(5);
+        
+        char d = pad.get_direction();
+        
+        if ((pad.check_event(Gamepad::BACK_PRESSED)) ||
+            (d == W)){
+            
+            if (_tone){
+                pad.tone(G_NOTE, 0.20);
+            }
+            exit++;
+        }
+    }
+}
+
+/**
+ * @details - Animate Joystick function creats a short animation of moving joystick.
+ */
+void Menu::animateJoystick(N5110 &lcd, Animations &animate)
+{
+    int timer = 0;
+    while (timer <= 3200){
+        
+        lcd.clear();
+        lcd.printString("   JOYSTICK   ", 0, 1);
+        lcd.printString("   SELECTED   ", 0, 2);
+        animate.drawLeftJoystick(lcd);
+        lcd.refresh();
+        timer += 400;
+        wait_ms(400);
+        
+        lcd.clear();
+        lcd.printString("   JOYSTICK   ", 0, 1);
+        lcd.printString("   SELECTED   ", 0, 2);
+        animate.drawVerticalJoystick(lcd);
+        lcd.refresh();
+        timer += 400;
+        wait_ms(400);
+        
+        lcd.clear();
+        lcd.printString("   JOYSTICK   ", 0, 1);
+        lcd.printString("   SELECTED   ", 0, 2);
+        animate.drawRightJoystick(lcd);
+        lcd.refresh();
+        timer += 400;
+        wait_ms(400);
+        
+        lcd.clear();
+        lcd.printString("   JOYSTICK   ", 0, 1);
+        lcd.printString("   SELECTED   ", 0, 2);
+        animate.drawVerticalJoystick(lcd);
+        lcd.refresh();
+        timer += 400;
+        wait_ms(400);
+    }
+}
+
+/**
+ * @details - Animate Gamepad function creats a short animation of moving gamepad.
+ */
+void Menu::animateGamepad(N5110 &lcd, Animations &animate)
+{
+    int timer = 0;
+    while (timer <= 3200){
+        
+        lcd.clear();
+        lcd.printString(" GAMEPAD TILT ", 0, 1);
+        lcd.printString("   SELECTED   ", 0, 2);
+        animate.drawLeftGamepad(lcd);
+        lcd.refresh();
+        timer += 400;
+        wait_ms(400);
+        
+        lcd.clear();
+        lcd.printString(" GAMEPAD TILT ", 0, 1);
+        lcd.printString("   SELECTED   ", 0, 2);
+        animate.drawVerticalGamepad(lcd);
+        lcd.refresh();
+        timer += 400;
+        wait_ms(400);
+        
+        
+        lcd.clear();
+        lcd.printString(" GAMEPAD TILT ", 0, 1);
+        lcd.printString("   SELECTED   ", 0, 2);
+        animate.drawRightGamepad(lcd);
+        lcd.refresh();
+        timer += 400;
+        wait_ms(400);
+        
+        lcd.clear();
+        lcd.printString(" GAMEPAD TILT ", 0, 1);
+        lcd.printString("   SELECTED   ", 0, 2);
+        animate.drawVerticalGamepad(lcd);
+        lcd.refresh();
+        timer += 400;
+        wait_ms(400);
+    }
+}
+
+/**
+ * @details - Animate Stickman function creates a short animation of jumping man to signify goal reached.
+ */
+void Menu::animateStickman(N5110 &lcd, Gamepad &pad, Animations &animate)
+{
+    int timer = 0;
+    while (timer <= 3200){
+        
+        int delay = 60;
+        
+        lcd.clear();
+        animate.stickmanOne(lcd);
+        pad.leds_on();
+        lcd.refresh();
+        timer += delay;
+        wait_ms(delay);
+        
+        lcd.clear();
+        animate.stickmanTwo(lcd);
+        pad.leds_off();
+        lcd.refresh();
+        timer += delay;
+        wait_ms(delay);
+        
+        lcd.clear();
+        animate.stickmanThree(lcd);
+        pad.leds_on();
+        lcd.refresh();
+        timer += delay;
+        wait_ms(delay);
+        
+        lcd.clear();
+        animate.stickmanFour(lcd);
+        pad.leds_off();
+        lcd.refresh();
+        timer += delay;
+        wait_ms(delay);
+        
+        lcd.clear();
+        animate.stickmanFive(lcd);
+        pad.leds_on();
+        lcd.refresh();
+        timer += delay;
+        wait_ms(delay);
+        
+        lcd.clear();
+        animate.stickmanSix(lcd);
+        pad.leds_off();
+        lcd.refresh();
+        timer += delay;
+        wait_ms(delay);
+        
+        lcd.clear();
+        animate.stickmanFive(lcd);
+        pad.leds_on();
+        lcd.refresh();
+        timer += delay;
+        wait_ms(delay);
+        
+        lcd.clear();
+        animate.stickmanFour(lcd);
+        pad.leds_off();
+        lcd.refresh();
+        timer += delay;
+        wait_ms(delay);
+        
+        lcd.clear();
+        animate.stickmanThree(lcd);
+        pad.leds_on();
+        lcd.refresh();
+        timer += delay;
+        wait_ms(delay);
+        
+        lcd.clear();
+        animate.stickmanTwo(lcd);
+        pad.leds_off();
+        lcd.refresh();
+        timer += delay;
+        wait_ms(delay);
+        
+    }
+    
+}
+
+