Code for the space evader game.

Dependencies:   N5110 PowerControl mbed

main.cpp

Committer:
domplatypus
Date:
2015-05-11
Revision:
1:225522d0dd77
Parent:
0:dd6685f1343e

File content as of revision 1:225522d0dd77:

/**
@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(timerFlag) {
            timerFlag = 0;
            if(soundOn) {
                soundActivate(); //activates sound
            }
            if(menuMode) {
                if(counter==20) {
                    menuSet();//runs the menu every 20 counts
                }
            } else if(gameOverMode) {
                //game over mode
                if(counter==20) {
                    gameOverSet();//sets the game over frame every 20 counts
                }
                if(soundOn) {
                    soundActivate(); //acitvates sound
                }
            } else if(introMode) {
                introSet(); //sets the intro frame every count
                timer.detach();
                timer.attach(&timerExpired,0.01); //attaching the timer for the next frame
            } else if(helpMode) {
                if(buttonFlag) {
                    menuInit(); //if button pressed go back to the menu
                }
                buttonFlag = 0;
            }

            else if(highScoreMode) {
                if(counter==20) {
                    if(buttonFlag) {
                        menuInit(); //if button pressed bring player back to menu
                    }
                }
            } else if(settingsMode) { //runs settingsMode
                if(counter==20) {
                    settingsSet();//runs the setting frame
                }
            } else if(gameMode) { //game run mode
                if(roundFlag) {
                    //if new round flag is set start the next round
                    roundFlag =0;
                    roundInit();
                }
                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) {// speed x1.0
                        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(asteroid[i].active) {
                                //move the asteroids that are active
                                asteroid[i].moveSelf();
                            }
                        }
                    }
                } else if(speedState==1) {// x1.25
                    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(asteroid[i].active) {
                                asteroid[i].moveSelf();
                            }
                        }
                    }
                } else if(speedState==2) { //x1.33
                    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(asteroid[i].active) {
                                asteroid[i].moveSelf();
                            }
                        }
                    }
                } else if(speedState==3) { //x2.5
                    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(asteroid[i].active) {
                                asteroid[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++;
        }
        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;
    optionSelected = 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;
    lcd.clear();
    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((((asteroid[j].position[0])>(ship.position[0]-5))&((asteroid[j].position[0])<(ship.position[0]+5))
                &((asteroid[j].position[1])>(ship.position[1]-5))&((asteroid[j].position[1])<(ship.position[1]+5)))&asteroid[j].active) {
            //if an asteroid overlaps with a ships position
            if(ship.shield) {//if ship shields are up
                asteroid[j].active = 0;
                asteroid[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;
                asteroid[j].active = 0;
                asteroid[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(asteroid[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(asteroid[j].active) {
                    if((asteroid[i].position[0]>(asteroid[j].position[0]-5))&(asteroid[i].position[0]<(asteroid[j].position[0]+5))
                            &(asteroid[i].position[1]>(asteroid[j].position[1]-5))&(asteroid[i].position[1]<(asteroid[j].position[1]+5))) {
                        // if asteroids collide
                        initSound();
                        soundType =3;// produce a sound
                        if(asteroid[i].position[0]>asteroid[j].position[0]) {//if asteroids x position is greater than the other move forwards
                            asteroid[i].xDirection = 1;
                        } else if(asteroid[i].position[0]<=asteroid[j].position[0]) { //if asteroid is behind the other asteroid in the x direction move to the left
                            asteroid[i].xDirection = -1;
                        }
                        if(asteroid[i].position[1]>asteroid[j].position[1]) {//if asteroid is below the other asteroid move down
                            asteroid[i].yDirection = 1;
                        } else if(asteroid[i].position[1]<=asteroid[j].position[1])//if asteroid is above the other asteroid move up
                            asteroid[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(((asteroid[j].position[0]>(laser[i].position[0]-5))&(asteroid[j].position[0]<(laser[i].position[0]+5))
                    &(asteroid[j].position[1]>(laser[i].position[1]-5))&(asteroid[j].position[1]<(laser[i].position[1]+5))&asteroid[j].active&laser[i].active)) {
                //if both laser and asteroid is active and they collide inititiate destruction
                initSound();
                soundType =2;//play sound
                asteroid[j].active = 0;
                asteroid[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] = asteroid[j].position[0];
                        item.position[1] = asteroid[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++) {
        asteroid[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
    optionSelected = optionSelected + joystick.direction[1];
    //loops around the menu
    if(optionSelected>3) {
        optionSelected = 0;
    } else if(optionSelected<0) {
        optionSelected = 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,optionSelected+2); // array set according to which optionSelected
    if(buttonFlag&(optionSelected == 0)) {
        //start option selected
        gameStart();
    } else if(buttonFlag&(optionSelected == 1)) {
        //instruction option selected
        highScoreSet();
    } else if(buttonFlag&(optionSelected == 2)) {
        //instruction option selected
        helpInit();
    } else if(buttonFlag&(optionSelected == 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
    ////http://developer.mbed.org/questions/249/float-or-integer-to-char-or-string-conve/
    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,35,2);
    lcd.printString(name,35,4);
    for(int i = 0; i<5; i++) {
        ///draws a line under the selected char
        lcd.setPixel(35+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();
    asteroid[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();
    asteroid[0].position[0] = 0;
    asteroid[0].position[1] = 16;
    asteroid[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();
    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++) {
        asteroid[i].init();//initiates asteroids equal to the round number
        asteroid[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
    optionSelected = optionSelected + joystick.direction[1];
    if(optionSelected>3) {
        optionSelected = 0;
    } else if(optionSelected<0) {
        optionSelected = 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,optionSelected); //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&(optionSelected == 0)) {
        sound = !sound;
    } else if(buttonFlag&(optionSelected == 1)) {
        //increments the speed counter if that option is selected
        speedState++;
        if(speedState>3) {
            //reset speedState if to high
            speedState=0;
        }
    } else if(buttonFlag&(optionSelected == 3)) {
        //back to menu
        menuInit();
    } else if(buttonFlag&(optionSelected == 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;
    optionSelected = 0;
    buttonFlag =0;
    settingsSet();
    timer.detach();
    timer.attach(&timerExpired,0.01);
}
void serialISR()
{
    //sets UNIX time
    set_time(1431348000);
}
void buttonPressed() // toggle direction in ISR
{
    if(debounce.read_ms()>200) {//only set flag 200 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
    }
}