Mini game developed for ECE 4180 lab

Dependencies:   4DGL-uLCD-SE mbed-rtos mbed

Files at this revision

API Documentation at this revision

Comitter:
slandry8
Date:
Mon Mar 14 17:42:07 2016 +0000
Commit message:
Final build of game for ECE 4180

Changed in this revision

4DGL-uLCD-SE.lib Show annotated file Show diff for this revision Revisions of this file
entity.cpp Show annotated file Show diff for this revision Revisions of this file
entity.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/4DGL-uLCD-SE.lib	Mon Mar 14 17:42:07 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/4180_1/code/4DGL-uLCD-SE/#2cb1845d7681
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/entity.cpp	Mon Mar 14 17:42:07 2016 +0000
@@ -0,0 +1,318 @@
+#include "entity.h"
+void evalScreens(Screen **s) {
+    if((*s[1]).pos > 127) {
+        //delete screen, shift old screen 1 to screen 0, create new screen 1
+        delete s[1];
+        s[1] = s[0];
+        //s[0] = new Screen(0x780D, -127);
+        s[0] = new Screen(0x780D, true,-127);
+    }
+    (*s[0]).decScreen();
+    (*s[1]).decScreen();
+}
+void drawScreens(uLCD_4DGL *u, Screen **s) {
+    //Only draw left-most screen objects if it is not in its initial position 
+    if((*s[0]).pos > -127) {
+        //overwrite previous location of blocks with bg color
+        for(int j = 0;j<=3;j++) {
+            DrawCoverUp((*(*s[0]).obs[j]).row, (*(*s[0]).obs[j]).col - DELTA_X,(*(*s[0]).obs[j]).w - 1,(*(*s[0]).obs[j]).h - 1,u);
+        }
+        //draw obstacles in new positions
+        DrawSliceBySlice((*s[0]).obs[0], u);
+        DrawSliceBySlice((*s[0]).obs[1], u);
+        DrawSliceBySlice((*s[0]).obs[2], u);
+        DrawSliceBySlice((*s[0]).obs[3], u);
+    }
+    //Since s[1] is always on-screen, draw its objects and any necessary cover-up boxes
+    for(int i = 0;i<=3;i++) {
+        DrawCoverUp((*(*s[1]).obs[i]).row, (*(*s[1]).obs[i]).col - DELTA_X,(*(*s[1]).obs[i]).w - 1, (*(*s[1]).obs[i]).h - 1,u);
+    }
+    //draw blocks in new positions
+    DrawSliceBySlice((*s[1]).obs[0], u);
+    DrawSliceBySlice((*s[1]).obs[1], u);
+    DrawSliceBySlice((*s[1]).obs[2], u);
+    DrawSliceBySlice((*s[1]).obs[3], u);
+}
+void drawPlayer(uLCD_4DGL *u, Player *p) {
+    //(*u).filled_rectangle((*p).col,(*p).row,(*p).col + 15,(*p).row + 31, (*p).color);
+    if((*p).isJumping) {
+        (*u).set_sector_address(0x001D, 0x78A5);
+    //set jumping sector
+    } else if((*p).isFalling) {
+        (*u).set_sector_address(0x001D, 0x78A2);
+    //set falling sector
+    } else {
+        (*u).set_sector_address(0x001D, 0x78A8);
+    }
+    //set neutral sector
+    (*u).display_image((*p).col, (*p).row);
+}
+void drawPlayerCoverUp(uLCD_4DGL *u, Player *p) {
+    //(*u).filled_rectangle((*p).col - (((*p).moveFlag & 2) >> 1) + ((*p).moveFlag & 1),(*p).row,(*p).col + 15,(*p).row + 31, 0x000000);
+    (*u).filled_rectangle((*p).col - (DELTA_X_P * (((*p).moveFlag & 2) >> 1)) + (((*p).w * ((*p).moveFlag & 1)) + 0),(*p).row,(*p).col - (1 * (((*p).moveFlag & 2) >> 1)) + ((16 * ((*p).moveFlag & 1)) + (DELTA_X_P * ((*p).moveFlag & 1))),(*p).row + 31, COVER_COLOR);
+}
+void drawPlayerCoverUp(uLCD_4DGL *u, Player *p, int dir) {
+    if((*p).moveFlag == MOVE_RIGHT) {
+        (*u).filled_rectangle((*p).col - DELTA_X_P - 1,(*p).row,(*p).col - 1,(*p).row + (*p).h - 1,COVER_COLOR);
+    }
+    if((*p).moveFlag == MOVE_LEFT) {
+        (*u).filled_rectangle((*p).col + (*p).w,(*p).row,(*p).col + (*p).w + DELTA_X_P + 1,(*p).row + (*p).h - 1,COVER_COLOR);
+    }
+}
+/*void drawPlayerAirborneCoverUp(uLCD_4DGL *u, Player *p) {
+    (*u).filled_rectangle((*p).col, (*p).row - (((*p).isFalling && ((*p).fallCounter >= 0)) ? DELTA_Y : 0) + 
+    (((*p).isJumping && ((*p).upCounter >= 0)) ? 32 : 0),(*p).col + 15, (*p).row - (((*p).isFalling && ((*p).fallCounter >= 0)) ? 1 : 0) + 
+    (((*p).isJumping && ((*p).upCounter >= 0)) ? 32 + DELTA_Y : 0), COVER_COLOR);
+}*/
+void drawPlayerAirborneCoverUp(uLCD_4DGL *u, Player *p) {
+    if((*p).isJumping) {
+        //draw a cover-up box below the player
+        (*u).filled_rectangle((*p).col,(*p).row + (*p).h,(*p).col + (*p).w - 1,(*p).row + (*p).h + DELTA_Y,COVER_COLOR);
+    }
+    if((*p).isFalling) {
+        //draw a cover-up box above the player
+        (*u).filled_rectangle((*p).col,(*p).row - DELTA_Y - 1, (*p).col + (*p).w - 1, (*p).row - 1,COVER_COLOR);
+    }
+}
+void drawPlayerDiagCoverUp(uLCD_4DGL *u, Player *p) {
+    if((*p).isJumping) {
+        if((*p).moveFlag == MOVE_RIGHT) {
+            (*u).filled_rectangle((*p).col - DELTA_X_P,(*p).row + (*p).h, (*p).col - 1, (*p).row + (*p).h +DELTA_Y - 1, COVER_COLOR);
+        }
+        if((*p).moveFlag == MOVE_LEFT) {
+            (*u).filled_rectangle((*p).col + (*p).w,(*p).row + (*p).h, (*p).col + (*p).w + DELTA_X_P - 1, (*p).row + (*p).h + DELTA_Y - 1, COVER_COLOR);
+        }
+    }
+    if((*p).isFalling) {
+        if((*p).moveFlag == MOVE_RIGHT) {
+            (*u).filled_rectangle((*p).col - DELTA_X_P,(*p).row - DELTA_Y,(*p).col - 1, (*p).row - 1,COVER_COLOR);
+        }
+        if((*p).moveFlag == MOVE_LEFT) {
+            (*u).filled_rectangle((*p).col + (*p).w, (*p).row - DELTA_Y, (*p).col + (*p).w + DELTA_X_P - 1, (*p).row - 1, COVER_COLOR);
+        }
+    }
+}
+void DrawIfOnScreen(Obstacle *o, uLCD_4DGL *u) {
+    if(((*o).col >= 0) || (((*o).col + (*o).w - 1) > 0)) { //If entity is on-screen
+        if((*o).col < 0) {
+            (*u).filled_rectangle(0,(*o).row,(*o).w - 1 + (*o).col,(*o).row + (*o).h - 1,(*o).color);//If left side is not on screen
+        } else if(((*o).col + 15) > 127) {
+            (*u).filled_rectangle((*o).col,(*o).row,127,(*o).row + (*o).h - 1,(*o).color);//Else if right side not on screen
+        } else {
+            (*u).filled_rectangle((*o).col,(*o).row,(*o).col + (*o).w - 1,(*o).row + (*o).h - 1,(*o).color); //Else all of the entity is on the screen 
+        }
+    } 
+}
+void DrawSliceBySlice(Obstacle *o, uLCD_4DGL *u) {
+    /*for(int i = 0; i<=15;i++) {
+        if((*o).col + i > 0 && (*o).col + i <= 127) {
+            (*u).set_sector_address(0x001D, 0x788F + i);
+            (*u).display_image((*o).col + i, (*o).row);
+        }
+    }*/
+             //(*u).set_sector_address(0x001D, 0x789F);
+            //(*u).display_image((*o).col, (*o).row); 
+            
+        if(((*o).col >= 0) || (((*o).col + (*o).w - 1) > 0)) { //If entity is on-screen
+        if((*o).col < 0) { //If the left side is off-screen
+            //set sector for particular slice
+            if((*o).w + (*o).col - 2 < 8) {
+                //+1 addition to pick sector
+                (*u).set_sector_address(0x001D, 0x78AB + (*o).w + (*o).col - 2);
+            } else {
+                //+2 addition to pick sector
+                (*u).set_sector_address(0x001D, 0x78B4 + ((((*o).w + (*o).col - 2) % 8) * 2));
+               
+            }
+            //draw the object
+            (*u).display_image(0, (*o).row); 
+        } else if(((*o).col + 15) > 127) { //If the right side is off-screen
+            if(127 - (*o).col < 8) {
+                //-1 to pick sector
+                (*u).set_sector_address(0x001D,0x78D8 - ((127 - (*o).col) % 8));
+            } else {
+                //-2 to pick sector
+                (*u).set_sector_address(0x001D,0x78D2 - (((127 - (*o).col) % 8) * 2));
+            }
+            //draw the object
+            (*u).display_image((*o).col, (*o).row); 
+        } else { //Otherwise the entire object is on-screen
+            (*u).set_sector_address(0x001D, 0x789F);
+            (*u).display_image((*o).col, (*o).row); 
+        }
+    }   
+}
+void DrawCoverUp(int row, int col, int w, int h, uLCD_4DGL *u) {
+    if((col >= 0) || ((col + w) > 0)) { //If entity is on-screen
+        if(col < 0) {
+            //(*u).filled_rectangle(0,row,15+col,row + 15,0x000000);//If left side is not on screen
+        } else if((col + w) > 127) {
+            (*u).filled_rectangle(col,row,col + DELTA_X - 1,row + h,COVER_COLOR);//Else if right side not on screen
+        } else {
+            (*u).filled_rectangle(col,row,col + DELTA_X - 1,row + h,COVER_COLOR); //Else all of the entity is on the screen 
+        }
+    } 
+}
+void drawScenery(uLCD_4DGL *u) {
+    (*u).filled_rectangle(0,0,127,7,0xf09860);
+    (*u).filled_rectangle(0,8,127,15,0xf0a870);
+    (*u).filled_rectangle(0,16,127,23,0xf0b880);
+    (*u).filled_rectangle(0,24,127,31,0xf0c890);
+    (*u).set_sector_address(0x001D,0x791A);
+    (*u).display_image(0,0);
+}
+void drawScore(uLCD_4DGL *u, int score) {
+char scoreChar[15];
+sprintf(scoreChar,"%d",score);
+(*u).textbackground_color(0xf09860);
+(*u).locate(11-strlen(scoreChar),0);
+(*u).printf("Score: %s",scoreChar);
+}
+//Collision detection functions
+void CollisionDetect(Screen **s, Player *p,bool *flag) {
+    if((*s[0]).pos > -127) {
+            //Check if the player has collided with any of s[0]'s objects
+            for(int j = 0;j<=3;j++) {
+                if(detectTR((*s[0]).obs[j],p) || detectBL((*s[0]).obs[j],p) || detectBR((*s[0]).obs[j],p) || detectTL((*s[0]).obs[j],p)) {
+                    //mark player as collided
+                    //(*p).color = 0xFF00FF;
+                    //mark block as collided
+                    //(*(*s[0]).obs[j]).color = 0x00FFFF;
+                    //set the collided flag to true
+                    *flag = true;
+                }
+            }
+    }
+    
+    //Check if the player has collided with any of s[1]'s objects
+    for(int i = 0;i<=3;i++) {
+                if(detectTR((*s[1]).obs[i],p) || detectBL((*s[1]).obs[i],p) || detectBR((*s[1]).obs[i],p) || detectTL((*s[1]).obs[i],p)) {
+                    //mark player as collided
+                    //(*p).color = 0xFF00FF;
+                    //mark block as collided
+                    //(*(*s[1]).obs[i]).color = 0x00FFFF;
+                    //set the collided flag to true
+                    *flag = true;
+                }
+            }
+}
+bool detectTR(Obstacle *o,Player *p) {
+    //return true if the top right corner of the player overlaps with an object
+    return ((((*o).col + (*o).w - 1) >= (*p).col) && (((*o).col + (*o).w - 1) <= (*p).col + (*p).w - 1) 
+    && (((*o).row >= (*p).row) && ((*o).row <= ((*p).row + (*p).h - 1))));
+}
+bool detectBL(Obstacle *o,Player *p) {
+    //return true if the bottom left corner of the player overlaps with an object
+    return ((((*o).col) >= (*p).col) && (((*o).col) <= (*p).col + (*p).w - 1) 
+    && (((*o).row + (*o).h - 1 >= (*p).row) && ((*o).row + (*o).h - 1 <= ((*p).row + (*p).h - 1))));
+}
+bool detectBR(Obstacle *o,Player *p) {
+    //return true if the bottom right corner of the player overlaps with an object
+    return ((((*o).col + (*o).w - 1) >= (*p).col) && (((*o).col + (*o).w - 1) <= (*p).col + (*p).w - 1) 
+    && (((*o).row + (*o).h - 1 >= (*p).row) && ((*o).row + (*o).h - 1 <= ((*p).row + (*p).h - 1))));
+}
+bool detectTL(Obstacle *o, Player *p) {
+    //return true if the top left corner of the player overlaps with an object
+    return ((((*o).col) >= (*p).col) && (((*o).col) <= (*p).col + (*p).w - 1)
+    && (((*o).row >= (*p).row) && ((*o).row <= ((*p).row + (*p).h - 1))));
+}
+/*
+//functions that belong to the Screen class
+*/
+void Screen::decScreen(void) {
+    //increment screen position and object positions so that they can move off-screen
+    pos+=DELTA_X;
+    (*obs[0]).col+=DELTA_X;
+    (*obs[1]).col+=DELTA_X;
+    (*obs[2]).col+=DELTA_X;
+    (*obs[3]).col+=DELTA_X;
+    //decrement position of objects associated with screen
+}
+Screen::Screen(int bg, int initPos) {
+    bgAddr = bg;
+    pos = initPos;
+    int j;
+    for(j = 0;j<=3;j++) {
+        obs[j] = new Obstacle(0x00FF00);
+        (*obs[j]).col = initPos + (16*j) + j;
+        (*obs[j]).row = 111;
+    }
+}
+//new default constructor
+Screen::Screen(int bg, bool randomSpots, int initPos) {
+    pos = initPos;
+    for(int j = 0;j<=3;j++) {
+        obs[j] = new Obstacle(0x0000FF);
+    }
+    //Pick random locations within the screen for the objects
+    (*obs[0]).col = initPos + (rand() % 2) * 16;
+    (*obs[1]).col = ((rand() % 2) * 16) + (*obs[0]).col;
+    (*obs[2]).col = ((rand() % 2) * 16) + (*obs[1]).col;
+    (*obs[3]).col = ((rand() % 2) * 16) + (*obs[2]).col;
+    //set height to either 16 or 32 pixels for object
+    for(int j = 0;j<=3;j++) {
+        (*obs[j]).h = ((rand() % 2) == 1 ? H_32 : H_16);
+        (*obs[j]).w = H_16;
+        (*obs[j]).row = 127-(*obs[j]).h;
+    }    
+}
+Screen::~Screen(void) {
+    //free the space for the deleted screen's obstacles in memory
+    delete obs[0];
+    delete obs[1];
+    delete obs[2];
+    delete obs[3];
+}
+/*
+//Functions that belong to the Obstacle class
+*/
+Obstacle::Obstacle(int c) {
+    color = c;
+    w = 16;
+    h = 16;
+    row = 0;
+    col = 0;
+}
+/*
+//Function that belong to the Player class
+*/
+Player::Player(void) {
+    //set default variables so that the player is in the bottom-right corner when the game begins
+    w = H_16;
+    h = H_32;
+    color = 0xFF0000; //color is deprecated, since we're using images now
+    col = 111;
+    row = 95;
+    hasMoved = false;
+    moveFlag = 0;
+    isFalling = false;
+    isJumping = false;
+    upCounter = -1;
+    fallCounter = -1;
+}
+/*
+// Functions that belong to the cursor class
+*/
+Cursor::Cursor(void) {
+    //set default cursor position so that the cursor is over 'A' on the high score screen
+    row = 30;
+    col = 5;
+    s = 10;
+    curChar = 'A';
+    delta_x = 14;
+    delta_y = 16;
+    hasMoved = false;
+    letterPressed = false;
+    c = 0;
+    moveFlag = 0;
+}
+void Cursor::draw(uLCD_4DGL *u) {
+    //draw the cursor rectangle at the current position
+    (*u).rectangle(col,row,col + s,row + s,0xFF3300);
+}
+void Cursor::coverUp(uLCD_4DGL *u) {
+    //draw a rectangle with the BG color at the previous cursor position to cover up the rectangle left behind by previous draw function
+    (*u).rectangle(col + ((moveFlag & MOVE_LEFT) * ((delta_x - s) + s)) - (((moveFlag & MOVE_RIGHT) >> 1) * ((delta_x - s) + s)), row + (((moveFlag & MOVE_UP)>>2) * ((delta_y - s) + s)) - (((moveFlag & MOVE_DOWN)>>3) * ((delta_y - s) + s)),
+    (col + s) + ((moveFlag & MOVE_LEFT)*  ((delta_x - s) + s)) - (((moveFlag & MOVE_RIGHT) >> 1) * ((delta_x - s) + s)), row + s + (((moveFlag & MOVE_UP)>>2) * ((delta_y - s) + s)) - (((moveFlag & MOVE_DOWN)>>3) * ((delta_y - s) + s)),
+    COVER_COLOR);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/entity.h	Mon Mar 14 17:42:07 2016 +0000
@@ -0,0 +1,146 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "uLCD_4DGL.h"
+#define DELTA_Y 3
+#define DELTA_X 3
+#define DELTA_X_P 2
+#define COVER_COLOR 0xf0c890
+#define H_32 32
+#define H_16 16
+#define STATE_START 0
+#define STATE_GAME 1
+#define STATE_LOSE 2
+#define STATE_SCORE 4
+#define MOVE_LEFT 1
+#define MOVE_RIGHT 2
+#define MOVE_UP 4
+#define MOVE_DOWN 8
+
+class Entity {
+    private:
+    public:
+    //y position of an entity (in pixels)
+    int row;
+    //x position of an entity (in pixels)
+    int col;
+    
+    };
+class Cursor : public Entity {
+    public:
+    //size of the s by s square cursor
+    int s;
+    //space that the cursor will move when the joystick is pressed left or right
+    int delta_x;
+    //space that the cursor will move when the joystick is pressed up or down
+    int delta_y;
+    //buffer that will contain the initials for a new high score
+    char initBuf[3];
+    int c;
+    //flag to see if the user moved the cursor
+    bool hasMoved;
+    //flag to see if the user has pressed the fire button on the high score screen
+    bool letterPressed;
+    //numerical value assoicated with a particular movement
+    int moveFlag;
+    //the last letter that the cursor selected on letterPressed
+    char curChar;
+    //default no-arg constructor
+    Cursor(void);
+    //function to draw the cursor on screen
+    void draw(uLCD_4DGL *u);
+    //function to cover up the previous position of the cursor
+    void coverUp(uLCD_4DGL *u);
+};
+class Player : public Entity {
+    public:
+    //Width of the p;ayer in pixels
+    int w;
+    //Height of the player in pixels
+    int h;
+    //(deprecated) color of the player in RGB
+    int color;
+    //default no-arg constructor
+    Player(void);
+    //flag to see if the user has moved using the joystick
+    bool hasMoved;
+    //flag to see if the user is jumping
+    bool isJumping;
+    //flag to see if the user is falling
+    bool isFalling;
+    //Used to keep track of how long until the player reaches the apex of the jump
+    int upCounter; 
+    //Used to check how long until the player lands
+    int fallCounter; 
+    //value representing some movement of direction
+    int moveFlag;
+};
+class Obstacle : public Entity {
+    public:
+    //(deprecated) color of the obstacle in RGB
+    int color;
+    //width of the obstacle in pixels
+    int w;
+    //height of the obstacle in pixels
+    int h;
+    //default constructor; color input variable is deprecated
+    Obstacle(int c);
+};
+class Counter : public Entity {
+};
+class Screen {
+private:
+public:
+//(deprecated) sector address of the screen's background
+int bgAddr;
+//current position, on or off-screen, in pixels
+int pos;
+//
+void drawScreen(void);
+//increase the position values of each object and screen, so that they appear to be moving
+void decScreen(void);
+//default constructor
+Screen(int bg, int initPos);
+//main constructor, though the boolean flag serves no purpose and should be removed
+Screen(int bg, bool randomSpots, int initPos);
+//the 4 cactus obstacles associated with this screen
+Obstacle *obs[4];
+//Class destructor.  Needed to delete both the screen and its associated obstacle objects
+~Screen(void);
+};
+//(Deprecated) draw the rectangles of the obstacles while also checking if they are on-screen
+void DrawIfOnScreen(Obstacle *o, uLCD_4DGL *u);
+//draw the cactus image for each obstacle, also checking if any part of the obstacle is off-screen, and drawing the appropriate image if so
+void DrawSliceBySlice(Obstacle *o, uLCD_4DGL *u);
+//Draw a filled rectangle with the background color to hide the pixels of the previous position of an object
+void DrawCoverUp(int row, int col, int w, int h, uLCD_4DGL *u);
+//Check if any screens are now past the player, and rearrange the screens if so
+void evalScreens(Screen **s);
+//draw all objects associated with a screen
+void drawScreens(uLCD_4DGL *u, Screen **s);
+//draw the player sprite
+void drawPlayer(uLCD_4DGL *u, Player *p);
+//(deprecated) draw the cover up rectangle for x-axis movement of the player
+void drawPlayerCoverUp(uLCD_4DGL *u, Player *p);
+//Draw the cover up rectangle for x-axis movement of the player
+void drawPlayerCoverUp(uLCD_4DGL *u, Player *p, int dir);
+//draw the cover up rectangle for y-axis movement of the player
+void drawPlayerAirborneCoverUp(uLCD_4DGL *u, Player *p);
+//Cover up the small square that occurs if the user moves diagonally
+void drawPlayerDiagCoverUp(uLCD_4DGL *u, Player *p);
+//Draw the sun and any other background objects
+void drawScenery(uLCD_4DGL *u);
+//Collision Detection
+//check a collision on the top-right corner of the player
+bool detectTR(Obstacle *o,Player *p);
+//check a collision on the bottom-left corner of the player
+bool detectBL(Obstacle *o,Player *p);
+//check a collision on the bottom-right corner of the player
+bool detectBR(Obstacle *o,Player *p);
+//check a collision on the top-left corner of the player
+bool detectTL(Obstacle *o, Player *p);
+//main function for collision detection; runs previous four functions and sets appropriate flags
+void CollisionDetect(Screen **s, Player *p,bool *flag);
+//draw the score counter on the right side of the screen
+void drawScore(uLCD_4DGL *u, int score);
+//Reset flags and other objects for a new game
+void initialize(Screen **s, Player *p, int *score, bool* initFlash, bool *scDrawn, bool *collide, int *c, int *r, Cursor *curs);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Mar 14 17:42:07 2016 +0000
@@ -0,0 +1,436 @@
+// Cactus Jumper video game
+//
+#include "mbed.h"
+#include "rtos.h"
+#include "uLCD_4DGL.h"
+#include "entity.h"
+
+
+uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin;
+Mutex posMutex;
+int state = STATE_START;
+int score;
+int k;
+char *scCompBuf;
+char *writtenScore;
+char *scoreStr;
+bool initialFlash = false;
+bool scoreDrawn = false;
+bool collided = false;
+bool newHighScore = false;
+bool titleDrawn = false;
+char readchar = ' ';
+class Nav_Switch
+{
+public:
+    Nav_Switch(PinName up,PinName down,PinName left,PinName right,PinName fire);
+    int read();
+//boolean functions to test each switch
+    bool up();
+    bool down();
+    bool left();
+    bool right();
+    bool fire();
+//automatic read on RHS
+    operator int ();
+//index to any switch array style
+    bool operator[](int index) {
+        return _pins[index];
+    };
+private:
+    BusIn _pins;
+ 
+};
+Nav_Switch::Nav_Switch (PinName up,PinName down,PinName left,PinName right,PinName fire):
+    _pins(up, down, left, right, fire)
+{
+    _pins.mode(PullUp); //needed if pullups not on board or a bare nav switch is used - delete otherwise
+    //Thread::wait(1); //delays just a bit for pullups to pull inputs high
+    wait(0.001);
+}
+inline bool Nav_Switch::up()
+{
+    return !(_pins[0]);
+}
+inline bool Nav_Switch::down()
+{
+    return !(_pins[1]);
+}
+inline bool Nav_Switch::left()
+{
+    return !(_pins[2]);
+}
+inline bool Nav_Switch::right()
+{
+    return !(_pins[3]);
+}
+inline bool Nav_Switch::fire()
+{
+    return !(_pins[4]);
+}
+inline int Nav_Switch::read()
+{
+    return _pins.read();
+}
+inline Nav_Switch::operator int ()
+{
+    return _pins.read();
+}
+ 
+Nav_Switch myNav( p25, p22, p23, p21, p24);
+int i = 111; //variable used for horizontal player movement
+int j = 96; //variable used for vertical player movement
+//initialize player and cursor 
+Player *player = new Player();
+Cursor *curs = new Cursor();
+//thread for player input detection
+void fire_thread(void const *args) {
+    while(true) {
+        //if player moves to the right during gameplay
+        if(myNav.right() && state == STATE_GAME) {
+             posMutex.lock();
+            i = ((i > 110) ? 110 : i + DELTA_X_P);
+            (*player).col = i;
+            (*player).hasMoved = true;
+            (*player).moveFlag = 2;
+             posMutex.unlock();
+             Thread::wait(35);
+        }
+        //if player moves to the left during gameplay
+        if(myNav.left() && state == STATE_GAME) {
+            posMutex.lock();
+            i = ((i < 2) ? 2 : i - DELTA_X_P);
+            (*player).col = i;
+            (*player).hasMoved = true;
+            (*player).moveFlag = 1;
+            posMutex.unlock();
+            Thread::wait(35);
+        }
+        posMutex.lock();
+        //if player jumps during gameplay and is not already in the jumping or falling state
+        if((myNav.up() && !((*player).isJumping || (*player).isFalling)) && state == STATE_GAME) {
+            (*player).isJumping = true;
+            (*player).upCounter = 48;
+            (*player).fallCounter = 48;
+        }
+        posMutex.unlock();
+        //if fire is pressed on start screen, begin game
+        if(myNav.fire() && state != STATE_GAME && state != STATE_SCORE && state != STATE_LOSE) {
+            state = STATE_GAME;
+            Thread::wait(35);
+        }
+        //Go to either start screen or new height screen when fire is pressed on game over screen
+        if(myNav.fire() && state == STATE_LOSE) {
+            if(!newHighScore) {
+                titleDrawn = false;
+                state = STATE_START;
+            } else {
+                state = STATE_SCORE;
+            }
+            Thread::wait(500);
+        }
+        //Navigation controls for high score screen
+        //if fire is pressed on the new high score screen
+        if(myNav.fire() && state == STATE_SCORE) {
+            //check whether to enter an initial or begin writing initials to file
+            if((*curs).curChar >= 'A' && (*curs).curChar <= 'Z') {
+                (*curs).initBuf[(*curs).c] = (*curs).curChar;
+            }
+            (*curs).letterPressed = true;
+            Thread::wait(200);
+        }
+        //If up is pressed on the new high score screen
+        if(myNav.up() && state == STATE_SCORE) {
+            //make sure cursor would not go out of bounds if moved
+            if(!((*curs).curChar - 8 < 'A')) {
+            (*curs).row -= (*curs).delta_y;
+            (*curs).hasMoved = true;
+            (*curs).moveFlag = 4;
+            (*curs).curChar-=8;
+            }
+            Thread::wait(100);
+        }
+        //If down is pressed on the new high score screen
+        if(myNav.down() && state == STATE_SCORE) {
+            //make sure cursor would not go out of boudns if moved
+            if(!((*curs).curChar + 8 > '[')) {
+            (*curs).row += (*curs).delta_y;
+            (*curs).hasMoved = true;
+            (*curs).moveFlag = 8;
+            (*curs).curChar+=8;
+            }
+            Thread::wait(100);
+        }
+        //If left is pressed on the new high score screen
+        if(myNav.left() && state == STATE_SCORE) {
+            //make sure cursor would not go out of boudns if moved
+            if(!((*curs).curChar == 'A') && !((*curs).curChar == 'I') && !((*curs).curChar == 'Q') && !((*curs).curChar == 'Y')) {
+            (*curs).col -= (*curs).delta_x;
+            (*curs).hasMoved = true;
+            (*curs).moveFlag = 1;
+            (*curs).curChar--;
+            }
+            Thread::wait(100);
+        }
+        //If right is pressed on the new high score screen
+        if(myNav.right() && state == STATE_SCORE) {
+            //make sure cursor would not go out of boudns if moved
+            if(!((*curs).curChar == 'H') && !((*curs).curChar == 'P') && !((*curs).curChar == 'X') && !((*curs).curChar == '[')) {
+            (*curs).col += (*curs).delta_x;
+            (*curs).hasMoved = true;
+            (*curs).moveFlag = 2;
+            (*curs).curChar++;
+            }
+            Thread::wait(100);
+        }
+    }
+}
+int main()
+{
+        //create thread for handling user input
+        Thread thread(fire_thread);
+        //initialize screen pointer array; allocate screen objects in memory
+        Screen *screenP[2];
+        screenP[0] = new Screen(0x780D,true,-127);
+        screenP[1] = new Screen(0x780D,true,0);
+        //set baud rate & initialize media on uLCD
+        uLCD.baudrate(3000000);
+        uLCD.media_init();
+        while(true) {
+            if(!(state | STATE_START)) {
+                //start screen
+                if(!titleDrawn) { //we want to only draw this information once
+                    newHighScore = false;
+                    //initialize game information
+                    initialize(screenP, player, &score, &initialFlash, &scoreDrawn, &collided, &i, &j, curs);
+                    //draw title screen and text
+                    uLCD.set_sector_address(0x001D, 0x78D9);
+                    uLCD.display_image(0,0);
+                    uLCD.textbackground_color(0x8f7738);
+                    uLCD.locate(3,12);
+                    uLCD.color(RED);
+                    uLCD.printf("Press fire");
+                    uLCD.locate(4,13);
+                    uLCD.printf("to start");
+                    uLCD.background_color(COVER_COLOR);
+                    //read in high score to display
+                    uLCD.set_sector_address(0x001D, 0x8700);
+                    uLCD.locate(3,15);
+                    readchar = ' ';
+                    while(readchar != '\xFF') {
+                        readchar = uLCD.read_byte();
+                        uLCD.putc(readchar);
+                    }
+                }
+                titleDrawn = true;
+                score = 0;
+                //The remainder of this if() causes the "blinking" of the "Press fire to start" on the title screen
+                Thread::wait(250);
+                uLCD.locate(3,12);
+                uLCD.color(0x8f7738);
+                uLCD.printf("Press fire");
+                uLCD.locate(4,13);
+                uLCD.printf("to start");
+                Thread::wait(250);
+                uLCD.locate(3,12);
+                uLCD.color(RED);
+                uLCD.printf("Press fire");
+                uLCD.locate(4,13);
+                uLCD.printf("to start");
+            } else if(state & STATE_GAME) {
+                
+                if(!initialFlash) {
+                    //we want to clear the screen and draw the background scenery only once when the game starts
+                    uLCD.filled_rectangle(0,0,127,127,COVER_COLOR);
+                    drawScenery(&uLCD);
+                    initialFlash = true;
+                }
+                //draw the obstacles
+                drawScreens(&uLCD, screenP);
+                posMutex.lock();
+                if((*player).isJumping || (*player).isFalling) {
+                    //check if end conditions for each state is currently met
+                    if(((*player).upCounter < 0) && ((*player).isJumping)) {
+                        //if the player has reached the top of their jump
+                        (*player).isJumping = false;
+                    }
+                    if(((*player).fallCounter < 0) && ((*player).isFalling)) {
+                        //if the player has stopped falling
+                        (*player).isFalling = false;
+                    }
+                    //check if the player can enter into a new state
+                    if(!(*player).isJumping && ((*player).fallCounter > 0) && (!(*player).isFalling)) {
+                        //set the falling condition for the player
+                        (*player).isFalling = true;
+                    }
+                //decrement jumping or falling counters, if applicable
+                    if((*player).isFalling) {
+                        (*player).row+=DELTA_Y;
+                        (*player).fallCounter-=DELTA_Y;
+                    }
+                    if((*player).isJumping) {
+                        (*player).row-=DELTA_Y;
+                        (*player).upCounter-=DELTA_Y;
+                    }
+                    drawPlayerAirborneCoverUp(&uLCD, player);
+                    if((*player).hasMoved) {
+                        drawPlayerDiagCoverUp(&uLCD, player);
+                    }
+                }
+                if((*player).hasMoved) {
+                    //cover up residual pixels from previous location of the player if they have moved
+                    //drawPlayerCoverUp(&uLCD, player);
+                    drawPlayerCoverUp(&uLCD, player, (*player).moveFlag);
+                }
+                (*player).hasMoved = false;
+                (*player).moveFlag = 0;
+                //detect collision
+                CollisionDetect(screenP,player,&collided);
+                if(collided) {
+                    //player has lost if collision detected
+                    state = STATE_LOSE;
+                }
+                drawPlayer(&uLCD, player);
+                drawScore(&uLCD, score);
+                posMutex.unlock();            
+                //Evaluate screens, delete old off-screen screens if necessary, and update the score
+                evalScreens(screenP);
+                score++;
+            } else if((state & STATE_LOSE) >> 1) {
+                //draw game over screen, plus NEW HIGH SCORE text if applicable
+                uLCD.textbackground_color(0xf09860);
+                uLCD.locate(6,0);
+                uLCD.printf("GAME OVER   ");
+                uLCD.set_sector_address(0x001D, 0x9300);
+                uLCD.locate(1,1);
+                k = 0;
+                if(scCompBuf != NULL) {
+                    //delete the previous score that was checked if the game has run once before
+                    delete scCompBuf;
+                }
+                scCompBuf = new char[15];
+                readchar = ' ';
+                //read in the score from the memory location on the SD card
+                while(readchar != '\xFF') {
+                    readchar = uLCD.read_byte();
+                    if(readchar >= '0' && readchar <= '9') {
+                    scCompBuf[k] = readchar;
+                    }
+                    k++;
+                }
+                //determine if player should go to high score or title screen on fire
+                if(score > atoi(scCompBuf)) {
+                    //new high score
+                    newHighScore = true;
+                    uLCD.locate(3,3);
+                    uLCD.textbackground_color(COVER_COLOR);
+                    uLCD.printf("NEW HIGH SCORE");
+                }
+            } else if((state & STATE_SCORE) >> 2) {
+            //name entry for new high score
+            if(!scoreDrawn) {
+                //Only draw background pieces once   
+                uLCD.filled_rectangle(0,0,127,127,COVER_COLOR);
+                uLCD.locate(0,0);
+                uLCD.textbackground_color(COVER_COLOR);
+                uLCD.printf("HIGH SCORE: %d\n\n", score);
+                uLCD.printf("Initials:\n\n");
+                uLCD.locate(0,4);
+                //Letter select for initials
+                uLCD.printf(" A B C D E F G H \n\n");
+                uLCD.printf(" I J K L M N O P \n\n");
+                uLCD.printf(" Q R S T U V W X \n\n");
+                uLCD.printf(" Y Z ");
+                uLCD.filled_rectangle(36,81,40,85,0x000000);
+                (*curs).draw(&uLCD);
+                scoreDrawn = true;
+            }
+            if((*curs).letterPressed) {
+            //draw initials
+                if((*curs).curChar >= 'A' && (*curs).curChar <= 'Z') { //If selected character is not the END character
+                    //pick correct location on screen to draw initial
+                    uLCD.locate(10+(*curs).c,2);
+                    uLCD.printf("%c",(*curs).initBuf[(*curs).c]);
+                    (*curs).c = (((*curs).c < 2) ? (*curs).c + 1 : 2);
+                    (*curs).letterPressed = false;
+                } else {
+                //write score to file
+                if(writtenScore == NULL) {
+                    //allocate array
+                    writtenScore = new char[4 + 15];   
+                } else {
+                    delete writtenScore;
+                    writtenScore = new char[4 + 15];
+                }
+                if(scoreStr != NULL) {
+                    //delete any previous string representation of score
+                    delete scoreStr;
+                }
+                scoreStr = new char[15];
+                //write score to display into a character array 
+                sprintf(writtenScore,"%s     %d",(*curs).initBuf,score);
+                //overwrite 0 that would appear after initials on score screen with blank space
+                writtenScore[3] = ' ';
+                //set location of title screen display score
+                uLCD.set_sector_address(0x001D, 0x8700);
+                uLCD.locate(0,12);
+                uLCD.printf("\n\nStoring score...");
+                for (int i=0; i<strlen(writtenScore); i++) {
+                    uLCD.write_byte(writtenScore[i]); //write a byte to SD card
+                }
+                uLCD.flush_media();
+                //set location for only the score
+                uLCD.set_sector_address(0x001D, 0x9300);
+                //read in score to character array
+                sprintf(scoreStr,"%d",score);
+                for (int i=0; i<strlen(scoreStr); i++) {
+                    uLCD.write_byte(scoreStr[i]); //write a byte to SD card
+                }
+                //Reset game once score has been saved
+                titleDrawn = false;
+                state = STATE_START;
+                }
+            }
+            if((*curs).hasMoved) {
+                //cover up old cursor
+                (*curs).coverUp(&uLCD);
+                //draw new cursor
+                (*curs).draw(&uLCD);
+                (*curs).hasMoved = false;
+                (*curs).moveFlag = 0;
+            }
+        }
+    }
+}
+
+void initialize(Screen **s, Player *p, int *score, bool* initFlash, bool *scDrawn, bool *collide, int *c, int *r, Cursor *curs) {
+        //initialize screen (only delete if the screen pointer is not a null pointer
+        if(s[0] != NULL) {
+            delete s[0];
+        }
+        if(s[1] != NULL) {
+            delete s[1];
+        }
+        s[0] = new Screen(0x780D,true,-127);
+        s[1] = new Screen(0x780D,true,0);
+        //Initialize or re-initialize player
+        if(p != NULL) {
+            delete p;
+        }
+        p = new Player();
+        *score = 0;
+        //Initialize or re-initialize flags used during gameplay
+        *initFlash = false;
+        *scDrawn = false;
+        *collide = false;
+        *c = 111;
+        *r = 96;
+        //Initialize or re-initialize the cursor
+        if(curs != NULL) {
+            delete curs;
+        }
+        curs = new Cursor();
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Mon Mar 14 17:42:07 2016 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/mbed_official/code/mbed-rtos/#07314541bd12
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Mar 14 17:42:07 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/34e6b704fe68
\ No newline at end of file