Mini game developed for ECE 4180 lab
Dependencies: 4DGL-uLCD-SE mbed-rtos mbed
Revision 0:a358215f57b7, committed 2016-03-14
- Comitter:
- slandry8
- Date:
- Mon Mar 14 17:42:07 2016 +0000
- Commit message:
- Final build of game for ECE 4180
Changed in this revision
diff -r 000000000000 -r a358215f57b7 4DGL-uLCD-SE.lib --- /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
diff -r 000000000000 -r a358215f57b7 entity.cpp --- /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
diff -r 000000000000 -r a358215f57b7 entity.h --- /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
diff -r 000000000000 -r a358215f57b7 main.cpp --- /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(); +} + + +
diff -r 000000000000 -r a358215f57b7 mbed-rtos.lib --- /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
diff -r 000000000000 -r a358215f57b7 mbed.bld --- /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