Code for the space evader game.

Dependencies:   N5110 PowerControl mbed

Revision:
0:dd6685f1343e
Child:
1:225522d0dd77
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun May 10 16:48:46 2015 +0000
@@ -0,0 +1,1054 @@
+/**
+@file main.cpp
+@brief Header file containing functions prototypes, defines and global variables.
+@brief Main code for the running of the game with external libraries of the joystick and the lcd screen
+@author Dominic J. Platt
+@date   April 2015
+*/
+#include "mbed.h"
+#include "main.h"
+#include "N5110.h" //importing Craig Evans library for LCD pixel manipulation functions
+#include "joystick.h" //external joystick files defined for simplification within the main file
+//external variables printFlag,joystick,pollJoystick,serial and button used
+//button(p18),xPot(p19),yPot(p20) used with external joystick
+#include "PowerControl/PowerControl.h"
+#include "PowerControl/EthernetPowerControl.h" 
+int main()
+{
+    init();
+    void PHY_PowerDown(); //powerdown the ethernet interface on the Mbed system
+    int counter = 0;//counter to count through the timer loops
+    introInit();
+    timer.attach(&timerExpired,0.01);
+    while(1) {
+
+        if(menuMode&timerFlag) {
+            timerFlag = 0;
+            if(counter==20) {
+                menuSet();//runs the menu every 20 counts
+            }
+            if(soundOn) {
+                soundActivate(); //activates sound
+            }
+            if(counter == 20) {
+                counter=0;//reset the counter
+            }
+            counter++;
+            //timer.detach();
+            //timer.attach(&timerExpired,0.01);//attaching the timer for the next frame
+        } else if(gameOverMode&timerFlag) {
+            //game over mode
+            timerFlag=0;
+            if(counter==20) {
+                gameOverSet();//sets the game over frame every 20 counts
+            }
+            if(soundOn) {
+                soundActivate(); //acitvates sound
+            }
+            if(counter == 20) {
+                counter=0;//reset the counter
+            }
+            counter++;
+            //timer.detach();
+            //timer.attach(&timerExpired,0.01);//attaching the timer for the next frame
+        } else if(introMode&timerFlag) {
+            introSet(); //sets the intro frame every count
+            timer.detach();
+            timer.attach(&timerExpired,0.01); //attaching the timer for the next frame
+        } else if(helpMode&timerFlag) {
+            timerFlag = 0;
+            if(buttonFlag) {
+                menuInit(); //if button pressed go back to the menu
+            }
+            buttonFlag = 0;
+            if(counter == 20) {
+                counter=0;//reset the counter
+            }
+            counter++;
+            //timer.detach();
+            //timer.attach(&timerExpired,0.01);
+        }
+
+        else if(highScoreMode&timerFlag) {
+            if(counter==20) {
+                timerFlag = 0;
+                if(buttonFlag) {
+                    menuInit(); //if button pressed bring player back to menu
+                }
+            }
+            if(counter == 20) {
+                counter=0;//reset the counter
+            }
+            counter++;
+            //timer.detach();
+            //timer.attach(&timerExpired,0.01);
+        } else if(settingsMode&timerFlag) { //runs settingsMode
+            timerFlag=0;
+            if(counter==20) {
+                settingsSet();//runs the setting frame
+            }
+            if(soundOn) {
+                soundActivate();
+            }
+            if(counter == 20) {
+                counter=0;//reset the counter
+            }
+            counter++;
+            //timer.detach();
+            //timer.attach(&timerExpired,0.01);
+        } else if(timerFlag&gameMode) { //game run mode
+            timerFlag = 0;
+            if(roundFlag) {
+                //if new round flag is set start the next round
+                roundFlag =0;
+                roundInit();
+            }
+            if(soundOn) {
+                soundActivate();//activates sound
+            }
+            if(item.active) {
+                item.addSelf();//if item has selected add the item to the screen
+            }
+            if(speedState==0) {
+                //controlling the rate of movement of the players ship and asteroids depending on the speedState
+                if(counter == 5||counter == 10||counter == 15||counter == 20) {
+                    if(shipExplodeFlag) {
+                        shipExplode();//if is in explotion stage play explotion frame
+                    } else {
+                        //otherwise move the ship
+                        ship.moveSelf(joystick.direction[0],joystick.direction[1]);
+                    }
+                    for(int i=0; i<8; i++) {
+                        if(asteroidM[i].active) {
+                            //move the asteroids that are active
+                            asteroidM[i].moveSelf();
+                        }
+                    }
+                }
+            } else if(speedState==1) {
+                if(counter == 4||counter == 8||counter == 12||counter == 16||counter == 20) {
+                    if(shipExplodeFlag) {
+                        shipExplode();
+                    } else {
+                        ship.moveSelf(joystick.direction[0],joystick.direction[1]);
+                    }
+                    for(int i=0; i<8; i++) {
+                        if(asteroidM[i].active) {
+                            asteroidM[i].moveSelf();
+                        }
+                    }
+                }
+            } else if(speedState==2) {
+                if(counter == 3||counter == 6||counter == 9||counter == 12||counter == 15||counter == 18||counter == 20) {
+                    if(shipExplodeFlag) {
+                        shipExplode();
+                    } else {
+                        ship.moveSelf(joystick.direction[0],joystick.direction[1]);
+                    }
+                    for(int i=0; i<8; i++) {
+                        if(asteroidM[i].active) {
+                            asteroidM[i].moveSelf();
+                        }
+                    }
+                }
+            } else if(speedState==3) {
+                if(counter == 2||counter == 4||counter == 6||counter == 8||counter == 10||counter == 12||counter == 14||counter == 16||counter == 18||counter == 20) {
+                    if(shipExplodeFlag) {
+                        shipExplode();
+                    } else {
+                        ship.moveSelf(joystick.direction[0],joystick.direction[1]);
+                    }
+                    for(int i=0; i<8; i++) {
+                        if(asteroidM[i].active) {
+                            asteroidM[i].moveSelf();
+                        }
+                    }
+                }
+            }
+
+            if(buttonFlag&laserClear) { // fire button pressed
+                laserActivate();
+            }
+            buttonFlag = 0; //reset the buttonFlag after everytime used
+            laserMove(); //move the laser depending on that which are active
+            check(); //checks the logic of the ships position against asteroids, asteroids against each other and walls, lasers against asteroids
+            if(counter ==3||counter == 6|| counter ==9||counter == 12||counter == 15||counter == 18||counter == 20) {
+                setScreen(); // refresh the screen once every three 'counts'
+            }
+            if(counter == 20) {
+                counter=0;//reset the counter
+            }
+            counter++;
+            //timer.detach();
+            //timer.attach(&timerExpired,0.005);//timerExpired function increased rate for the game
+        }
+        sleep();// put the mbed to sleep otherwise
+    }
+}
+
+void setScreen()
+{
+    for(int i = 0; i<84; i++) {
+        for(int j = 0; j<48; j++) { //loop through each element of the array
+            if(!(cellsCurrent==cellsBuffer)) {//if the currentCell element does not equal to the previous cell element update the display
+                if (cellsCurrent[j][i] == 1) {
+                    lcd.setPixel(i,j); //set pixel if 1
+                } else {
+                    lcd.clearPixel(i,j); //clear pixel otherwise
+                }
+                cellsBuffer[j][i] = cellsCurrent[j][i]; //update the bufferArray
+            }
+        }
+    }
+    lcd.refresh(); //refreshing the screen for the new display
+}
+void init()
+{
+    lcd.init();
+    debounce.start(); //start the debounce timer
+    buttonFlag =0;
+    walls = 0; // variable to declare whether asteroids can pass through walls
+    settingsMode =0;
+    speedState = 0;
+    roundNumber = 1;
+    asteroids = 0;
+    directionMatrix[0] = -1; // the two available matrices for our asteroids direction
+    directionMatrix[1] = 1;
+    //declares when the player is able to shoot again
+    laserClear = 1;
+    //counter to count how long a laser has been active for
+    laserCounter = 0;
+    timerFlag = 0; //timer intially 0
+    laserCoolDown = 70;
+    rapidFire = 0;
+    abilityCounter = 0;
+    titleSelected = 0;
+    introMode = 1;
+    lcd.init();
+    srand(time(NULL));//seedin the random function with the current time for more random functions
+    joystickButton.rise(&buttonPressed); //function called when button is pressed
+    serialTime.attach(&serialISR); //function called when string is sent to the mded
+    calibrateJoystick(); //joystick must remain still during this stage
+    pollJoystick.attach(&updateJoystick,1.0/10.0); //joystick checked every 10 s
+    lcd.setBrightness(1.0);//set the brightness to maximum as sound interfere's with each other
+}
+void clearArray()
+{
+    //clears the 'master' cell array so that all the pixels are nil
+    for(int i = 0; i<48; i++) {
+        for(int j = 0; j<84; j++) {
+            cellsCurrent[i][j] =0;
+        }
+    }
+}
+void initSound()
+{
+    if(sound) {
+        soundOn = 1;
+        soundCounter = 0;
+        buzzer = 0.01;
+    }
+}
+void soundActivate()
+{
+    if(sound) {
+        buzzer = 0.01;
+        if(soundCounter>19) {
+            soundOn = 0;
+            soundCounter = 0;
+            buzzer = 0;
+            //sets the sound according to which soundType is active
+        } else if(soundType ==1) {
+            buzzer.period(1/(frequency[soundCounter]));//cycles through the frequency elements to produce a increasing frequency sound
+            soundCounter++;
+        } else if(soundType ==2) {
+            buzzer.period(1/(frequency[19-soundCounter]));//moves backwards through the frequency elements to produce a decreasing frequency sound
+            soundCounter = soundCounter+2;
+        } else if(soundType ==3) {
+            buzzer.period(0.005);//high frequency sound when asteroids bounce off one another
+            soundCounter = soundCounter+10;
+        } else if(soundType ==4) {
+            buzzer.period(1/(frequency[19-soundCounter]));
+            soundCounter = soundCounter+1;
+        }
+    }
+}
+void iDSet()
+{
+    FILE *fp = fopen("/local/Highscores.csv", "r"); // open file for reading
+    char stringBuff[100]; //creating our stringBuff to hold the characters read from the file
+    if (fp == NULL) {//if file cannot be opened
+        perror ("Error opening file");
+        for(int i = 0; i<5; i++) {
+            iD[i].active = 0; //deactivate the iD classes
+        }
+        return;
+    } else {
+        if ( fgets (stringBuff , 100 , fp) != NULL )
+            puts (stringBuff); //sets the stringBuff to hold the characters of the fike
+        fclose (fp);
+    }
+    int k = 0; //integer represents which char in the file the program is at
+    for(int i=0; i<5 ; i++) { // 5 for loop to loop through all 5 iD objects
+        if(stringBuff[k]=='*') {
+            return; //exit loop when it reaches a '*' which is set to signify the end of the file
+        }
+        for(int j = 0; j<3; j++) {
+            iD[i].name[j] = stringBuff[k];//3 characters of the string buff set to the iD
+            k++;//increment counter
+        }
+        int scoreInt[5];//holds each digit of the score
+        for(int j=0; j<5; j++) {
+            scoreInt[j] = 0; // setting these elements to nil
+        }
+        k++;//increment counter as current character will be a ','
+        int count = 0;//count to count how many digits the score has
+        for(int j = 0; (!(stringBuff[k]==',')); j++) { // loop while not at character ','
+            scoreInt[j] = stringBuff[k]- '0';//setting the score digit to be the number selected
+            k++;//increment counter
+            count = j;
+        }
+        //sets the score according to the digits obtained and the number of digits
+        if(count ==1) {
+            iD[i].score = scoreInt[0]*10;
+        } else if(count==2) {
+            iD[i].score = scoreInt[0]*100+scoreInt[1]*10;
+        } else if(count==3) {
+            iD[i].score = scoreInt[0]*1000+scoreInt[1]*100+scoreInt[2]*10;
+        } else if(count ==4) {
+            iD[i].score = scoreInt[0]*10000+scoreInt[1]*1000+scoreInt[2]*100+scoreInt[3]*10;
+        } else if(count ==5) {
+            iD[i].score = scoreInt[0]*100000+scoreInt[1]*10000+scoreInt[2]*1000+scoreInt[3]*100+scoreInt[4]*10;
+        }
+        k++;//increment counter
+        for(int j = 0; (!(stringBuff[k]==',')); j++) {//for loop while character is not a ','
+            iD[i].date[j] = stringBuff[k]; // sets the data characters
+            k++;
+        }
+        k++;
+        iD[i].active = 1; // iD is now active
+        if(stringBuff[k]=='*') {
+            i=5; //exit loop when '*' is reached
+        }
+    }
+}
+
+void writeDataToFile(int score,char n1, char n2, char n3)
+{
+    //code idea from http://www.cplusplus.com/reference/cstdio/fgets/
+
+    ID playerBuff; //ID object created to hold the players attributes to write into the file
+    playerBuff.score = score;
+    playerBuff.active = 1;
+    sprintf(playerBuff.name,"%c%c%c",n1,n2,n3);
+    time_t seconds = time(NULL); // get current time
+    //format time into a string (time and date)
+    strftime(playerBuff.date,6,"%b", localtime(&seconds));
+    iDSet();//gets the current players ID from the file
+    for(int i = 0; i<5; i++) {
+        //organises the current players score against the other one and shifts all iDs below downwards
+        if(playerBuff.score>iD[i].score) {
+            if(i<4) {
+                iD[4] = iD[3];
+            }
+            if(i<3) {
+                iD[3] = iD[2];
+            }
+            if(i<2) {
+                iD[2] = iD[1];
+            }
+            if(i<1) {
+                iD[1] = iD[0];
+            }
+            iD[i] = playerBuff;
+            i=5; //exit for loop
+        }
+    }
+    remove( "/local/Highscores.csv" ); //deletes the existing file
+    FILE *fp0 = fopen("/local/Highscores.csv", "a"); // open 'log.csv' (excel file) for appending
+// creates a new file
+    for(int i = 0; i<5; i++) {
+        if(iD[i].active) { // writes the currents players iD into the file with a ',' to seperate the attributes
+            fprintf(fp0,"%c%c%c,%d,%s,",iD[i].name[0],iD[i].name[1],iD[i].name[2],iD[i].score,iD[i].date); // print string to file "," represents break between name and score "/" represents a new line
+        }
+    }
+    //writes a '*' to signify the end of the data
+    fprintf(fp0,"*");//marks the end of the file
+    fclose(fp0); // close file
+}
+void writeID()
+{
+    lcd.clear();
+    //prints the column names
+    lcd.printString("Name",0,0);
+    lcd.printString("Score",26,0);
+    lcd.printString("Date",56,0);
+    //assigns the players iD from the flash drive
+    iDSet();
+    for(int i = 0; i<5; i++) {
+        //printing each repective ID on the screen
+        if(iD[i].active) { //only if the ID is active do we want to display this
+            char nameString[3];
+            char scoreString[5];
+            sprintf(scoreString,"%d",iD[i].score);
+            sprintf(nameString,"%c%c%c",iD[i].name[0],iD[i].name[1],iD[i].name[2]);
+            lcd.printString(nameString,0,i+1);
+            lcd.printString(scoreString,26,i+1);
+            lcd.printString(iD[i].date,56,i+1);
+        }
+    }
+}
+
+void initSpawn()
+{
+    int count = 0;
+    //defining the spawnLocations matrix
+    for(int j = 0; j<4; j++) {
+        for(int i= 0 ; i<8; i++) {
+            if(i==7||i==0||j==0||j==3) {
+                //defining the spawn locations to be along the borders of the screen
+                spawnLocation[count][0] = i*10;
+                spawnLocation[count][1] = j*10;
+                if(j==3) {
+                    spawnLocation[count][1] = 42;
+                }
+                spawnLocation[count][2] = 1;
+                count++;
+            }
+        }
+    }
+    if(ship.position[1]<10) {
+        int x = ship.position[0]/10;
+        spawnLocation[x][2] = 0; // not available
+    }
+    if((ship.position[1]>30)) {
+        int x = ship.position[0]/10;
+        spawnLocation[x+12][2] = 0;
+        if(!((x+11)==11)) {
+            spawnLocation[x+11][2] = 0;
+        }
+        if(!((x+13)==20)) {
+            spawnLocation[x+13][2] = 0;
+        }
+    }
+    if(ship.position[0]<10) {
+        int x = ship.position[1]/10;
+        if(x==0) {
+            spawnLocation[0][2] = 0;
+        }
+        if(x==1) {
+            spawnLocation[8][2] = 0;
+        }
+        if(x==2) {
+            spawnLocation[10][2] = 0;
+        }
+        if(x==3) {
+            spawnLocation[12][2] = 0;
+        }
+    }
+    if(ship.position[0]>74) {
+        int x = ship.position[1]/10;
+        if(x==0) {
+            spawnLocation[7][2] = 0;
+        }
+        if(x==1) {
+            spawnLocation[9][2] = 0;
+        }
+        if(x==2) {
+            spawnLocation[11][2] = 0;
+        }
+        if(x==3) {
+            spawnLocation[19][2] = 0;
+        }
+    }
+}
+int getSpawnLocation()
+{
+
+    while(1) {//while loop continues until function produces a return
+        int x = rand() % 20; // produces a random number 0 to 19
+        if(spawnLocation[x][2]) {
+            //if position is available
+            spawnLocation[x][2] = 0;//position no longer available
+            return x;//position is no longer availables
+        }
+    }
+}
+void timerExpired()
+{
+    // timer function to control the frame rate, enemy speed, ship speed, laser speed
+    timerFlag = 1; //turn flag on
+}
+
+Laser laserInit()   //function to create a laser class with x y position sent
+{
+    Laser laser; //laser object created of the Laser class
+    laser.active = 0; // laser is not active
+    laser.counterFlag = 0;
+    for(int i =0; i< 5; i++) {
+        laser.shape[i] = 1; // defining the laser matrix
+    }
+    return laser; //returning the laser class
+}
+
+void gameOverInit()
+{
+    //initialises variables for the gameOver screen
+    cSelected =0;
+    c1 =0;
+    c2 = 0;
+    c3 = 0;
+    gameMode = 0;
+    gameOverMode =1;
+    menuMode = 0;
+    speedState = 0;
+    //http://developer.mbed.org/questions/249/float-or-integer-to-char-or-string-conve/
+    char scoreString[10];
+    //converts score to string
+    sprintf(scoreString,"%d",score);
+    lcd.clear();
+    lcd.printString("Game Over",10,0);
+    lcd.printString("Your score was",0,1);
+    //score is printed
+    lcd.printString(scoreString,10,2);
+    lcd.printString("AAA",10,4);
+    buttonFlag = 0;
+    timer.detach();
+    timer.attach(&timerExpired,0.01);
+}
+void check()
+{
+    //ship position check against asteroids
+    for (int j = 0; j<8; j++) {
+        //loops through every asteroid
+        if((((asteroidM[j].position[0])>(ship.position[0]-5))&((asteroidM[j].position[0])<(ship.position[0]+5))
+                &((asteroidM[j].position[1])>(ship.position[1]-5))&((asteroidM[j].position[1])<(ship.position[1]+5)))&asteroidM[j].active) {
+            //if an asteroid overlaps with a ships position
+            if(ship.shield) {//if ship shields are up
+                asteroidM[j].active = 0;
+                asteroidM[j].deleteSelf(); //deactivating the asteroid
+                asteroids--;
+                if(score>50) {//player looses 50 points
+                    score = score - 50;
+                } else {
+                    score = 0;
+                }
+                ship.shield =0; //shields are deactivated
+                ship.shieldUpdate();//updates the players shield state
+                initSound();
+                soundType =3;
+            } else if((!shipExplodeFlag)&!ship.shield) {
+                shipExplodeFlag = 1;
+                explotionStage = 1;
+                asteroidM[j].active = 0;
+                asteroidM[j].deleteSelf();
+                initSound();
+                soundType =2;
+            }
+        }
+    }
+// checking the asteroids position off each other so they can bounce off each other
+    for(int i = 0; i<8; i++) {
+        if(asteroidM[i].active) { //looping through all the active asteroids
+            for(int j = 0; j<8; j++) {
+                if(i==j) { //if asteroid checked is the actual asteroid of the first for loop move to the next one
+                    j++;
+                }
+                if(asteroidM[j].active) {
+                    if((asteroidM[i].position[0]>(asteroidM[j].position[0]-5))&(asteroidM[i].position[0]<(asteroidM[j].position[0]+5))
+                            &(asteroidM[i].position[1]>(asteroidM[j].position[1]-5))&(asteroidM[i].position[1]<(asteroidM[j].position[1]+5))) {
+                        // if asteroids collide
+                        initSound();
+                        soundType =3;// produce a sound
+                        if(asteroidM[i].position[0]>asteroidM[j].position[0]) {//if asteroids x position is greater than the other move forwards
+                            asteroidM[i].xDirection = 1;
+                        } else if(asteroidM[i].position[0]<=asteroidM[j].position[0]) { //if asteroid is behind the other asteroid in the x direction move to the left
+                            asteroidM[i].xDirection = -1;
+                        }
+                        if(asteroidM[i].position[1]>asteroidM[j].position[1]) {//if asteroid is below the other asteroid move down
+                            asteroidM[i].yDirection = 1;
+                        } else if(asteroidM[i].position[1]<=asteroidM[j].position[1])//if asteroid is above the other asteroid move up
+                            asteroidM[i].yDirection = -1;
+                    }
+                }
+            }
+        }
+    }
+    //checking the laser positions against the asteroids
+    for(int i = 0; i<4; i++) {
+        for (int j = 0; j<8; j++) {
+            if(((asteroidM[j].position[0]>(laser[i].position[0]-5))&(asteroidM[j].position[0]<(laser[i].position[0]+5))
+                    &(asteroidM[j].position[1]>(laser[i].position[1]-5))&(asteroidM[j].position[1]<(laser[i].position[1]+5))&asteroidM[j].active&laser[i].active)) {
+                //if both laser and asteroid is active and they collide inititiate destruction
+                initSound();
+                soundType =2;//play sound
+                asteroidM[j].active = 0;
+                asteroidM[j].deleteSelf(); //deactivating the asteroid
+                asteroids--;//marking one less asteroid
+                score = score + 10;//player gains point
+                laser[i].active = 0; // deactiviating the laser
+                laser[i].deleteSelf();
+                if(!(item.active||rapidFire)) {
+                    int x = rand() %7; // 1 in 7 chance of an item drop
+                    if(x==0) {
+                        //puts the item to the asteroids position
+                        item.active = 1;
+                        item.position[0] = asteroidM[j].position[0];
+                        item.position[1] = asteroidM[j].position[1];
+                        item.addSelf();
+                    }
+                }
+            }
+        }
+    }
+    if(asteroids == 0) {
+        //new round when all asteroids are destroyed
+        roundFlag = 1;
+    }
+    if(rapidFire) {
+        //rapidFire enabled when user touches item
+        if(abilityCounter>1000) { //if the ability counter exceeds a certain number
+            rapidFire=0;//deactivate rapidFire
+            laserCoolDown = 70; //laser fire cool down set to normal
+        } else {
+            abilityCounter++; //increment counter
+        }
+    }
+    if((((item.position[0])>(ship.position[0]-5))&((item.position[0])<(ship.position[0]+5))
+            &((item.position[1])>(ship.position[1]-5))&((item.position[1])<(ship.position[1]+5)))&item.active) {
+        //if ship collides with the item
+        //sets the laserCoolDown to be much lower for rapidFire
+        laserCoolDown = 22;
+        item.active = 0; //deactivate and remove the item from the matrix
+        item.deleteSelf();
+        rapidFire = 1;
+        abilityCounter = 0;//initiates counter
+    }
+
+}
+
+void laserActivate()
+{
+    laserClear = 0; // laser is not clear to fire
+    if(!laser[0].active) {//if laser is not active activate this laser object
+        laser[0].position[0] = ship.position[0] + 5;
+        laser[0].position[1] = ship.position[1] + 2;//set the lasers position and activate
+        laser[0].active =1; //laser is now active
+        laser[0].counterFlag = 1;
+    } else if(!laser[1].active) {
+        laser[1].position[0] = ship.position[0] +5;
+        laser[1].position[1] = ship.position[1] +2;
+        laser[1].active = 1;
+        laser[1].counterFlag = 1;
+    } else if(!laser[2].active) {
+        laser[2].position[0] = ship.position[0]+5;
+        laser[2].position[1] = ship.position[1]+2;
+        laser[2].active = 1;
+        laser[2].counterFlag = 1;
+    } else if(!laser[3].active) {
+        laser[3].position[0] = ship.position[0]+5;
+        laser[3].position[1] = ship.position[1]+2;
+        laser[3].active = 1;
+        laser[3].counterFlag = 1;
+    }
+    initSound();//initiate laser sound
+    soundType =1;
+}
+void laserMove()
+{
+    //moves the laser if it is active
+    if(laser[0].active) {
+        laser[0].moveSelf(1);
+    }
+    if(laser[1].active) {
+        laser[1].moveSelf(1);
+    }
+    if(laser[2].active) {
+        laser[2].moveSelf(1);
+    }
+    if(laser[3].active) {
+        laser[3].moveSelf(1);
+    }
+    //if laser counterFlag is set, increment the laser Counter
+    if(laser[0].counterFlag||laser[1].counterFlag||laser[2].counterFlag||laser[3].counterFlag) {
+        //if the laserCounter exceeds the cooldown limit laser is clear to fire
+        if(laserCounter>laserCoolDown) {
+            laserCounter = 0;
+            laserClear = 1;
+            laser[0].counterFlag = 0;
+            laser[1].counterFlag = 0;
+            laser[2].counterFlag = 0;
+            laser[3].counterFlag = 0;
+        }
+        laserCounter++;
+    }
+}
+void gameStart()
+{
+    for(int i = 0; i<8; i++) {
+        asteroidM[i].active = 0;
+    }
+    item.active = 0;
+    clearArray();
+    asteroids = 0;
+    roundNumber = 1;
+    score = 0;
+    menuMode =0;
+    gameMode =1;
+    highScoreMode = 0;
+    lcd.clear();
+    clearArray();
+    ship.init();
+    ship.addSelf();
+    item.init();
+    roundFlag = 1;
+    gameMode = 1;
+    buttonFlag =0;
+    shipExplodeFlag = 0;
+    timer.detach();
+    timer.attach(&timerExpired,0.005);
+}
+void highScoreSet()
+{
+    menuMode = 0;
+    gameMode = 0;
+    introMode = 0;
+    highScoreMode = 1;
+    gameOverMode = 0;
+    iDSet();
+    writeID();
+    timer.detach();
+    timer.attach(&timerExpired,0.01);
+}
+void menuSet()
+{
+    //sets the option selected depending on the joystick y direction
+    titleSelected = titleSelected + joystick.direction[1];
+    //loops around the menu
+    if(titleSelected>3) {
+        titleSelected = 0;
+    } else if(titleSelected<0) {
+        titleSelected = 3;
+    }
+    if((joystick.direction[1]==1)||(joystick.direction[1]==-1)) {
+        //if joystick moved initiate sound
+        soundType =3;
+        initSound();
+    }
+    lcd.clear();
+    for(int i = 0; i<84; i++) {
+        cellsCurrent[8][i] = 1;//draws a line under the title
+    }
+    ship.addSelf(); // adds the ship as a logo to the screen
+    setScreen(); // sets the screen
+    lcd.printString("Space Evader",0,0); //text overlayed on the screen
+    lcd.printString("Start Game",10,2);
+    lcd.printString("HighScores",10,3);
+    lcd.printString("Help",10,4);
+    lcd.printString("Settings",10,5);
+    lcd.printString(">",0,titleSelected+2); // array set according to which titleSelected
+    if(buttonFlag&(titleSelected == 0)) {
+        //start option selected
+        gameStart();
+    } else if(buttonFlag&(titleSelected == 1)) {
+        //instruction option selected
+        highScoreSet();
+    } else if(buttonFlag&(titleSelected == 2)) {
+        //instruction option selected
+        helpInit();
+    } else if(buttonFlag&(titleSelected == 3)) {
+        //settings option selected
+        settingsInit();
+    }
+    //setting the buttonFlag off so it is not set again until the joystick is pressed
+    buttonFlag = 0;
+}
+
+void gameOverSet()
+{
+    if((joystick.direction[0]==1)||(joystick.direction[0]==-1)||(joystick.direction[1]==1)||(joystick.direction[1]==-1)) {
+        //sound activate when joystick moved
+        initSound();
+        soundType =3;
+    }
+    char scoreString[10]; //stores the score
+    sprintf(scoreString,"%d",score);//converts the users score from an int to a string
+    char alphabet [27] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"}; //alphabet matrix defined
+    cSelected = cSelected +joystick.direction[0]; //character selected moved depending on the joystick
+    if(cSelected>2) { //loops through the characters selected at the boundaries
+        cSelected = 0;
+    } else if(cSelected <0) {
+        cSelected = 2;
+    }//sets the character selected depending to the one chosen
+    if(cSelected ==0) {
+        c1 = c1+ joystick.direction[1];
+        if(c1>25) {
+            c1 = 0;
+        }
+        if(c1<0) {
+            c1 = 25;
+        }
+    }
+    if(cSelected ==1) {
+        c2 = c2+joystick.direction[1];
+        if(c2>25) {
+            c2 = 0;
+        }
+        if(c2<0) {
+            c2 = 25;
+        }
+    }
+    if(cSelected ==2) {
+        c3 = c3 + joystick.direction[1];
+        if(c3>25) {
+            c3 = 0;
+        }
+        if(c3<0) {
+            c3 = 25;
+        }
+    }
+    char name[3];
+    //converts the name chars into a string
+    sprintf(name,"%c%c%c",alphabet[c1],alphabet[c2],alphabet[c3]);
+    lcd.clear();
+    //sets the characters
+    lcd.printString("Game Over",10,0);
+    lcd.printString("Your score was",0,1);
+    lcd.printString(scoreString,25,2);
+    lcd.printString(name,25,4);
+    for(int i = 0; i<5; i++) {
+        ///draws a line under the selected char
+        lcd.setPixel(25+i+cSelected*6,40);
+    }
+    lcd.refresh();
+    if(buttonFlag) {
+        //if button is pressed write the players ID to the drive
+        writeDataToFile(score,alphabet[c1],alphabet[c2],alphabet[c3]);
+        //open the menu
+        menuInit();
+    }
+    //reset flag
+    buttonFlag = 0;
+}
+void helpInit()
+{
+    //clear the array
+    clearArray();
+    //clear the lcd
+    lcd.clear();
+    //initialise the spawn position, although spawn positions are not needed this function is required to initialise an asteroid object
+    initSpawn();
+    ship.init();
+    asteroidM[0].init();
+    item.init();
+    menuMode = 0;
+    gameOverMode = 0;
+    helpMode =1;
+    gameOverMode =0;
+    highScoreMode =0;
+    //adding the asteroid, ship and item objects to the screen
+    ship.position[0] = 0;
+    ship.position[1] = 0;
+    ship.addSelf();
+    ship.shield = 0;
+    ship.shieldUpdate();
+    ship.position[0] = 0;
+    ship.position[1] = 8;
+    ship.addSelf();
+    asteroidM[0].position[0] = 0;
+    asteroidM[0].position[1] = 16;
+    asteroidM[0].addSelf();
+    item.position[0] = 0;
+    item.position[1] = 24;
+    item.addSelf();
+    setScreen();//setting the matrix
+    lcd.printString("Player ship",10,0); //adding text to label the objects
+    lcd.printString("Vulnerable",10,1);
+    lcd.printString("Asteroid",10,2);
+    lcd.printString("Rapid fire",10,3);
+    lcd.printString("Avoid and kill",0,4);
+    lcd.printString("the asteroids",0,5);
+    timer.detach();
+    timer.attach(&timerExpired,0.01);
+}
+void menuInit()
+{
+    clearArray();
+    ship.init();
+    ship.position[0] = 75;
+    ship.position[1] = 2;
+    ship.addSelf();
+    setScreen();
+    lcd.printString("Space Evader",0,0);
+    lcd.printString("Start Game",10,2);
+    lcd.printString("HighScores",10,3);
+    lcd.printString("Help",10,4);
+    lcd.printString("Settings",10,5);
+    settingsMode = 0;
+    gameOverMode = 0;
+    gameMode = 0;
+    menuMode = 1;
+    introMode = 0;
+    helpMode = 0;
+    buttonFlag =0;
+    timer.detach();
+    timer.attach(&timerExpired,0.01);
+}
+void introInit()
+{
+    introCounter= 0;
+    introMode =1;
+    settingsMode = 0;
+    gameOverMode = 0;
+    gameMode = 0;
+    menuMode = 0;
+    helpMode = 0;
+    buttonFlag = 0;
+    timer.detach();
+    timer.attach(&timerExpired,0.01);
+}
+void introSet() //intro mode frame set
+{
+    if(introCounter<=100) {
+        //play this for first 100 frames
+        lcd.printString("Dominic Platt",0,0);
+        lcd.printString("Presents...",12,1);
+    }
+    if(introCounter==100) {
+        //initialise and set ship
+        ship.init();
+        ship.position[0] = 0;
+        ship.position[1] =34;
+        ship.addSelf();
+    }
+    if(introCounter>100&introCounter<180) {
+        //move ship for next 80 frames
+        ship.moveSelf(1,0);
+        setScreen();
+        lcd.printString("Space Evader",5,0);
+
+    }
+    if(introCounter==180||buttonFlag) { // if timer up or button pressed
+        //starts menu
+        ship.deleteSelf();
+        menuInit();
+    }
+    introCounter++; //introCounter
+}
+void roundInit()
+{
+    //initialises a round
+    if(roundNumber>8) {
+        roundNumber = 1; // reset the roundNumber
+        if(speedState<4) {
+            speedState++;//increases the speed of the game if it hasn't exceeded its max value
+        }
+        ship.shield=1; // regenerate shields when new round initiates
+        ship.shieldUpdate();
+    }
+    initSpawn(); // initialises spawn positions
+    for(int i = 0; i<roundNumber; i++) {
+        asteroidM[i].init();//initiates asteroids equal to the round number
+        asteroidM[i].active = 1;
+        asteroids++; // add one to the counter
+    }
+    roundNumber++; //increment roundNumber
+}
+void shipExplode()
+{
+    //sets the explotionn frame of the ship
+    ship.destroySelf(explotionStage);
+    explotionStage++;//increment the explotionStage
+    if(explotionStage>12) {
+        //explotion finished gameOverScreenSet
+        shipExplodeFlag = 0;
+        gameOverInit();
+    }
+}
+void settingsSet()
+{
+    //sets the title selected with the joystick
+    titleSelected = titleSelected + joystick.direction[1];
+    if(titleSelected>3) {
+        titleSelected = 0;
+    } else if(titleSelected<0) {
+        titleSelected = 3;
+    }
+    if((joystick.direction[1]==1)||(joystick.direction[1]==-1)) {
+        soundType =3; //sound when joystick moved
+        initSound();
+    }
+    lcd.clear();
+    lcd.printString("Sound",7,0);
+    lcd.printString("On",45,0);
+    lcd.printString("Off",65,0);
+    if(sound) {//sets the marker depending on whether sound is on or not
+        lcd.printString(" ",59,0);
+        lcd.printString("-",39,0);
+    } else {
+        lcd.printString(" ",39,0);
+        lcd.printString("-",59,0);
+    }
+    lcd.printString("Speed",7,1);
+    char myChar[8];
+    sprintf(myChar,"%dx",1+speedState); //speed marked
+    lcd.printString(myChar,60,1);
+    lcd.printString("Walls",7,2);
+    lcd.printString(">",0,titleSelected); //selector depending on option selected
+    char bufferDate[14]; //presents the time and date
+    char bufferTime[14];
+    lcd.printString("Back",7,3);
+    time_t seconds = time(NULL); // get current time
+    //format time into a string (time and date)
+    strftime(bufferDate,14,"%D", localtime(&seconds));
+    strftime(bufferTime,14,"%T", localtime(&seconds));
+    lcd.printString(bufferDate,7,4);
+    lcd.printString(bufferTime,7,5);
+    if(buttonFlag&(titleSelected == 0)) {
+        sound = !sound;
+    } else if(buttonFlag&(titleSelected == 1)) {
+        //increments the speed counter if that option is selected
+        speedState++;
+        if(speedState>3) {
+            //reset speedState if to high
+            speedState=0;
+        }
+    } else if(buttonFlag&(titleSelected == 3)) {
+        //back to menu
+        menuInit();
+    } else if(buttonFlag&(titleSelected == 2)) {
+        //turn on/off the walls
+        walls = !walls;
+    }
+    if(walls) {//presents whether the walls are active
+        lcd.printString("On",50,2);
+    } else {
+        lcd.printString("Off",50,2);
+    }
+    //reset the button flag
+    buttonFlag = 0;
+}
+void settingsInit()
+{
+    //initialises the setting screen
+    menuMode = 0;
+    settingsMode = 1;
+    titleSelected = 0;
+    buttonFlag =0;
+    settingsSet();
+    timer.detach();
+    timer.attach(&timerExpired,0.01);
+}
+void serialISR()
+{
+    //sets UNIX time
+    set_time(1430595271);
+}
+void buttonPressed() // toggle direction in ISR
+{
+    if(debounce.read_ms()>150) {//only set flag 150 ms after the last flag was set to filter out the 'bounces'
+        //buttonFlag set when button is pressed
+        buttonFlag = 1;
+        debounce.reset();//reset the debounce timer
+    }
+}
\ No newline at end of file