A retro gaming programme, designed for use on a portable embedded system. Incorporates power saving techniques.

Dependencies:   ConfigFile N5110 PowerControl beep mbed

Revision:
53:a3077af736bb
Parent:
52:bb2acf0e248a
Child:
54:8180eec1656d
--- a/main.cpp	Thu Apr 30 19:57:59 2015 +0000
+++ b/main.cpp	Thu Apr 30 19:59:54 2015 +0000
@@ -12,6 +12,1170 @@
 #include <ctime>
 #include <cstdlib>
 
+//struct for choosing initials
+struct State {
+    char output1;
+    char output2;
+    char output3;
+    int nextState[2];
+};
+
+//assigns new identifier to struct
+typedef const struct State STYP;
+
+//output array for struct Alphabet
+STYP fsm[27] = {
+    //output//nextstate//previousstate//
+    {'A','A','A',{1,26}},
+    {'B','B','B',{2,0}},
+    {'C','C','C',{3,1}},
+    {'D','D','D',{4,2}},
+    {'E','E','E',{5,3}},
+    {'F','F','F',{6,4}},
+    {'G','G','G',{7,5}},
+    {'H','H','H',{8,6}},
+    {'I','I','I',{9,7}},
+    {'J','J','J',{10,8}},
+    {'K','K','K',{11,9}},
+    {'L','L','L',{12,10}},
+    {'M','M','M',{13,11}},
+    {'N','N','N',{14,12}},
+    {'O','O','O',{15,13}},
+    {'P','P','P',{16,14}},
+    {'Q','Q','Q',{17,15}},
+    {'R','R','R',{18,16}},
+    {'S','S','S',{19,17}},
+    {'T','T','T',{20,18}},
+    {'U','U','U',{21,19}},
+    {'V','V','V',{22,20}},
+    {'W','W','W',{23,21}},
+    {'X','X','X',{24,22}},
+    {'Y','Y','Y',{25,23}},
+    {'Z','Z','Z',{26,24}},
+    {'.','.','.',{0,25}},
+};
+
+//timer to read the joystick
+Ticker pollJoystick;
+
+//serial out for debug
+Serial serial(USBTX,USBRX);
+
+//create enumerated type (0,1,2,3 etc. for direction)
+//could be extended for diagonals etc.
+enum DirectionName {
+    UP,
+    DOWN,
+    LEFT,
+    RIGHT,
+    CENTRE,
+    UNKNOWN
+
+};
+
+//struct for Joystick
+typedef struct JoyStick Joystick;
+struct JoyStick {
+    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
+};
+
+//create struct variable
+Joystick joystick;
+
+//if buttonA set flag A
+void timerExpiredA()
+{
+    if(buttonA == 1) {
+        buttonFlagA = 1;
+        serial.printf("flagA set\n");
+    }
+}
+
+//if buttonB set flag B
+void timerExpiredB()
+{
+    if(buttonB == 1) {
+        buttonFlagB = 1;
+        serial.printf("flagB set\n");
+    }
+}
+
+//set seed/randomise initial co-Ordinates
+void randomise()
+{
+    srand (time(NULL));//initial seed for randomisation
+
+    //initial random x co-ordinates
+    //for falling hazards
+    //(values between 3 and 76)
+    randX1 = rand() % 74 + 5;
+    randX2 = rand() % 74 + 5;
+    randX3 = rand() % 74 + 5;
+    randX4 = rand() % 74 + 5;
+    randX5 = rand() % 74 + 5;
+    randX6 = rand() % 74 + 5;
+}
+
+//static background
+void drawBackground()
+{
+    //x, y, w, h, fill - draw ground
+    lcd.drawRect(0,47,84,0,1);
+    //x, y, w, h, fill - draw left wall
+    lcd.drawRect(2,0,0,47,1);
+    //left wall - brick line 1
+    lcd.drawLine(1,1,1,48,2);
+    //left wall - brick line 2
+    lcd.drawLine(0,0,0,48,2);
+
+    //x, y, w, h, fill - draw right wall
+    lcd.drawRect(81,0,0,47,1);
+    //right wall - brick line 1
+    lcd.drawLine(82,0,82,48,2);
+    //right wall - brick line 2
+    lcd.drawLine(83,1,83,48,2);
+
+    lcd.refresh();
+}
+
+//intro screen
+void drawWelcome()
+{
+    //bottom border
+    lcd.drawRect(0,44,84,2,1);
+    //top border
+    lcd.drawRect(0,1,84,2,1);
+    lcd.refresh();
+
+    //print initials 'DRT'
+    lcd.printChar('D',30,2);
+    wait(0.6);
+    lcd.printChar('R',37,2);
+    wait(0.6);
+    lcd.printChar('T',44,2);
+    wait(0.6);
+
+    //print 'presents...'
+    lcd.printString("presents...",8,3);
+    wait(1.0);
+
+    //dramatic flashing
+    buzzer.beep(5000,0.3);
+    lcd.inverseMode();
+    wait(0.2);
+    lcd.normalMode();
+    wait(0.2);
+    buzzer.beep(5000,0.3);
+    lcd.inverseMode();
+    wait(0.2);
+    lcd.normalMode();
+    wait(1.0);
+
+    //more dramatic flashing
+    buzzer.beep(5000,0.3);
+    lcd.inverseMode();
+    wait(0.2);
+    lcd.normalMode();
+    wait(0.2);
+    buzzer.beep(5000,0.3);
+    lcd.inverseMode();
+    wait(0.2);
+    lcd.normalMode();
+    wait(0.6);
+}
+
+//pixel ninja character
+void drawNinja()
+{
+    //x, y, w, h, fill - left leg
+    lcd.drawRect(a1,39,0,7,1);
+    //right leg
+    lcd.drawRect(a2,39,0,7,1);
+    //centre stick
+    lcd.drawRect(a3,37,0,7,1);
+    //back of the head
+    lcd.drawRect(a1,33,0,4,1);
+    //top of the head
+    lcd.drawRect(a1,33,4,0,1);
+    //jaw
+    lcd.drawRect(a2,38,2,0,1);
+    //right shoulder
+    lcd.drawRect(a4,40,1,0,1);
+    //left shoulder
+    lcd.drawRect(a5,40,1,0,1);
+    //left arm
+    lcd.drawRect(a5,41,0,1,1);
+    //right arm
+    lcd.drawRect(a6,41,0,1,1);
+    //right eye
+    lcd.drawRect(a6,35,0,0,1);
+    //mouth piece
+    lcd.drawRect(a6,37,0,0,1);
+    //left eye
+    lcd.drawRect(a2,35,0,0,1);
+    //sword handle
+    lcd.drawRect(a7,36,0,0,1);
+    lcd.drawRect(a5,37,0,0,1);
+    lcd.drawRect(a8,38,0,0,1);
+
+    lcd.refresh();
+}
+
+//stops ninja going through walls
+void ninjaBoundaries()
+{
+    if(a6 > 79 )
+        a6 = 79;
+    if(a4 > 78)
+        a4 = 78;
+    if(a2 > 77)
+        a2 = 77;
+    if(a3 > 76)
+        a3 = 76;
+    if(a1 > 75)
+        a1 = 75;
+    if(a8 > 74)
+        a8 = 74;
+    if(a5 > 73)
+        a5 = 73;
+    if(a7 > 72)
+        a7 = 72;
+
+    if(a6 < 11 )
+        a6 = 11;
+    if(a4 < 10)
+        a4 = 10;
+    if(a2 < 9)
+        a2 = 9;
+    if(a3 < 8)
+        a3 = 8;
+    if(a1 < 7)
+        a1 = 7;
+    if(a8 < 6)
+        a8 = 6;
+    if(a5 < 5)
+        a5 = 5;
+    if(a7 < 4)
+        a7 = 4;
+}
+
+//resets variables initial values when game ends or is exited
+void resetGame()
+{
+    score = 0;
+
+    a1 = 22;
+    a2 = 24;
+    a3 = 23;
+    a4 = 25;
+    a5 = 20;
+    a6 = 26;
+    a7 = 19;
+    a8 = 21;
+
+    //in this case the X values are given a
+    //new random variable each time the player
+    //dies, exits or starts a new game
+    randX1 = rand() % 74 + 5;
+    randX2 = rand() % 74 + 5;
+    randX3 = rand() % 74 + 5;
+    randX4 = rand() % 74 + 5;
+    randX5 = rand() % 74 + 5;
+    randX6 = rand() % 74 + 5;
+
+    randY1 = 0;
+    randY2 = 0;
+    randY3 = 0;
+    randY4 = 0;
+    randY5 = 0;
+    randY6 = 0;
+    lcd.clear();
+}
+
+//draws falling hazards
+void drawHazards()
+{
+    //X, Y, radius, fill
+    lcd.drawCircle(randX1,randY1,2,1);
+    lcd.drawCircle(randX2,randY2,2,1);
+    lcd.drawCircle(randX3,randY3,2,1);
+    lcd.drawCircle(randX4,randY4,2,1);
+    lcd.drawCircle(randX5,randY5,2,1);
+    lcd.drawCircle(randX6,randY6,2,1);
+
+    lcd.refresh();
+}
+
+//makes hazards fall - randomises X axis co-ordinates
+void hazardFall()
+{
+    //increments randY1 variables
+    //appearing to make them fall
+    randY1 = randY1 += fall;
+    randY2 = randY2 += fall;
+    randY3 = randY3 += fall;
+    randY4 = randY4 += fall;
+    randY5 = randY5 += fall;
+    randY6 = randY6 += fall;
+
+    //loops the objects once they 'hit the floor'
+    //this imitates a new set of objects falling
+
+    if (randY1>=48)
+        randY1=0;
+
+    if (randY2>=48)
+        randY2=0;
+
+    if (randY3>=48)
+        randY3=0;
+
+    if (randY4>=48)
+        randY4=0;
+
+    if (randY5>=48)
+        randY5=0;
+
+    //each time the objects loop, a new pseudo random value
+    //is assigned to the global variables (randX) to
+    //randomise their positions
+
+    if (randY6>=48) {
+        randY6=0;
+
+        score = score++;//increment score by 1 after each wave of hazards
+
+        randX1 = rand() % 74 + 5;//psuedo random number
+        randX2 = rand() % 74 + 5;//between 5 and 74
+        randX3 = rand() % 74 + 5;
+        randX4 = rand() % 74 + 5;
+        randX5 = rand() % 74 + 5;
+        randX6 = rand() % 74 + 5;
+    }
+}
+
+//clears old pixels and keeps set pixels
+void startrek()
+{
+    for (int i=3; i<81; i++)//loops through rows
+        for (int j=0; j<47; j++)
+            if (cells[i][j]) {//if there's a pixel then keep it
+                lcd.setPixel(i,j);
+            } else {
+                lcd.clearPixel(i,j);//else remove the old ones
+            }
+    lcd.refresh();
+}
+
+//clears old pixels and keeps set pixels
+void refreshCursor1()
+{
+    for (int i=70; i<80; i++)//loops through rows
+        for (int j=17; j<25; j++)
+            if (cells[i][j]) {//if there's a pixel then keep it
+                lcd.setPixel(i,j);
+            } else {
+                lcd.clearPixel(i,j);//else remove the old ones
+            }
+    lcd.refresh();
+}
+
+//clears old pixels and keeps set pixels
+void refreshCursor2()
+{
+    for (int i=70; i<80; i++)//loops through rows
+        for (int j=25; j<32; j++)
+            if (cells[i][j]) {//if there's a pixel then keep it
+                lcd.setPixel(i,j);
+            } else {
+                lcd.clearPixel(i,j);//else remove the old ones
+            }
+    lcd.refresh();
+}
+
+//clears old pixels and keeps set pixels
+void refreshCursor3()
+{
+    for (int i=70; i<80; i++)//loops through rows
+        for (int j=32; j<40; j++)
+            if (cells[i][j]) {//if there's a pixel then keep it
+                lcd.setPixel(i,j);
+            } else {
+                lcd.clearPixel(i,j);//else remove the old ones
+            }
+    lcd.refresh();
+}
+
+//beep/light when buttons are closed
+void actionButtons()
+{
+    if((FX == 0)&&(buttonA||buttonB)) {
+        ledA = 1;
+        buzzer.beep(1500,0.3);
+    }
+    if (buttonA || buttonB) {
+        ledA = 1;
+    } else {
+        ledA = 0;
+    }
+}
+
+//presents main menu options
+void mainMenu(int& mainOption)
+{
+    actionButtons();//set audible/light for button
+
+    //joystick selection
+    if (printFlag) {//if flag set, clear flag and print joystick values to serial port
+        printFlag = 0;
+
+        //option up
+        if (joystick.direction == UP) {
+            serial.printf(" UP\n");
+            mainOption = mainOption--;
+            if (mainOption < 0)mainOption = 0;
+        }
+        //option down
+        if (joystick.direction == DOWN) {
+            serial.printf(" DOWN\n");
+            mainOption = mainOption++;
+            if (mainOption > 2)mainOption = 2;
+        }
+        //Centre / Unknown orientation
+        if (joystick.direction == CENTRE)
+            serial.printf(" CENTRE\n");
+        if (joystick.direction == UNKNOWN)
+            serial.printf(" Unsupported direction\n");
+
+        //'Play Game' option 1
+        if (mainOption == 0) {
+            lcd.printString("Play Game",3,4);
+        }
+        //'High Scores' option 2
+        if (mainOption == 1) {
+            lcd.printString("  Scores ",3,4);
+        }
+        //'Options' option 3
+        if (mainOption == 2) {
+            lcd.printString(" Options ",3,4);
+        }
+    }
+}
+
+//draws main menu
+void drawMainMenu()
+{
+    //bottom border
+    lcd.drawRect(0,47,84,0,1);
+    //top border
+    lcd.drawRect(0,0,84,2,1);
+
+    //title outline
+    lcd.drawRect(3,6,77,10,0);
+
+////castle //x, y, w, h, fill//////////////////////
+
+    //castle main bulk
+    lcd.drawRect(59,32,21,8,1);
+
+    //left window bulk
+    lcd.drawRect(59,22,2,10,1);
+    //centre left window bulk
+    lcd.drawRect(65,22,2,10,1);
+    //centre right window bulk
+    lcd.drawRect(72,22,2,10,1);
+    //right window bulk
+    lcd.drawRect(78,22,2,10,1);
+    //central window bulk
+    lcd.drawRect(68,25,3,7,1);
+
+    //central window bulk
+    lcd.drawRect(75,28,0,0,1);
+    lcd.drawRect(77,28,0,0,1);
+    lcd.drawRect(64,28,0,0,1);
+    lcd.drawRect(62,28,0,0,1);
+
+    //above left window bulk
+    lcd.drawRect(62,25,3,2,1);
+    //above right window bulk
+    lcd.drawRect(75,25,2,2,1);
+
+    //lower right line
+    lcd.drawRect(71,42,9,0,1);
+    //upper right line
+    lcd.drawRect(70,41,10,0,1);
+
+    //upper left line
+    lcd.drawRect(59,41,10,0,1);
+    //lower left line
+    lcd.drawRect(59,42,9,0,1);
+
+    //bottom left bulk
+    lcd.drawRect(59,43,8,3,1);
+    //bottom right bulk
+    lcd.drawRect(72,43,8,3,1);
+
+    //option arrows - lower
+    lcd.drawRect(27,42,4,0,1);
+    lcd.drawRect(28,43,2,0,1);
+    lcd.drawRect(29,44,0,0,1);
+
+    //option arrows - higher
+    lcd.drawRect(27,29,4,0,1);
+    lcd.drawRect(28,28,2,0,1);
+    lcd.drawRect(29,27,0,0,1);
+
+    //print 'Xtreme Tower'
+    lcd.printString("Xtreme Tower",7,1);
+
+    lcd.refresh();
+}
+
+//presents exit menu options
+void exitMenu(int& exitOption)
+{
+    actionButtons();
+    if (printFlag) {//if flag set, clear flag and print joystick values to serial port
+        printFlag = 0;
+
+        //check joystick direction
+        if (joystick.direction == LEFT) {
+            serial.printf(" LEFT\n");
+            exitOption--;
+            if(exitOption < 0)exitOption = 0;
+        }
+        if (joystick.direction == RIGHT) {
+            serial.printf(" RIGHT\n");
+            exitOption++;
+            if(exitOption > 1)exitOption = 1;
+        }
+        if (joystick.direction == CENTRE)
+            serial.printf(" CENTRE\n");
+        if (joystick.direction == UNKNOWN)
+            serial.printf(" Unsupported direction\n");
+    }
+    //draws option cursor
+    if(exitOption == 0) {
+        lcd.printString("YES",33,3);
+    }
+    else if(exitOption == 1) {
+        lcd.printString(" NO",33,3);
+    }
+}
+
+//draws exit menu
+void drawExitMenu()
+{
+    //set exit menu
+    lcd.clear();
+    drawBackground();
+    lcd.printString("Exit Game?",14,1);
+
+    lcd.drawRect(8,3,70,30,0);//title outline
+    //option arrow - right
+    lcd.drawRect(55,25,0,4,1);
+    lcd.drawRect(56,26,0,2,1);
+    lcd.drawRect(57,27,0,0,1);
+
+    //option arrow - left//
+    lcd.drawRect(27,25,0,4,1);
+    lcd.drawRect(26,26,0,2,1);
+    lcd.drawRect(25,27,0,0,1);
+
+    lcd.refresh();
+}
+
+//presents the options
+void optionsMenu(int& option)
+{
+    //joystick selection
+    if (printFlag) {  //if flag set, clear flag and print joystick values to serial port
+        printFlag = 0;
+
+        //option up
+        if (joystick.direction == UP) {
+            serial.printf(" UP\n");
+            option = option--;
+            if (option < 0)option = 0;
+        }
+        //option down
+        if (joystick.direction == DOWN) {
+            serial.printf(" DOWN\n");
+            option = option++;
+            if (option > 1)option = 1;
+        }
+        //Centre / Unknown orientation
+        if (joystick.direction == CENTRE)
+            serial.printf(" CENTRE\n");
+        if (joystick.direction == UNKNOWN)
+            serial.printf(" Unsupported direction\n");
+
+        //'Difficulty' option 1
+        if (option == 0) {
+            lcd.drawCircle(72,27,2,1);
+            refreshCursor3();
+        }
+        //'Sound FX' option 2
+        if (option == 1) {
+            lcd.drawCircle(72,35,2,1);
+            refreshCursor2();
+        }
+    }
+
+    lcd.refresh();
+}
+
+//draws options menu
+void drawOptionsMenu()
+{
+    lcd.clear();//clear screen
+    drawBackground();
+    lcd.drawRect(3,6,77,10,0);//title outline
+    lcd.drawRect(0,47,84,0,1);//bottom border
+    lcd.drawRect(0,0,84,2,1);//top border
+    lcd.printString("Options",20,1);//title
+    lcd.printString("Difficulty",3,3);
+    lcd.printString("Sound FX",3,4);
+
+    lcd.refresh();
+}
+
+//present difficulty options
+void difficultyMenu(int& subOption)
+{
+    actionButtons();
+
+    //joystick selection
+    if (printFlag) {//if flag set, clear flag,print joystick values
+        printFlag = 0;
+
+        //option up
+        if (joystick.direction == UP) {
+            serial.printf(" UP\n");
+            subOption = subOption--;
+            if (subOption < 1)subOption = 1;
+        }
+        //option down
+        if (joystick.direction == DOWN) {
+            serial.printf(" DOWN\n");
+            subOption = subOption++;
+            if (subOption > 3)subOption = 3;
+        }
+        //Centre / Unknown orientation
+        if (joystick.direction == CENTRE)
+            serial.printf(" CENTRE\n");
+        if (joystick.direction == UNKNOWN)
+            serial.printf(" Unsupported direction\n");
+
+        //'Easy' option 1
+        if (subOption == 1) {
+            lcd.drawCircle(72,19,2,1);
+            refreshCursor2();
+            refreshCursor3();
+            if(buttonFlagA) { //select easy
+                buttonFlagA = 0;
+                fall = 1;
+            }
+        }
+        //'Normal' option 2
+        if (subOption == 2) {
+            lcd.drawCircle(72,27,2,1);
+            refreshCursor1();
+            refreshCursor3();
+
+            if(buttonFlagA) { //select normal
+                buttonFlagA = 0;
+                fall = 2;
+            }
+        }
+        //'Forget It' option 3
+        if (subOption == 3) {
+            lcd.drawCircle(72,35,2,1);
+            refreshCursor1();
+            refreshCursor2();
+
+            if(buttonFlagA) { //select difficult
+                buttonFlagA = 0;
+                fall = 3;
+            }
+        }
+    }
+
+    lcd.refresh();
+}
+
+//draw difficulty settings
+void drawDifficultyMenu()
+{
+    lcd.clear();
+    drawBackground();
+    lcd.drawRect(0,47,84,0,1);//bottom border
+    lcd.drawRect(0,0,84,2,1);//top border
+    lcd.refresh();
+    lcd.printString("*Difficulty*",5,1);//title
+    lcd.printString("Easy",5,2);//title
+    lcd.printString("Normal",5,3);//title
+    lcd.printString("Forget It",5,4);//title
+}
+
+//present sound FX options
+void soundFXMenu(int& fxOption)
+{
+    actionButtons();
+
+    //joystick selection
+    if (printFlag) {//if flag set, clear flag,print joystick values
+        printFlag = 0;
+
+        //option up
+        if (joystick.direction == UP) {
+            serial.printf(" UP\n");
+            fxOption = fxOption--;
+            if (fxOption < 0)fxOption = 0;
+        }
+        //option down
+        if (joystick.direction == DOWN) {
+            serial.printf(" DOWN\n");
+            fxOption = fxOption++;
+            if (fxOption > 1)fxOption = 1;
+        }
+        //Centre / Unknown orientation
+        if (joystick.direction == CENTRE)
+            serial.printf(" CENTRE\n");
+        if (joystick.direction == UNKNOWN)
+            serial.printf(" Unsupported direction\n");
+    }
+    //'ON' option 1
+    if (fxOption == 0) {
+        lcd.drawCircle(72,27,2,1);//draw cursor 'ON'
+        refreshCursor1();
+        refreshCursor3();
+
+        if(buttonFlagA) {
+            buttonFlagA =0;
+            FX = 0;
+            serial.printf("FX = %d\n",FX);
+        }
+    }
+    //'OFF' option 2
+    if (fxOption == 1) {
+        lcd.drawCircle(72,35,2,1);//draw cursor 'OFF'
+        refreshCursor1();
+        refreshCursor2();
+
+        if(buttonFlagA) {
+            buttonFlagA =0;
+            FX = 1;
+            serial.printf("FX = %d\n",FX);
+        }
+    }
+    lcd.refresh();
+}
+
+//draw Sound FX settings
+void drawSoundFXMenu()
+{
+    lcd.clear();
+    drawBackground();
+    lcd.drawRect(0,47,84,0,1);//bottom border
+    lcd.drawRect(0,0,84,2,1);//top border
+    lcd.printString("*Sound FX*",10,1);//title
+    lcd.printString("ON",35,3);//title
+    lcd.printString("OFF",33,4);//title
+    lcd.refresh();
+}
+
+//if any of the high scores are beaten, they are replaced.
+//player enters initials using structs outputs
+void newScore()
+{
+    if(score >= highScore3) {//entry condition
+        buttonFlagA = 0;//reset flags
+        buttonFlagB = 0;
+        lcd.clear();//clears screen
+        drawBackground();//draws background
+        lcd.printString("High Score!!",7,0);//title
+        lcd.printString("Enter ID",19,4);//title
+
+        int n;//local variable used for storing temporary global variable
+        int initial = 0;//used for isolating which initial is being selected
+        char x,y,z;
+
+        //print initial characters
+        x=fsm[state1].output1;
+        lcd.printChar(x,28,2);
+        y=fsm[state2].output2;
+        lcd.printChar(y,40,2);
+        z=fsm[state3].output3;
+        lcd.printChar(z,52,2);
+
+        while(1) {
+
+            //joystick selection
+            if (printFlag) {//if flag set, clear flag,print joystick values
+                printFlag = 0;
+
+                if(joystick.direction==CENTRE) {
+                    preDirection=0;
+                }
+                if (joystick.direction == UP ) {
+                    serial.printf(" UP\n");
+                    state1 = state1--;
+                    if (state1 < 0)state1 = 0;
+                    state2 = state2--;
+                    if (state2 < 0)state2 = 0;
+                    state3 = state3--;
+                    if (state3 < 0)state3 = 0;
+                }
+                //option down
+                if (joystick.direction == DOWN ) {
+                    serial.printf(" DOWN\n");
+                    state1 = state1++;
+                    if (state1 > 26)state1 = 26;
+                    state2 = state2++;
+                    if (state2 > 26)state2 = 26;
+                    state3 = state3++;
+                    if (state3 > 26)state3 = 26;
+                }
+                if (joystick.direction == LEFT && preDirection==0) {
+                    serial.printf(" LEFT\n");
+                    initial = initial--;
+                    if (initial < 0)initial = 0;
+                    preDirection=1;
+                }
+                if (joystick.direction == RIGHT && preDirection==0) {
+                    serial.printf(" RIGHT\n");
+                    initial = initial++;
+                    if (initial > 2)initial = 2;
+                    preDirection=1;
+                }
+                //Centre / Unknown orientation
+                if (joystick.direction == CENTRE)
+                    serial.printf(" CENTRE\n");
+                if (joystick.direction == UNKNOWN)
+                    serial.printf(" Unsupported direction\n");
+            }
+            //if initial 3 display selected character
+            if (initial == 0) {
+                x=fsm[state1].output1;
+                lcd.printChar(x,28,2);
+            }
+            //if initial 1 display selected character
+            if(initial == 1) {
+                y=fsm[state2].output2;
+                lcd.printChar(y,40,2);
+            }
+            //if initial 2 display selected character
+            if(initial == 2) {
+                z=fsm[state3].output3;
+                lcd.printChar(z,52,2);
+            }
+            if(buttonFlagA) {
+                actionButtons();
+                buttonFlagA = 0;
+                buttonFlagB = 0;
+                break;
+            }
+        }
+        //if player beats High Score 3, replace it with new score
+        if(score >= highScore3 && score<highScore2 ) {
+            highScore3 = score;
+            sprintf (player3initials, "3.%c%c%c.....%i",x,y,z,highScore3);
+        }
+        //if player beats High Score 3 and 2, replace HighScore2 with new score
+        if(score >= highScore2 && score< highScore1) {
+            highScore3 = highScore2;
+            n = score;
+            highScore2 = n;
+            sprintf (player3initials, "3.%c%c%c.....%i",player2initials[2],player3initials[3],player3initials[4],highScore3);
+            sprintf (player2initials, "2.%c%c%c.....%i",x,y,z,highScore2);
+        }
+        //if player beats High Score 1, 2 and 3, replace highScore1 with new score
+        if(score >= highScore1 ) {
+            highScore3 = highScore2;
+            highScore2 = highScore1;
+            n = score;
+            highScore1 = n;
+            sprintf (player3initials, "3.%c%c%c.....%i",player2initials[2],player3initials[3],player3initials[4],highScore3);
+            sprintf (player2initials, "2.%c%c%c.....%i",player1initials[2],player1initials[3],player1initials[4],highScore2);
+            sprintf (player1initials, "1.%c%c%c.....%i",x,y,z,highScore1);
+        }
+        state1 = 0;
+        state2 = 0;
+        state3 = 0;
+    }
+}
+
+//actual game
+void game(int& exitFlag, int& exitOption)
+{
+    actionButtons();
+    lcd.clear();//clears screen
+    drawBackground();//draw background
+
+    ///game///
+    while(1) {
+        //print score - top left of display
+        char buffer[14];//create buffer for string
+        int length = sprintf(buffer,"Level:%d",score);//insert buffer
+        lcd.printString(buffer,3,0);//display
+
+        actionButtons();
+        drawNinja();//set character
+        drawHazards();//initiates hazards
+        hazardFall();//increments hazards towards floor
+        wait(0.1);//slow down objects
+        
+        if (printFlag) {  //if flag set, clear flag and print joystick values to serial port
+            printFlag = 0;
+
+            //check joystick direction
+            if (joystick.direction == LEFT) {
+                serial.printf(" LEFT\n");
+                a1 = a1-=2;
+                a2 = a2-=2;
+                a3 = a3-=2;
+                a4 = a4-=2;
+                a5 = a5-=2;
+                a6 = a6-=2;
+                a7 = a7-=2;
+                a8 = a8-=2;
+                ninjaBoundaries();
+            }
+            if (joystick.direction == RIGHT) {
+                serial.printf(" RIGHT\n");
+                a1 = a1+=2;
+                a2 = a2+=2;
+                a3 = a3+=2;
+                a4 = a4+=2;
+                a5 = a5+=2;
+                a6 = a6+=2;
+                a7 = a7+=2;
+                a8 = a8+=2;
+                ninjaBoundaries();
+            }
+            if (joystick.direction == CENTRE)
+                serial.printf(" CENTRE\n");
+            if (joystick.direction == UNKNOWN)
+                serial.printf(" Unsupported direction\n");
+
+            //integer to represent character being
+            //struck by falling object
+            int contactPoint = 0;
+
+            //contact points
+            if(lcd.getPixel((a1+4),32))
+                contactPoint++;
+            if(lcd.getPixel((a1),32))
+                contactPoint++;
+            if(lcd.getPixel((a7),32))
+                contactPoint++;
+
+            //if contact point is not zero
+            //character has been hit
+            //and the game ends
+            if ( contactPoint !=0) {
+                lcd.printString("Game Over",17,2);
+                lcd.inverseMode();
+                buzzer.beep(2000,0.2);//frequeny/duration
+                wait(0.5);
+                lcd.normalMode();
+                wait(0.5);
+                lcd.inverseMode();
+                buzzer.beep(2000,0.2);
+                wait(0.5);
+                lcd.normalMode();
+                wait(0.5);
+                lcd.inverseMode();
+                buzzer.beep(2000,0.2);
+                wait(0.5);
+                lcd.normalMode();
+                newScore();//enter initial screen if previous scores are beaten
+                resetGame();//reset values
+                break;
+            }
+            lcd.refresh();//refresh screen
+            startrek();//clears unset pixels, keeps set pixels
+
+///Exit Menu (Back button pressed)///
+            if(buttonFlagB) {
+                buttonFlagB = 0;//reset flags
+                buttonFlagA = 0;
+                actionButtons();
+                drawExitMenu();//draws the exit menu
+
+                while(1) {
+                    exitMenu(exitOption);//presents exit options
+
+                    //'exit' option YES
+                    if((buttonFlagA)&&(exitOption == 0)) { //returns to menu
+                        exitOption = 1;//reset intial option value
+                        buttonFlagA = 0;//reset flags
+                        buttonFlagB = 0;
+                        actionButtons();
+                        lcd.clear();//clears screen
+                        resetGame();//resets scores/objects
+                        exitFlag = 1;//sets exit flag
+                        break;
+                    }
+                    //'exit' option NO - returns to game
+                    if((buttonFlagA)&&(exitOption == 1)) {
+                        buttonFlagA = 0;//resets flags
+                        buttonFlagB = 0;
+                        break;
+                    }
+                    sleep();//put while to sleep
+                }
+                //if 'exit' option YES, resets
+                //game values returns to main menu
+                if (exitFlag!=0) { //if exit flag set
+                    exitFlag = 0;//reset flag
+                    break;//break to main menu
+                }
+            }
+            serial.printf("Score: %i \n",score);//print Score for debug
+        }
+    }
+}
+
+//high scores screen
+void scores()
+{
+    actionButtons();
+    lcd.clear();//clear screen
+    drawBackground();//set background
+    lcd.printString("High Scores",10,0);//title
+
+    //prints scores with names
+    lcd.printString(player1initials,5,2);//display
+
+    lcd.printString(player2initials,5,3);//display
+
+    lcd.printString(player3initials,5,4);//display
+
+    while(1) {
+        actionButtons();//select
+
+        //back to menu
+        if(buttonFlagB) {
+            buttonFlagA = 0;//reset flags
+            buttonFlagB = 0;
+            lcd.clear();
+            break;
+        }
+        sleep();//put while to sleep
+    }
+}
+
+//options menu
+void optionsMenu()
+{
+    int option = 0;
+    int subOption = fall;//keeps cursor on selected option, even after exiting screen
+    int fxOption = 0;
+    actionButtons();
+    drawOptionsMenu();//draws options menu
+    //counters for navigation
+
+    while(1) {
+        actionButtons();
+        optionsMenu(option);//presents options
+
+//////////////////////difficulty menu ////////////////////////////////////
+        if ((option == 0)&&(buttonFlagA)) {
+            buttonFlagA = 0;//reset flag
+            actionButtons();
+            drawDifficultyMenu();//draws difficulty menu
+
+            while(1) {
+                actionButtons();
+                difficultyMenu(subOption);//presents difficulty options
+
+                if(buttonFlagB) {
+                    buttonFlagB = 0;//reset flags
+                    buttonFlagA = 0;
+                    lcd.clear();//clear screen
+                    break;//return back
+                }
+                sleep();//put while to sleep
+            }
+            drawOptionsMenu();
+        }
+/////////////////////sound FX menu //////////////////////////////////////
+        if((option ==1)&&(buttonFlagA)) {
+            buttonFlagA = 0;//reset flags
+            buttonFlagB = 0;
+            actionButtons();
+            drawSoundFXMenu();//draw menu
+
+            while(1) {
+                actionButtons();
+                soundFXMenu(fxOption);//presents options
+
+                //back to options menu
+                if(buttonFlagB) {
+                    buttonFlagB = 0;//reset flags
+                    buttonFlagA = 0;
+                    lcd.clear();//clear screen
+                    break;//return back
+                }
+                sleep();//put while to sleep
+            }
+            drawOptionsMenu();
+        }
+        //back to mainmenu
+        if(buttonFlagB) {
+            buttonFlagB = 0;//reset flags
+            buttonFlagA = 0;
+            lcd.clear();//clear
+            break;//return back
+        }
+        sleep();//put while to sleep
+    }
+}
+
+//read default positions of the joystick to calibrate later readings
+void calibrateJoystick()
+{
+    joyButton.mode(PullDown);
+    //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;
+}
+
+//reads and updates position of joystick according to voltage readings
+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 = joyButton;
+
+    //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 = DOWN;
+    } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
+        joystick.direction = UP;
+    } 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 {
+        joystick.direction = UNKNOWN;
+    }
+
+    //set flag for printing
+    printFlag = 1;
+}
 
 int main()
 {