My ELEC2645 joystick project Tetris Game NAME: JIANWEI CHEN SID: 200879849

Dependencies:   N5110 SDFileSystem mbed

Revision:
4:463abe5f5135
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Game.h	Thu May 05 09:18:01 2016 +0000
@@ -0,0 +1,816 @@
+/**
+@file Game.h
+@brief Header file containing functions prototypes, defines and global variables for the tetris game.
+@brief Revision 1.0.
+@author JIANWEI CHEN
+@date   May 2016
+*/
+
+#ifndef GAME_H
+#define GAME_H
+
+#include "mbed.h"
+#include "Patterns.h"
+#include "N5110.h"
+#include "SDFileSystem.h"
+#include "main.h"
+
+//! Create patterns object
+Patterns patterns;
+/**
+Create ticker object for game
+@brief ticker to control the speed of game
+*/
+Ticker game;
+
+////////////////////////////////////////////////////////
+// Variables
+////////////////////////////////////////////////////////
+
+int xOld; /*!< Variable for storing the pattern previous position when game is runnung */
+int typeCount = 0; /*!< Variable for counting elements in array typeArray[100]*/
+int nextTypeCount; /*!< Variable to show the position of next element in typeArray[100] i.e. nextTypeCount=typeCount+1*/
+
+/** Flag to show left hand side conllision of pattern
+@note flag = 0 - there is no collision on the left
+@note flag = 1 - there is collision on the left
+*/
+int left_collision_flag = 0;
+
+/** Flag to show right hand side conllision of pattern
+@note flag = 0 - there is no collision
+@note flag = 1 - there is collision
+*/
+int right_collision_flag = 0;
+
+/** Flag to show bottom conllision of pattern
+@note flag = 0 - there is no collision
+@note flag = 1 - there is collision
+*/
+int bottom_collision_flag = 0;
+
+/** Flag to show top conllision of pattern
+@note flag = 0 - there is no collision
+@note flag = 1 - there is collision
+*/
+int top_collision_flag = 0;
+
+/** Flag to show if there is pixels set on the 4 pixels distance away from the bottom of pattern
+@brief if flag = 0, user can pull joystick down to make pattern falling faster
+@note flag = 0 - there is no collision
+@note flag = 1 - there is collision
+*/
+int fastmove_bottom_collision_flag = 0;
+
+/** Flag to show if allow patterns to rotate
+@note flag = 0 - allow
+@note flag = 1 - not allow
+*/
+int rotation_collision_flag = 0;
+
+/** Two dimension array to store current pattern pixels setting in a 6x6 square
+@note For example, if current pattern is "L"
+@note the pixels setting is
+@note 1 1 0 0 0 0
+@note 1 1 0 0 0 0
+@note 1 1 0 0 0 0
+@note 1 1 0 0 0 0
+@note 1 1 1 1 0 0
+@note 1 1 1 1 0 0
+*/
+int pattern_buffer[6][6];
+
+/** Array to store types of pattern
+@brief 100 random integers in the range of 0~6
+@brief will be stored in the array in order to generate
+@brief random type of pattern each time new pattern is generated
+*/
+int typeArray[100];
+int buffer[84][48]; /*!< Array to store whole screen pixel settings */
+int score=0; /*!< Variable to store score in the game */
+volatile int g_game_flag = 0; /*!< Flag for game ticker */
+
+/** Struct for position
+@brief Contains the pattern position(x,y),
+@brief pattern type and rotation
+*/
+struct Position {
+    float x;
+    float y;
+    int type;
+    int rotation;
+};
+typedef struct Position position;
+position pos;
+
+////////////////////////////////////////////////////////////////////////
+// Functions
+////////////////////////////////////////////////////////////////////////
+/**
+Game ticker isr function
+*/
+void game_isr();
+
+/**
+Initialise the variables in game
+*/
+void init_game();
+
+/** Drawing the pattern at position (x,y)
+@param type - type of pattern (0~6)
+@param rotation - rotation of pattern (0~3)
+@param x - x co-ordinate of pattern, which is the top left corner pixel of 6x6 square
+@param y - y co-ordinate of pattern, which is the top left corner pixel of 6x6 square
+@param fill - fill = 0 white, fill = 1 black
+*/
+void drawPattern(int type,int rotation,int x,int y,int fill);
+
+/**Left collision detect
+@brief Function to check the left collision of current falling pattern and set the left_collision_flag
+*/
+void left_collisionDetect();
+
+/**Right collision detect
+@brief Function to check the right collision of current falling pattern and set the left_collision_flag
+*/
+void right_collisionDetect();
+
+/**Bottom collision detect
+@brief Function to check the bottom collision of current falling pattern and set the right_collision_flag
+*/
+void bottom_collisionDetect();
+
+/**top collision detect
+@brief Function to check the top collision of current falling pattern and set the top_collision_flag
+*/
+void top_collisionDetect();
+
+/**Rotation collision detect
+@brief Function to check if the program should allow user to rotate the pattern and set the rotation_collision_flag
+*/
+void rotation_collisionDetect();
+
+/**Fast move collision detect
+@brief Function to check if the program should allow user to move the pattern falling faster and set the fastmove_collision_flag
+@note check the 4 pixels distance away from the bottom of pattern
+*/
+void fastmove_bottom_collisionDetect();
+
+/**Get pattern pixel settings
+@brief Function to get the current falling pattern pixel settings
+@note pixels setting will be store in pattern_buffer[6][6];
+@param type - type of pattern (0~6)
+@param rotation - rotation of pattern (0~3)
+*/
+void get_pattern(int type, int rotatin);
+
+/**Scan the whole screen pixel settings
+@brief Function to store the whole screen pixel settings and store in buffer[84][48]
+*/
+void scan();
+
+/** Cancel the filled lines and add the score
+@brief Function to check if there are lines filled
+@brief if one line is filled, cancel it and move the pixels above this line down and add the score
+*/
+void cancelLine();
+
+/**
+Game finish animations
+*/
+void finishAnimation();
+
+/** User press button when game is in process
+@brief When button pressed in the game, ask user if they want to exit the game
+@return TRUE - exit the game  FALSE - contiute the game
+*/
+bool buttonPressedInGame();
+
+/**Save the highest score to SD card
+@param score - a integer number need to save to SD card
+*/
+void save_score_SD(int score);
+
+/**
+Read the highest score from SD card
+*/
+int read_score_SD();
+
+/**
+Complete tetris game
+*/
+void tetis_game();
+
+
+/////////////////////////////////////////////////
+/// Function Definitions
+/////////////////////////////////////////////////
+
+void tetis_game()
+{
+    bool exitGame; //bool variable to save the exit game decision when button pressed
+    while (1) {
+        if(g_game_flag==1) {
+            g_game_flag = 0;
+
+            exitGame=buttonPressedInGame(); //check if user press button and get the decision
+            if(exitGame) { // exit game
+                break; //jump out of while loop
+            }
+
+            pos.type = typeArray[typeCount]; //get the pattern type
+            nextTypeCount=typeCount+1;
+            if (nextTypeCount>99) { //start from the first element in type array
+                nextTypeCount=0;
+            }
+            drawPattern(typeArray[nextTypeCount],0,55,41,1);// draw next pattern on the right hand side of screen
+            if (pos.y >= -5) { // when pattern start falling, clear previous pattern
+                drawPattern(pos.type,pos.rotation,xOld,pos.y-1,0);
+            }
+
+            updateJoystick(); //get the joystick direction
+
+            top_collisionDetect(); // check if current pattern touch the top
+            if (top_collision_flag == 1) { // if touch the top, finish the game
+                red_led=1;
+                green_led=0;
+                //play sound at end of game
+                for(double i=1; i>=0; i-=0.1) {
+                    buzzer = i;
+                    wait(0.2);
+                }
+                buzzer = 0;
+                finishAnimation(); //finish animation
+                lcd.clear();
+                int stored_score=read_score_SD();
+                if (score>stored_score) { // if score is larger than highest score, save it to SD card
+                    save_score_SD(score);
+                }
+                // show the score
+                char scoreBuffer[14];
+                sprintf(scoreBuffer,"%d",score);
+                lcd.printString("SCORE IS: ",10,2);
+                lcd.printString(scoreBuffer,35,4);
+                lcd.refresh();
+                wait(3.0);
+                lcd.clear();
+                state=0; // back to the main menu
+                break;
+            }
+
+            //move patterns according to joystick direction
+            switch(joystick.direction) {
+                case UP: // rotation
+                    rotation_collision_flag = 0;
+                    rotation_collisionDetect(); // check if allow rotation
+                    if(rotation_collision_flag == 0) { // allow rotation
+                        pos.rotation++;
+                        if (pos.rotation>3) {
+                            pos.rotation=0;
+                        }
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    } else {// not allow rotation
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    }
+                    break;
+                case DOWN: // faster moving down
+                    fastmove_bottom_collision_flag = 0;
+                    fastmove_bottom_collisionDetect();
+                    if (fastmove_bottom_collision_flag == 0) {// allow faster move
+                        pos.y +=4; // move pattern down by 4 pixels distance
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    } else {
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    }
+                    break;
+                case RIGHT: // move right
+                    right_collision_flag = 0;
+                    right_collisionDetect(); // detect right collision
+                    if( right_collision_flag == 0) { // allow move right
+                        pos.x +=2;
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    } else { // not allow move right
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                        right_collision_flag = 0;
+                    }
+                    break;
+                case LEFT: //move left
+                    left_collision_flag = 0;
+                    left_collisionDetect(); // detect left collision
+                    if( left_collision_flag == 0) {// allow move left
+                        pos.x -=2;
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    } else { // not allow move left
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                        left_collision_flag = 0;
+                    }
+
+                    break;
+                case CENTRE: // joystick in centre
+                    drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    break;
+                case  UNKNOWN:
+                    drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    break;
+            }
+
+            xOld = pos.x; //store previous pattern x co-codinate
+
+            bottom_collisionDetect(); // bottom collision detect
+            if (bottom_collision_flag == 0) { // no collision
+                pos.y++; // keep moving pattern down
+                buzzer = 0; // turn off buzzer
+            } else { // bottom collision
+                drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); // fix pattern
+                cancelLine(); // check filled lines and add score
+                pos.x = 10; // new pattern will fall from the centre
+                pos.y = -6;
+                pos.rotation=0;
+                drawPattern(typeArray[nextTypeCount],pos.rotation,55,41,0);// clear the old next pattern show on RHS of screen
+                typeCount ++; //new type of pattern
+                if (typeCount >99) {
+                    typeCount = 0;
+                }
+            }
+            lcd.refresh();
+        }
+        sleep(); // go to sleep mode unless ticker interupt
+    }
+}
+
+
+void init_game()
+{
+    pos.x = 10;
+    pos.y = -6;
+    pos.rotation=0;
+    typeCount=0;
+    green_led=1; // turn on green led
+    //generate 100 random integers in the range of 0~6
+    //and store in typeArray
+    for(int i=0; i<=99; i++) {
+        typeArray[i] = rand()%7;
+    }
+
+    //gaming screen
+    lcd.drawLine(30,0,30,47,1);
+    lcd.printString("Level:",42,0);
+    lcd.printString("Score:",42,2);
+    lcd.printString("0",42,3);
+    lcd.printString("Next:",42,4);
+
+    //play sound at begining of game
+    for(double i=0; i<=1.0; i+=0.1) {
+        buzzer = i;
+        wait(0.2);
+    }
+    buzzer = 0;
+}
+
+
+void get_pattern(int type, int rotation)
+{
+    for(int i=0; i<=5; i++) {
+        for(int j=0; j<=5; j++) {// patterns.getPatterns(type,rotation,j,i) return pattern[type][rotation][y][x];
+            pattern_buffer[i][j] = patterns.getPatterns(type,rotation,j,i);
+        }
+    }
+}
+
+
+void scan()
+{
+    //screen has 84x48 pixels
+    for (int i=0; i<=83; i++) {
+        for (int j=0; j<=47; j++) {
+            if(lcd.getPixel(i,j)) { //if pixel is set
+                buffer[i][j] = 1;
+            } else { // pixel is clear
+                buffer[i][j] = 0;
+            }
+        }
+    }
+}
+
+// draw pattern at (x,y)
+void drawPattern(int type,int rotation,int x,int y,int fill)
+{
+    get_pattern(type,rotation); // get the pattern pixel settings, which store in pattern_buffer
+    for(int i=x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
+        for(int j=y; j <= y+5; j++) {
+            if (j>=0) {
+                if(pattern_buffer[i-x][j-y]==1) {//pixel setting is 1
+                    if (fill==0) { //draw white pattern
+                        if (j<=47 && i>=0) { // draw pattern inside the screen
+                            lcd.clearPixel(i,j);
+                        }
+                    } else if (fill==1) { //draw black pattern
+                        if (j<=47 && i>=0) {
+                            lcd.setPixel(i,j);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+void left_collisionDetect()
+{
+    int left_boundary[6][6];
+    get_pattern(pos.type,pos.rotation);
+
+    /* get the left boundary pixel settings
+       e.g: if pattern is L
+       left boundary is
+       1 0 0 0 0 0
+       1 0 0 0 0 0
+       1 0 0 0 0 0
+       1 0 0 0 0 0
+       1 0 0 0 0 0
+       1 0 0 0 0 0
+    */
+    for (int j=0; j<=5; j++) { //
+        for (int i=0; i<=5; i++) {
+            if (pattern_buffer[i][j]==1) {
+                left_boundary[i][j]=1;
+                for(int k=i+1; k<=5; k++) {
+                    left_boundary[k][j] = 0;
+                }
+                break;
+            } else {
+                left_boundary[i][j]=0;
+            }
+        }
+    }
+
+    //check left collision
+    int x = pos.x;
+    int y = pos.y;
+    if (x<0) { //for all the pattern, when x<0, pattern is on the most LHS of screen
+        left_collision_flag = 1;
+    } else { //check the pixel status away from left boundary for one pixel distance
+        for(int i=x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
+            for(int j=y; j <= y+5; j++) {
+                if(left_boundary[i-x][j-y]==1) {
+                    if(i == 0) { // pattern at most LHS of screen
+                        left_collision_flag = 1;
+                        break; // don't need to check the other pixels at same x, jump out of inner for loop
+                    } else if (lcd.getPixel(i-1,j)) { //check one pixel away from left boundary
+                        left_collision_flag = 1;
+                        break;
+                    } else {
+                        left_collision_flag = 0;
+                    }
+                }
+            }
+            if (left_collision_flag == 1) {
+                break;// jump out of inner for loop
+            }
+        }
+    }
+}
+
+
+void right_collisionDetect()
+{
+    int right_boundary[6][6];
+    get_pattern(pos.type,pos.rotation);
+
+    /* get the right boundary pixel settings
+       e.g: if pattern is L
+       left boundary is
+       0 0 1 0 0 0
+       0 0 1 0 0 0
+       0 0 1 0 0 0
+       0 0 1 0 0 0
+       0 0 0 1 0 0
+       0 0 0 1 0 0
+    */
+    for (int j=0; j<=5; j++) {
+        for (int i=5; i>=0; i--) {
+            if (pattern_buffer[i][j]==1) {
+                right_boundary[i][j]=1;
+                for(int k=i-1; k>=0; k--) {
+                    right_boundary[k][j] = 0;
+                }
+                break;
+            } else {
+                right_boundary[i][j]=0;
+            }
+        }
+    }
+
+    //check right collision
+    int x = pos.x;
+    int y = pos.y;
+    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
+        for(int j=y; j <= y+5; j++) {
+            if(right_boundary[i-x][j-y]==1) {
+                if(j>=0) {
+                    if(i >= 29) { // most RHS of gaming screen
+                        right_collision_flag = 1;
+                        break;
+                    } else if (lcd.getPixel(i+1,j)) {//check the pixel status away from right boundary for one pixel distance
+                        right_collision_flag = 1;
+                        break;
+                    } else {
+                        right_collision_flag = 0;
+                    }
+                }
+            }
+        }
+        if (right_collision_flag == 1) {
+            break;
+        }
+    }
+}
+
+
+void bottom_collisionDetect()
+{
+    int bot_boundary[6][6];
+    get_pattern(pos.type,pos.rotation);
+
+    /* get the left boundary pixel settings
+       e.g: if pattern is L
+       left boundary is
+       0 0 0 0 0 0
+       0 0 0 0 0 0
+       0 0 0 0 0 0
+       0 0 0 0 0 0
+       0 0 0 0 0 0
+       1 1 1 1 0 0
+    */
+    for (int i=0; i<=5; i++) {
+        for (int j=5; j>=0; j--) {
+            if (pattern_buffer[i][j]==1) {
+                bot_boundary[i][j]=1;
+                for(int k=j-1; k>=0; k--) {
+                    bot_boundary[i][k] = 0;
+                }
+                break;
+            } else {
+                bot_boundary[i][j]=0;
+            }
+        }
+    }
+
+    //check bottom collision
+    int x = pos.x;
+    int y = pos.y;
+    for(int i = x; i <= x+5; i++) { //check from left
+        for(int j=y+5; j >= y; j--) { //check from bottom
+            if (j>=-1) { //start check when pattern fall in the screen
+                if(bot_boundary[i-x][j-y]==1) {
+                    if(j >= 47) { // pattern at bottom
+                        bottom_collision_flag = 1;
+                        break; // jump out of inner for loop
+                    } else if (lcd.getPixel(i,j+1)) {//check the pixel status away from bottom boundary for one pixel distance
+                        bottom_collision_flag = 1;
+                        break;
+                    } else {
+                        bottom_collision_flag = 0;
+                    }
+                }
+            } else { //at bottom of screen
+                bottom_collision_flag = 0;
+            }
+        }
+        if( bottom_collision_flag == 1) {
+            break; // jump out of inner for loop
+        }
+    }
+}
+
+
+void rotation_collisionDetect()
+{
+    int rotation = pos.rotation+1;
+    if (rotation>3) {
+        rotation=0;
+    }
+    get_pattern(pos.type,rotation);
+
+    //check pixel status of upcoming rotation
+    int x = pos.x;
+    int y = pos.y;
+    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
+        for(int j=y; j <= y+5; j++) {
+            if(pattern_buffer[i-x][j-y]==1) {
+                if(i<0) { // out of LHS screen
+                    rotation_collision_flag = 1;
+                } else if(lcd.getPixel(i,j)) { // there is pixel set
+                    rotation_collision_flag = 1;
+                    break; //jump out of inner for loop
+                } else {
+                    rotation_collision_flag = 0;
+                }
+            }
+        }
+        if (rotation_collision_flag == 1) {
+            break; //jump out of inner for loop
+        }
+    }
+}
+
+
+void top_collisionDetect()
+{
+    if (pos.y==-6) { //pattern is about to fall
+        bottom_collisionDetect();
+        if (bottom_collision_flag == 1) { //if can't fall
+            top_collision_flag = 1; // top collision
+        } else {
+            top_collision_flag = 0;
+        }
+    }
+}
+
+
+void fastmove_bottom_collisionDetect()
+{
+    int bot_boundary[6][6];
+    get_pattern(pos.type,pos.rotation);
+
+    // get the bottom boundary pattern
+    for (int i=0; i<=5; i++) {
+        for (int j=5; j>=0; j--) {
+            if (pattern_buffer[i][j]==1) {
+                bot_boundary[i][j]=1;
+                for(int k=j-1; k>=0; k--) {
+                    bot_boundary[i][k] = 0;
+                }
+                break;
+            } else {
+                bot_boundary[i][j]=0;
+            }
+        }
+    }
+
+    //check bottom collision for 4 pixel distance away from bottom boundary
+    int x = pos.x;
+    int y = pos.y;
+    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
+        for(int j=y+5; j >= y; j--) {
+            if (j>=-1) {
+                if(bot_boundary[i-x][j-y]==1) {
+                    if(j >= 42) { // pattern is about to fall on the bottom
+                        fastmove_bottom_collision_flag = 1;
+                        break;
+                    } else if (lcd.getPixel(i,j+4)) {//check bottom collision for 4 pixel distance away from bottom boundary
+                        fastmove_bottom_collision_flag = 1;
+                        break;
+                    } else {
+                        fastmove_bottom_collision_flag = 0;
+                    }
+                }
+            } else {
+                fastmove_bottom_collision_flag = 0;
+            }
+        }
+        if( fastmove_bottom_collision_flag == 1) {
+            break;
+        }
+    }
+}
+
+
+void game_isr()
+{
+    g_game_flag = 1;
+}
+
+
+void cancelLine()
+{
+    // int linePattern[30][2]; //the pixel setting for one line(30x2 square)
+    int count; // count setting pixels two by two
+    for(int j=0; j<=46; j+=2) {
+        for(int i=0; i<=29; i++) {
+            if (lcd.getPixel(i,j)==0||lcd.getPixel(i,j+1)==0) { // there is clear pixel
+                count=0;
+                break;
+            } else if (lcd.getPixel(i,j)&&lcd.getPixel(i,j+1)) {
+                count++;
+            }
+        }
+        if(count==30) { // one line is filled
+            count=0; // reset the variable count
+            lcd.drawRect(0,j,29,1,2); //clear the line
+            buzzer = 0.5;
+            score+=10;  // add the score
+            //update the score
+            char scoreBuffer[14];
+            sprintf(scoreBuffer,"%d",score);
+            lcd.printString(scoreBuffer,42,3);
+            scan();
+            // move the patterns above the line down for 2 pixels' hight
+            for (int x=0; x<=29; x++) {
+                for (int y=j; y>=0; y--) {
+                    if (buffer[x][y]) {
+                        lcd.clearPixel(x,y);
+                        lcd.setPixel(x,y+2);
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+void finishAnimation()
+{
+    for (int j=47; j>=0; j--) {
+        lcd.drawRect(0,j,29,1,1);
+        wait(0.05);
+        lcd.refresh();
+    }
+}
+
+
+bool buttonPressedInGame()
+{
+    bool exit_game;
+    if (g_button_flag) { // user press button finish game
+        g_button_flag=0;
+        scan(); // save the currnet gaming screen
+        game.detach(); // detach the game ticker
+        lcd.clear();
+        while(1) {
+            lcd.printString("Exit The Game?",1,1);
+            lcd.printString("YES",38,3);
+            lcd.printString("NO",38,4);
+            pointer(); // invoke pointer function
+            if (g_button_flag) {
+                g_button_flag=0;
+                if(pointer_position==0) { //"YES" -exit game
+                    lcd.clear();
+                    state=0; // back to main menu
+                    pointer_position=0;
+                    exit_game=true;
+                    int stored_score=read_score_SD();
+                    if (score>stored_score) { // if the score is higher than highest score, save it
+                        save_score_SD(score);
+                    }
+                    score=0; //clear socre
+                    red_led=1;
+                    green_led=0;
+                    break;
+                } else { //"NO" - continue the game
+                    exit_game=false;
+                    if(state==3) { // game level is easy
+                        lcd.clear();
+                        for(int i=0; i<=83; i++) { // back to the gaming screen before press button
+                            for(int j=0; j<=47; j++) {
+                                if(buffer[i][j]) {
+                                    lcd.setPixel(i,j);
+                                }
+                            }
+                        }
+                        game.attach(&game_isr,0.2); // easy game
+                        exit_game=false;
+                        break;
+                    } else if(state==4) {// game level is hard
+                        lcd.clear();
+                        for(int i=0; i<=83; i++) {// back to the gaming screen before press button
+                            for(int j=0; j<=47; j++) {
+                                if(buffer[i][j]) {
+                                    lcd.setPixel(i,j);
+                                }
+                            }
+                        }
+                        game.attach(&game_isr,0.1);// hard game
+                        break;
+                    }
+                }
+                break;
+            }
+        }
+    }
+    if(exit_game) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+
+int read_score_SD()
+{
+    fp = fopen("/sd/topscore.txt", "r"); //open file
+    int stored_top_score;
+    fscanf(fp, "%d",&stored_top_score); // ensure data type matches - note address operator (&)
+    fclose(fp);  // ensure you close the file after reading
+    return stored_top_score;
+}
+
+
+void save_score_SD(int score)
+{
+    fp = fopen("/sd/topscore.txt", "w");
+    fprintf(fp, "%d",score); // ensure data type matches
+    fclose(fp);  // ensure you close the file after writing
+}
+#endif
\ No newline at end of file