My ELEC2645 joystick project Tetris Game NAME: JIANWEI CHEN SID: 200879849
Dependencies: N5110 SDFileSystem mbed
Game.h@4:463abe5f5135, 2016-05-05 (annotated)
- Committer:
- cjw851102
- Date:
- Thu May 05 09:18:01 2016 +0000
- Revision:
- 4:463abe5f5135
Final version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
cjw851102 | 4:463abe5f5135 | 1 | /** |
cjw851102 | 4:463abe5f5135 | 2 | @file Game.h |
cjw851102 | 4:463abe5f5135 | 3 | @brief Header file containing functions prototypes, defines and global variables for the tetris game. |
cjw851102 | 4:463abe5f5135 | 4 | @brief Revision 1.0. |
cjw851102 | 4:463abe5f5135 | 5 | @author JIANWEI CHEN |
cjw851102 | 4:463abe5f5135 | 6 | @date May 2016 |
cjw851102 | 4:463abe5f5135 | 7 | */ |
cjw851102 | 4:463abe5f5135 | 8 | |
cjw851102 | 4:463abe5f5135 | 9 | #ifndef GAME_H |
cjw851102 | 4:463abe5f5135 | 10 | #define GAME_H |
cjw851102 | 4:463abe5f5135 | 11 | |
cjw851102 | 4:463abe5f5135 | 12 | #include "mbed.h" |
cjw851102 | 4:463abe5f5135 | 13 | #include "Patterns.h" |
cjw851102 | 4:463abe5f5135 | 14 | #include "N5110.h" |
cjw851102 | 4:463abe5f5135 | 15 | #include "SDFileSystem.h" |
cjw851102 | 4:463abe5f5135 | 16 | #include "main.h" |
cjw851102 | 4:463abe5f5135 | 17 | |
cjw851102 | 4:463abe5f5135 | 18 | //! Create patterns object |
cjw851102 | 4:463abe5f5135 | 19 | Patterns patterns; |
cjw851102 | 4:463abe5f5135 | 20 | /** |
cjw851102 | 4:463abe5f5135 | 21 | Create ticker object for game |
cjw851102 | 4:463abe5f5135 | 22 | @brief ticker to control the speed of game |
cjw851102 | 4:463abe5f5135 | 23 | */ |
cjw851102 | 4:463abe5f5135 | 24 | Ticker game; |
cjw851102 | 4:463abe5f5135 | 25 | |
cjw851102 | 4:463abe5f5135 | 26 | //////////////////////////////////////////////////////// |
cjw851102 | 4:463abe5f5135 | 27 | // Variables |
cjw851102 | 4:463abe5f5135 | 28 | //////////////////////////////////////////////////////// |
cjw851102 | 4:463abe5f5135 | 29 | |
cjw851102 | 4:463abe5f5135 | 30 | int xOld; /*!< Variable for storing the pattern previous position when game is runnung */ |
cjw851102 | 4:463abe5f5135 | 31 | int typeCount = 0; /*!< Variable for counting elements in array typeArray[100]*/ |
cjw851102 | 4:463abe5f5135 | 32 | int nextTypeCount; /*!< Variable to show the position of next element in typeArray[100] i.e. nextTypeCount=typeCount+1*/ |
cjw851102 | 4:463abe5f5135 | 33 | |
cjw851102 | 4:463abe5f5135 | 34 | /** Flag to show left hand side conllision of pattern |
cjw851102 | 4:463abe5f5135 | 35 | @note flag = 0 - there is no collision on the left |
cjw851102 | 4:463abe5f5135 | 36 | @note flag = 1 - there is collision on the left |
cjw851102 | 4:463abe5f5135 | 37 | */ |
cjw851102 | 4:463abe5f5135 | 38 | int left_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 39 | |
cjw851102 | 4:463abe5f5135 | 40 | /** Flag to show right hand side conllision of pattern |
cjw851102 | 4:463abe5f5135 | 41 | @note flag = 0 - there is no collision |
cjw851102 | 4:463abe5f5135 | 42 | @note flag = 1 - there is collision |
cjw851102 | 4:463abe5f5135 | 43 | */ |
cjw851102 | 4:463abe5f5135 | 44 | int right_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 45 | |
cjw851102 | 4:463abe5f5135 | 46 | /** Flag to show bottom conllision of pattern |
cjw851102 | 4:463abe5f5135 | 47 | @note flag = 0 - there is no collision |
cjw851102 | 4:463abe5f5135 | 48 | @note flag = 1 - there is collision |
cjw851102 | 4:463abe5f5135 | 49 | */ |
cjw851102 | 4:463abe5f5135 | 50 | int bottom_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 51 | |
cjw851102 | 4:463abe5f5135 | 52 | /** Flag to show top conllision of pattern |
cjw851102 | 4:463abe5f5135 | 53 | @note flag = 0 - there is no collision |
cjw851102 | 4:463abe5f5135 | 54 | @note flag = 1 - there is collision |
cjw851102 | 4:463abe5f5135 | 55 | */ |
cjw851102 | 4:463abe5f5135 | 56 | int top_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 57 | |
cjw851102 | 4:463abe5f5135 | 58 | /** Flag to show if there is pixels set on the 4 pixels distance away from the bottom of pattern |
cjw851102 | 4:463abe5f5135 | 59 | @brief if flag = 0, user can pull joystick down to make pattern falling faster |
cjw851102 | 4:463abe5f5135 | 60 | @note flag = 0 - there is no collision |
cjw851102 | 4:463abe5f5135 | 61 | @note flag = 1 - there is collision |
cjw851102 | 4:463abe5f5135 | 62 | */ |
cjw851102 | 4:463abe5f5135 | 63 | int fastmove_bottom_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 64 | |
cjw851102 | 4:463abe5f5135 | 65 | /** Flag to show if allow patterns to rotate |
cjw851102 | 4:463abe5f5135 | 66 | @note flag = 0 - allow |
cjw851102 | 4:463abe5f5135 | 67 | @note flag = 1 - not allow |
cjw851102 | 4:463abe5f5135 | 68 | */ |
cjw851102 | 4:463abe5f5135 | 69 | int rotation_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 70 | |
cjw851102 | 4:463abe5f5135 | 71 | /** Two dimension array to store current pattern pixels setting in a 6x6 square |
cjw851102 | 4:463abe5f5135 | 72 | @note For example, if current pattern is "L" |
cjw851102 | 4:463abe5f5135 | 73 | @note the pixels setting is |
cjw851102 | 4:463abe5f5135 | 74 | @note 1 1 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 75 | @note 1 1 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 76 | @note 1 1 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 77 | @note 1 1 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 78 | @note 1 1 1 1 0 0 |
cjw851102 | 4:463abe5f5135 | 79 | @note 1 1 1 1 0 0 |
cjw851102 | 4:463abe5f5135 | 80 | */ |
cjw851102 | 4:463abe5f5135 | 81 | int pattern_buffer[6][6]; |
cjw851102 | 4:463abe5f5135 | 82 | |
cjw851102 | 4:463abe5f5135 | 83 | /** Array to store types of pattern |
cjw851102 | 4:463abe5f5135 | 84 | @brief 100 random integers in the range of 0~6 |
cjw851102 | 4:463abe5f5135 | 85 | @brief will be stored in the array in order to generate |
cjw851102 | 4:463abe5f5135 | 86 | @brief random type of pattern each time new pattern is generated |
cjw851102 | 4:463abe5f5135 | 87 | */ |
cjw851102 | 4:463abe5f5135 | 88 | int typeArray[100]; |
cjw851102 | 4:463abe5f5135 | 89 | int buffer[84][48]; /*!< Array to store whole screen pixel settings */ |
cjw851102 | 4:463abe5f5135 | 90 | int score=0; /*!< Variable to store score in the game */ |
cjw851102 | 4:463abe5f5135 | 91 | volatile int g_game_flag = 0; /*!< Flag for game ticker */ |
cjw851102 | 4:463abe5f5135 | 92 | |
cjw851102 | 4:463abe5f5135 | 93 | /** Struct for position |
cjw851102 | 4:463abe5f5135 | 94 | @brief Contains the pattern position(x,y), |
cjw851102 | 4:463abe5f5135 | 95 | @brief pattern type and rotation |
cjw851102 | 4:463abe5f5135 | 96 | */ |
cjw851102 | 4:463abe5f5135 | 97 | struct Position { |
cjw851102 | 4:463abe5f5135 | 98 | float x; |
cjw851102 | 4:463abe5f5135 | 99 | float y; |
cjw851102 | 4:463abe5f5135 | 100 | int type; |
cjw851102 | 4:463abe5f5135 | 101 | int rotation; |
cjw851102 | 4:463abe5f5135 | 102 | }; |
cjw851102 | 4:463abe5f5135 | 103 | typedef struct Position position; |
cjw851102 | 4:463abe5f5135 | 104 | position pos; |
cjw851102 | 4:463abe5f5135 | 105 | |
cjw851102 | 4:463abe5f5135 | 106 | //////////////////////////////////////////////////////////////////////// |
cjw851102 | 4:463abe5f5135 | 107 | // Functions |
cjw851102 | 4:463abe5f5135 | 108 | //////////////////////////////////////////////////////////////////////// |
cjw851102 | 4:463abe5f5135 | 109 | /** |
cjw851102 | 4:463abe5f5135 | 110 | Game ticker isr function |
cjw851102 | 4:463abe5f5135 | 111 | */ |
cjw851102 | 4:463abe5f5135 | 112 | void game_isr(); |
cjw851102 | 4:463abe5f5135 | 113 | |
cjw851102 | 4:463abe5f5135 | 114 | /** |
cjw851102 | 4:463abe5f5135 | 115 | Initialise the variables in game |
cjw851102 | 4:463abe5f5135 | 116 | */ |
cjw851102 | 4:463abe5f5135 | 117 | void init_game(); |
cjw851102 | 4:463abe5f5135 | 118 | |
cjw851102 | 4:463abe5f5135 | 119 | /** Drawing the pattern at position (x,y) |
cjw851102 | 4:463abe5f5135 | 120 | @param type - type of pattern (0~6) |
cjw851102 | 4:463abe5f5135 | 121 | @param rotation - rotation of pattern (0~3) |
cjw851102 | 4:463abe5f5135 | 122 | @param x - x co-ordinate of pattern, which is the top left corner pixel of 6x6 square |
cjw851102 | 4:463abe5f5135 | 123 | @param y - y co-ordinate of pattern, which is the top left corner pixel of 6x6 square |
cjw851102 | 4:463abe5f5135 | 124 | @param fill - fill = 0 white, fill = 1 black |
cjw851102 | 4:463abe5f5135 | 125 | */ |
cjw851102 | 4:463abe5f5135 | 126 | void drawPattern(int type,int rotation,int x,int y,int fill); |
cjw851102 | 4:463abe5f5135 | 127 | |
cjw851102 | 4:463abe5f5135 | 128 | /**Left collision detect |
cjw851102 | 4:463abe5f5135 | 129 | @brief Function to check the left collision of current falling pattern and set the left_collision_flag |
cjw851102 | 4:463abe5f5135 | 130 | */ |
cjw851102 | 4:463abe5f5135 | 131 | void left_collisionDetect(); |
cjw851102 | 4:463abe5f5135 | 132 | |
cjw851102 | 4:463abe5f5135 | 133 | /**Right collision detect |
cjw851102 | 4:463abe5f5135 | 134 | @brief Function to check the right collision of current falling pattern and set the left_collision_flag |
cjw851102 | 4:463abe5f5135 | 135 | */ |
cjw851102 | 4:463abe5f5135 | 136 | void right_collisionDetect(); |
cjw851102 | 4:463abe5f5135 | 137 | |
cjw851102 | 4:463abe5f5135 | 138 | /**Bottom collision detect |
cjw851102 | 4:463abe5f5135 | 139 | @brief Function to check the bottom collision of current falling pattern and set the right_collision_flag |
cjw851102 | 4:463abe5f5135 | 140 | */ |
cjw851102 | 4:463abe5f5135 | 141 | void bottom_collisionDetect(); |
cjw851102 | 4:463abe5f5135 | 142 | |
cjw851102 | 4:463abe5f5135 | 143 | /**top collision detect |
cjw851102 | 4:463abe5f5135 | 144 | @brief Function to check the top collision of current falling pattern and set the top_collision_flag |
cjw851102 | 4:463abe5f5135 | 145 | */ |
cjw851102 | 4:463abe5f5135 | 146 | void top_collisionDetect(); |
cjw851102 | 4:463abe5f5135 | 147 | |
cjw851102 | 4:463abe5f5135 | 148 | /**Rotation collision detect |
cjw851102 | 4:463abe5f5135 | 149 | @brief Function to check if the program should allow user to rotate the pattern and set the rotation_collision_flag |
cjw851102 | 4:463abe5f5135 | 150 | */ |
cjw851102 | 4:463abe5f5135 | 151 | void rotation_collisionDetect(); |
cjw851102 | 4:463abe5f5135 | 152 | |
cjw851102 | 4:463abe5f5135 | 153 | /**Fast move collision detect |
cjw851102 | 4:463abe5f5135 | 154 | @brief Function to check if the program should allow user to move the pattern falling faster and set the fastmove_collision_flag |
cjw851102 | 4:463abe5f5135 | 155 | @note check the 4 pixels distance away from the bottom of pattern |
cjw851102 | 4:463abe5f5135 | 156 | */ |
cjw851102 | 4:463abe5f5135 | 157 | void fastmove_bottom_collisionDetect(); |
cjw851102 | 4:463abe5f5135 | 158 | |
cjw851102 | 4:463abe5f5135 | 159 | /**Get pattern pixel settings |
cjw851102 | 4:463abe5f5135 | 160 | @brief Function to get the current falling pattern pixel settings |
cjw851102 | 4:463abe5f5135 | 161 | @note pixels setting will be store in pattern_buffer[6][6]; |
cjw851102 | 4:463abe5f5135 | 162 | @param type - type of pattern (0~6) |
cjw851102 | 4:463abe5f5135 | 163 | @param rotation - rotation of pattern (0~3) |
cjw851102 | 4:463abe5f5135 | 164 | */ |
cjw851102 | 4:463abe5f5135 | 165 | void get_pattern(int type, int rotatin); |
cjw851102 | 4:463abe5f5135 | 166 | |
cjw851102 | 4:463abe5f5135 | 167 | /**Scan the whole screen pixel settings |
cjw851102 | 4:463abe5f5135 | 168 | @brief Function to store the whole screen pixel settings and store in buffer[84][48] |
cjw851102 | 4:463abe5f5135 | 169 | */ |
cjw851102 | 4:463abe5f5135 | 170 | void scan(); |
cjw851102 | 4:463abe5f5135 | 171 | |
cjw851102 | 4:463abe5f5135 | 172 | /** Cancel the filled lines and add the score |
cjw851102 | 4:463abe5f5135 | 173 | @brief Function to check if there are lines filled |
cjw851102 | 4:463abe5f5135 | 174 | @brief if one line is filled, cancel it and move the pixels above this line down and add the score |
cjw851102 | 4:463abe5f5135 | 175 | */ |
cjw851102 | 4:463abe5f5135 | 176 | void cancelLine(); |
cjw851102 | 4:463abe5f5135 | 177 | |
cjw851102 | 4:463abe5f5135 | 178 | /** |
cjw851102 | 4:463abe5f5135 | 179 | Game finish animations |
cjw851102 | 4:463abe5f5135 | 180 | */ |
cjw851102 | 4:463abe5f5135 | 181 | void finishAnimation(); |
cjw851102 | 4:463abe5f5135 | 182 | |
cjw851102 | 4:463abe5f5135 | 183 | /** User press button when game is in process |
cjw851102 | 4:463abe5f5135 | 184 | @brief When button pressed in the game, ask user if they want to exit the game |
cjw851102 | 4:463abe5f5135 | 185 | @return TRUE - exit the game FALSE - contiute the game |
cjw851102 | 4:463abe5f5135 | 186 | */ |
cjw851102 | 4:463abe5f5135 | 187 | bool buttonPressedInGame(); |
cjw851102 | 4:463abe5f5135 | 188 | |
cjw851102 | 4:463abe5f5135 | 189 | /**Save the highest score to SD card |
cjw851102 | 4:463abe5f5135 | 190 | @param score - a integer number need to save to SD card |
cjw851102 | 4:463abe5f5135 | 191 | */ |
cjw851102 | 4:463abe5f5135 | 192 | void save_score_SD(int score); |
cjw851102 | 4:463abe5f5135 | 193 | |
cjw851102 | 4:463abe5f5135 | 194 | /** |
cjw851102 | 4:463abe5f5135 | 195 | Read the highest score from SD card |
cjw851102 | 4:463abe5f5135 | 196 | */ |
cjw851102 | 4:463abe5f5135 | 197 | int read_score_SD(); |
cjw851102 | 4:463abe5f5135 | 198 | |
cjw851102 | 4:463abe5f5135 | 199 | /** |
cjw851102 | 4:463abe5f5135 | 200 | Complete tetris game |
cjw851102 | 4:463abe5f5135 | 201 | */ |
cjw851102 | 4:463abe5f5135 | 202 | void tetis_game(); |
cjw851102 | 4:463abe5f5135 | 203 | |
cjw851102 | 4:463abe5f5135 | 204 | |
cjw851102 | 4:463abe5f5135 | 205 | ///////////////////////////////////////////////// |
cjw851102 | 4:463abe5f5135 | 206 | /// Function Definitions |
cjw851102 | 4:463abe5f5135 | 207 | ///////////////////////////////////////////////// |
cjw851102 | 4:463abe5f5135 | 208 | |
cjw851102 | 4:463abe5f5135 | 209 | void tetis_game() |
cjw851102 | 4:463abe5f5135 | 210 | { |
cjw851102 | 4:463abe5f5135 | 211 | bool exitGame; //bool variable to save the exit game decision when button pressed |
cjw851102 | 4:463abe5f5135 | 212 | while (1) { |
cjw851102 | 4:463abe5f5135 | 213 | if(g_game_flag==1) { |
cjw851102 | 4:463abe5f5135 | 214 | g_game_flag = 0; |
cjw851102 | 4:463abe5f5135 | 215 | |
cjw851102 | 4:463abe5f5135 | 216 | exitGame=buttonPressedInGame(); //check if user press button and get the decision |
cjw851102 | 4:463abe5f5135 | 217 | if(exitGame) { // exit game |
cjw851102 | 4:463abe5f5135 | 218 | break; //jump out of while loop |
cjw851102 | 4:463abe5f5135 | 219 | } |
cjw851102 | 4:463abe5f5135 | 220 | |
cjw851102 | 4:463abe5f5135 | 221 | pos.type = typeArray[typeCount]; //get the pattern type |
cjw851102 | 4:463abe5f5135 | 222 | nextTypeCount=typeCount+1; |
cjw851102 | 4:463abe5f5135 | 223 | if (nextTypeCount>99) { //start from the first element in type array |
cjw851102 | 4:463abe5f5135 | 224 | nextTypeCount=0; |
cjw851102 | 4:463abe5f5135 | 225 | } |
cjw851102 | 4:463abe5f5135 | 226 | drawPattern(typeArray[nextTypeCount],0,55,41,1);// draw next pattern on the right hand side of screen |
cjw851102 | 4:463abe5f5135 | 227 | if (pos.y >= -5) { // when pattern start falling, clear previous pattern |
cjw851102 | 4:463abe5f5135 | 228 | drawPattern(pos.type,pos.rotation,xOld,pos.y-1,0); |
cjw851102 | 4:463abe5f5135 | 229 | } |
cjw851102 | 4:463abe5f5135 | 230 | |
cjw851102 | 4:463abe5f5135 | 231 | updateJoystick(); //get the joystick direction |
cjw851102 | 4:463abe5f5135 | 232 | |
cjw851102 | 4:463abe5f5135 | 233 | top_collisionDetect(); // check if current pattern touch the top |
cjw851102 | 4:463abe5f5135 | 234 | if (top_collision_flag == 1) { // if touch the top, finish the game |
cjw851102 | 4:463abe5f5135 | 235 | red_led=1; |
cjw851102 | 4:463abe5f5135 | 236 | green_led=0; |
cjw851102 | 4:463abe5f5135 | 237 | //play sound at end of game |
cjw851102 | 4:463abe5f5135 | 238 | for(double i=1; i>=0; i-=0.1) { |
cjw851102 | 4:463abe5f5135 | 239 | buzzer = i; |
cjw851102 | 4:463abe5f5135 | 240 | wait(0.2); |
cjw851102 | 4:463abe5f5135 | 241 | } |
cjw851102 | 4:463abe5f5135 | 242 | buzzer = 0; |
cjw851102 | 4:463abe5f5135 | 243 | finishAnimation(); //finish animation |
cjw851102 | 4:463abe5f5135 | 244 | lcd.clear(); |
cjw851102 | 4:463abe5f5135 | 245 | int stored_score=read_score_SD(); |
cjw851102 | 4:463abe5f5135 | 246 | if (score>stored_score) { // if score is larger than highest score, save it to SD card |
cjw851102 | 4:463abe5f5135 | 247 | save_score_SD(score); |
cjw851102 | 4:463abe5f5135 | 248 | } |
cjw851102 | 4:463abe5f5135 | 249 | // show the score |
cjw851102 | 4:463abe5f5135 | 250 | char scoreBuffer[14]; |
cjw851102 | 4:463abe5f5135 | 251 | sprintf(scoreBuffer,"%d",score); |
cjw851102 | 4:463abe5f5135 | 252 | lcd.printString("SCORE IS: ",10,2); |
cjw851102 | 4:463abe5f5135 | 253 | lcd.printString(scoreBuffer,35,4); |
cjw851102 | 4:463abe5f5135 | 254 | lcd.refresh(); |
cjw851102 | 4:463abe5f5135 | 255 | wait(3.0); |
cjw851102 | 4:463abe5f5135 | 256 | lcd.clear(); |
cjw851102 | 4:463abe5f5135 | 257 | state=0; // back to the main menu |
cjw851102 | 4:463abe5f5135 | 258 | break; |
cjw851102 | 4:463abe5f5135 | 259 | } |
cjw851102 | 4:463abe5f5135 | 260 | |
cjw851102 | 4:463abe5f5135 | 261 | //move patterns according to joystick direction |
cjw851102 | 4:463abe5f5135 | 262 | switch(joystick.direction) { |
cjw851102 | 4:463abe5f5135 | 263 | case UP: // rotation |
cjw851102 | 4:463abe5f5135 | 264 | rotation_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 265 | rotation_collisionDetect(); // check if allow rotation |
cjw851102 | 4:463abe5f5135 | 266 | if(rotation_collision_flag == 0) { // allow rotation |
cjw851102 | 4:463abe5f5135 | 267 | pos.rotation++; |
cjw851102 | 4:463abe5f5135 | 268 | if (pos.rotation>3) { |
cjw851102 | 4:463abe5f5135 | 269 | pos.rotation=0; |
cjw851102 | 4:463abe5f5135 | 270 | } |
cjw851102 | 4:463abe5f5135 | 271 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); |
cjw851102 | 4:463abe5f5135 | 272 | } else {// not allow rotation |
cjw851102 | 4:463abe5f5135 | 273 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); |
cjw851102 | 4:463abe5f5135 | 274 | } |
cjw851102 | 4:463abe5f5135 | 275 | break; |
cjw851102 | 4:463abe5f5135 | 276 | case DOWN: // faster moving down |
cjw851102 | 4:463abe5f5135 | 277 | fastmove_bottom_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 278 | fastmove_bottom_collisionDetect(); |
cjw851102 | 4:463abe5f5135 | 279 | if (fastmove_bottom_collision_flag == 0) {// allow faster move |
cjw851102 | 4:463abe5f5135 | 280 | pos.y +=4; // move pattern down by 4 pixels distance |
cjw851102 | 4:463abe5f5135 | 281 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); |
cjw851102 | 4:463abe5f5135 | 282 | } else { |
cjw851102 | 4:463abe5f5135 | 283 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); |
cjw851102 | 4:463abe5f5135 | 284 | } |
cjw851102 | 4:463abe5f5135 | 285 | break; |
cjw851102 | 4:463abe5f5135 | 286 | case RIGHT: // move right |
cjw851102 | 4:463abe5f5135 | 287 | right_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 288 | right_collisionDetect(); // detect right collision |
cjw851102 | 4:463abe5f5135 | 289 | if( right_collision_flag == 0) { // allow move right |
cjw851102 | 4:463abe5f5135 | 290 | pos.x +=2; |
cjw851102 | 4:463abe5f5135 | 291 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); |
cjw851102 | 4:463abe5f5135 | 292 | } else { // not allow move right |
cjw851102 | 4:463abe5f5135 | 293 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); |
cjw851102 | 4:463abe5f5135 | 294 | right_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 295 | } |
cjw851102 | 4:463abe5f5135 | 296 | break; |
cjw851102 | 4:463abe5f5135 | 297 | case LEFT: //move left |
cjw851102 | 4:463abe5f5135 | 298 | left_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 299 | left_collisionDetect(); // detect left collision |
cjw851102 | 4:463abe5f5135 | 300 | if( left_collision_flag == 0) {// allow move left |
cjw851102 | 4:463abe5f5135 | 301 | pos.x -=2; |
cjw851102 | 4:463abe5f5135 | 302 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); |
cjw851102 | 4:463abe5f5135 | 303 | } else { // not allow move left |
cjw851102 | 4:463abe5f5135 | 304 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); |
cjw851102 | 4:463abe5f5135 | 305 | left_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 306 | } |
cjw851102 | 4:463abe5f5135 | 307 | |
cjw851102 | 4:463abe5f5135 | 308 | break; |
cjw851102 | 4:463abe5f5135 | 309 | case CENTRE: // joystick in centre |
cjw851102 | 4:463abe5f5135 | 310 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); |
cjw851102 | 4:463abe5f5135 | 311 | break; |
cjw851102 | 4:463abe5f5135 | 312 | case UNKNOWN: |
cjw851102 | 4:463abe5f5135 | 313 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); |
cjw851102 | 4:463abe5f5135 | 314 | break; |
cjw851102 | 4:463abe5f5135 | 315 | } |
cjw851102 | 4:463abe5f5135 | 316 | |
cjw851102 | 4:463abe5f5135 | 317 | xOld = pos.x; //store previous pattern x co-codinate |
cjw851102 | 4:463abe5f5135 | 318 | |
cjw851102 | 4:463abe5f5135 | 319 | bottom_collisionDetect(); // bottom collision detect |
cjw851102 | 4:463abe5f5135 | 320 | if (bottom_collision_flag == 0) { // no collision |
cjw851102 | 4:463abe5f5135 | 321 | pos.y++; // keep moving pattern down |
cjw851102 | 4:463abe5f5135 | 322 | buzzer = 0; // turn off buzzer |
cjw851102 | 4:463abe5f5135 | 323 | } else { // bottom collision |
cjw851102 | 4:463abe5f5135 | 324 | drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); // fix pattern |
cjw851102 | 4:463abe5f5135 | 325 | cancelLine(); // check filled lines and add score |
cjw851102 | 4:463abe5f5135 | 326 | pos.x = 10; // new pattern will fall from the centre |
cjw851102 | 4:463abe5f5135 | 327 | pos.y = -6; |
cjw851102 | 4:463abe5f5135 | 328 | pos.rotation=0; |
cjw851102 | 4:463abe5f5135 | 329 | drawPattern(typeArray[nextTypeCount],pos.rotation,55,41,0);// clear the old next pattern show on RHS of screen |
cjw851102 | 4:463abe5f5135 | 330 | typeCount ++; //new type of pattern |
cjw851102 | 4:463abe5f5135 | 331 | if (typeCount >99) { |
cjw851102 | 4:463abe5f5135 | 332 | typeCount = 0; |
cjw851102 | 4:463abe5f5135 | 333 | } |
cjw851102 | 4:463abe5f5135 | 334 | } |
cjw851102 | 4:463abe5f5135 | 335 | lcd.refresh(); |
cjw851102 | 4:463abe5f5135 | 336 | } |
cjw851102 | 4:463abe5f5135 | 337 | sleep(); // go to sleep mode unless ticker interupt |
cjw851102 | 4:463abe5f5135 | 338 | } |
cjw851102 | 4:463abe5f5135 | 339 | } |
cjw851102 | 4:463abe5f5135 | 340 | |
cjw851102 | 4:463abe5f5135 | 341 | |
cjw851102 | 4:463abe5f5135 | 342 | void init_game() |
cjw851102 | 4:463abe5f5135 | 343 | { |
cjw851102 | 4:463abe5f5135 | 344 | pos.x = 10; |
cjw851102 | 4:463abe5f5135 | 345 | pos.y = -6; |
cjw851102 | 4:463abe5f5135 | 346 | pos.rotation=0; |
cjw851102 | 4:463abe5f5135 | 347 | typeCount=0; |
cjw851102 | 4:463abe5f5135 | 348 | green_led=1; // turn on green led |
cjw851102 | 4:463abe5f5135 | 349 | //generate 100 random integers in the range of 0~6 |
cjw851102 | 4:463abe5f5135 | 350 | //and store in typeArray |
cjw851102 | 4:463abe5f5135 | 351 | for(int i=0; i<=99; i++) { |
cjw851102 | 4:463abe5f5135 | 352 | typeArray[i] = rand()%7; |
cjw851102 | 4:463abe5f5135 | 353 | } |
cjw851102 | 4:463abe5f5135 | 354 | |
cjw851102 | 4:463abe5f5135 | 355 | //gaming screen |
cjw851102 | 4:463abe5f5135 | 356 | lcd.drawLine(30,0,30,47,1); |
cjw851102 | 4:463abe5f5135 | 357 | lcd.printString("Level:",42,0); |
cjw851102 | 4:463abe5f5135 | 358 | lcd.printString("Score:",42,2); |
cjw851102 | 4:463abe5f5135 | 359 | lcd.printString("0",42,3); |
cjw851102 | 4:463abe5f5135 | 360 | lcd.printString("Next:",42,4); |
cjw851102 | 4:463abe5f5135 | 361 | |
cjw851102 | 4:463abe5f5135 | 362 | //play sound at begining of game |
cjw851102 | 4:463abe5f5135 | 363 | for(double i=0; i<=1.0; i+=0.1) { |
cjw851102 | 4:463abe5f5135 | 364 | buzzer = i; |
cjw851102 | 4:463abe5f5135 | 365 | wait(0.2); |
cjw851102 | 4:463abe5f5135 | 366 | } |
cjw851102 | 4:463abe5f5135 | 367 | buzzer = 0; |
cjw851102 | 4:463abe5f5135 | 368 | } |
cjw851102 | 4:463abe5f5135 | 369 | |
cjw851102 | 4:463abe5f5135 | 370 | |
cjw851102 | 4:463abe5f5135 | 371 | void get_pattern(int type, int rotation) |
cjw851102 | 4:463abe5f5135 | 372 | { |
cjw851102 | 4:463abe5f5135 | 373 | for(int i=0; i<=5; i++) { |
cjw851102 | 4:463abe5f5135 | 374 | for(int j=0; j<=5; j++) {// patterns.getPatterns(type,rotation,j,i) return pattern[type][rotation][y][x]; |
cjw851102 | 4:463abe5f5135 | 375 | pattern_buffer[i][j] = patterns.getPatterns(type,rotation,j,i); |
cjw851102 | 4:463abe5f5135 | 376 | } |
cjw851102 | 4:463abe5f5135 | 377 | } |
cjw851102 | 4:463abe5f5135 | 378 | } |
cjw851102 | 4:463abe5f5135 | 379 | |
cjw851102 | 4:463abe5f5135 | 380 | |
cjw851102 | 4:463abe5f5135 | 381 | void scan() |
cjw851102 | 4:463abe5f5135 | 382 | { |
cjw851102 | 4:463abe5f5135 | 383 | //screen has 84x48 pixels |
cjw851102 | 4:463abe5f5135 | 384 | for (int i=0; i<=83; i++) { |
cjw851102 | 4:463abe5f5135 | 385 | for (int j=0; j<=47; j++) { |
cjw851102 | 4:463abe5f5135 | 386 | if(lcd.getPixel(i,j)) { //if pixel is set |
cjw851102 | 4:463abe5f5135 | 387 | buffer[i][j] = 1; |
cjw851102 | 4:463abe5f5135 | 388 | } else { // pixel is clear |
cjw851102 | 4:463abe5f5135 | 389 | buffer[i][j] = 0; |
cjw851102 | 4:463abe5f5135 | 390 | } |
cjw851102 | 4:463abe5f5135 | 391 | } |
cjw851102 | 4:463abe5f5135 | 392 | } |
cjw851102 | 4:463abe5f5135 | 393 | } |
cjw851102 | 4:463abe5f5135 | 394 | |
cjw851102 | 4:463abe5f5135 | 395 | // draw pattern at (x,y) |
cjw851102 | 4:463abe5f5135 | 396 | void drawPattern(int type,int rotation,int x,int y,int fill) |
cjw851102 | 4:463abe5f5135 | 397 | { |
cjw851102 | 4:463abe5f5135 | 398 | get_pattern(type,rotation); // get the pattern pixel settings, which store in pattern_buffer |
cjw851102 | 4:463abe5f5135 | 399 | for(int i=x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square |
cjw851102 | 4:463abe5f5135 | 400 | for(int j=y; j <= y+5; j++) { |
cjw851102 | 4:463abe5f5135 | 401 | if (j>=0) { |
cjw851102 | 4:463abe5f5135 | 402 | if(pattern_buffer[i-x][j-y]==1) {//pixel setting is 1 |
cjw851102 | 4:463abe5f5135 | 403 | if (fill==0) { //draw white pattern |
cjw851102 | 4:463abe5f5135 | 404 | if (j<=47 && i>=0) { // draw pattern inside the screen |
cjw851102 | 4:463abe5f5135 | 405 | lcd.clearPixel(i,j); |
cjw851102 | 4:463abe5f5135 | 406 | } |
cjw851102 | 4:463abe5f5135 | 407 | } else if (fill==1) { //draw black pattern |
cjw851102 | 4:463abe5f5135 | 408 | if (j<=47 && i>=0) { |
cjw851102 | 4:463abe5f5135 | 409 | lcd.setPixel(i,j); |
cjw851102 | 4:463abe5f5135 | 410 | } |
cjw851102 | 4:463abe5f5135 | 411 | } |
cjw851102 | 4:463abe5f5135 | 412 | } |
cjw851102 | 4:463abe5f5135 | 413 | } |
cjw851102 | 4:463abe5f5135 | 414 | } |
cjw851102 | 4:463abe5f5135 | 415 | } |
cjw851102 | 4:463abe5f5135 | 416 | } |
cjw851102 | 4:463abe5f5135 | 417 | |
cjw851102 | 4:463abe5f5135 | 418 | |
cjw851102 | 4:463abe5f5135 | 419 | void left_collisionDetect() |
cjw851102 | 4:463abe5f5135 | 420 | { |
cjw851102 | 4:463abe5f5135 | 421 | int left_boundary[6][6]; |
cjw851102 | 4:463abe5f5135 | 422 | get_pattern(pos.type,pos.rotation); |
cjw851102 | 4:463abe5f5135 | 423 | |
cjw851102 | 4:463abe5f5135 | 424 | /* get the left boundary pixel settings |
cjw851102 | 4:463abe5f5135 | 425 | e.g: if pattern is L |
cjw851102 | 4:463abe5f5135 | 426 | left boundary is |
cjw851102 | 4:463abe5f5135 | 427 | 1 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 428 | 1 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 429 | 1 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 430 | 1 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 431 | 1 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 432 | 1 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 433 | */ |
cjw851102 | 4:463abe5f5135 | 434 | for (int j=0; j<=5; j++) { // |
cjw851102 | 4:463abe5f5135 | 435 | for (int i=0; i<=5; i++) { |
cjw851102 | 4:463abe5f5135 | 436 | if (pattern_buffer[i][j]==1) { |
cjw851102 | 4:463abe5f5135 | 437 | left_boundary[i][j]=1; |
cjw851102 | 4:463abe5f5135 | 438 | for(int k=i+1; k<=5; k++) { |
cjw851102 | 4:463abe5f5135 | 439 | left_boundary[k][j] = 0; |
cjw851102 | 4:463abe5f5135 | 440 | } |
cjw851102 | 4:463abe5f5135 | 441 | break; |
cjw851102 | 4:463abe5f5135 | 442 | } else { |
cjw851102 | 4:463abe5f5135 | 443 | left_boundary[i][j]=0; |
cjw851102 | 4:463abe5f5135 | 444 | } |
cjw851102 | 4:463abe5f5135 | 445 | } |
cjw851102 | 4:463abe5f5135 | 446 | } |
cjw851102 | 4:463abe5f5135 | 447 | |
cjw851102 | 4:463abe5f5135 | 448 | //check left collision |
cjw851102 | 4:463abe5f5135 | 449 | int x = pos.x; |
cjw851102 | 4:463abe5f5135 | 450 | int y = pos.y; |
cjw851102 | 4:463abe5f5135 | 451 | if (x<0) { //for all the pattern, when x<0, pattern is on the most LHS of screen |
cjw851102 | 4:463abe5f5135 | 452 | left_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 453 | } else { //check the pixel status away from left boundary for one pixel distance |
cjw851102 | 4:463abe5f5135 | 454 | for(int i=x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square |
cjw851102 | 4:463abe5f5135 | 455 | for(int j=y; j <= y+5; j++) { |
cjw851102 | 4:463abe5f5135 | 456 | if(left_boundary[i-x][j-y]==1) { |
cjw851102 | 4:463abe5f5135 | 457 | if(i == 0) { // pattern at most LHS of screen |
cjw851102 | 4:463abe5f5135 | 458 | left_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 459 | break; // don't need to check the other pixels at same x, jump out of inner for loop |
cjw851102 | 4:463abe5f5135 | 460 | } else if (lcd.getPixel(i-1,j)) { //check one pixel away from left boundary |
cjw851102 | 4:463abe5f5135 | 461 | left_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 462 | break; |
cjw851102 | 4:463abe5f5135 | 463 | } else { |
cjw851102 | 4:463abe5f5135 | 464 | left_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 465 | } |
cjw851102 | 4:463abe5f5135 | 466 | } |
cjw851102 | 4:463abe5f5135 | 467 | } |
cjw851102 | 4:463abe5f5135 | 468 | if (left_collision_flag == 1) { |
cjw851102 | 4:463abe5f5135 | 469 | break;// jump out of inner for loop |
cjw851102 | 4:463abe5f5135 | 470 | } |
cjw851102 | 4:463abe5f5135 | 471 | } |
cjw851102 | 4:463abe5f5135 | 472 | } |
cjw851102 | 4:463abe5f5135 | 473 | } |
cjw851102 | 4:463abe5f5135 | 474 | |
cjw851102 | 4:463abe5f5135 | 475 | |
cjw851102 | 4:463abe5f5135 | 476 | void right_collisionDetect() |
cjw851102 | 4:463abe5f5135 | 477 | { |
cjw851102 | 4:463abe5f5135 | 478 | int right_boundary[6][6]; |
cjw851102 | 4:463abe5f5135 | 479 | get_pattern(pos.type,pos.rotation); |
cjw851102 | 4:463abe5f5135 | 480 | |
cjw851102 | 4:463abe5f5135 | 481 | /* get the right boundary pixel settings |
cjw851102 | 4:463abe5f5135 | 482 | e.g: if pattern is L |
cjw851102 | 4:463abe5f5135 | 483 | left boundary is |
cjw851102 | 4:463abe5f5135 | 484 | 0 0 1 0 0 0 |
cjw851102 | 4:463abe5f5135 | 485 | 0 0 1 0 0 0 |
cjw851102 | 4:463abe5f5135 | 486 | 0 0 1 0 0 0 |
cjw851102 | 4:463abe5f5135 | 487 | 0 0 1 0 0 0 |
cjw851102 | 4:463abe5f5135 | 488 | 0 0 0 1 0 0 |
cjw851102 | 4:463abe5f5135 | 489 | 0 0 0 1 0 0 |
cjw851102 | 4:463abe5f5135 | 490 | */ |
cjw851102 | 4:463abe5f5135 | 491 | for (int j=0; j<=5; j++) { |
cjw851102 | 4:463abe5f5135 | 492 | for (int i=5; i>=0; i--) { |
cjw851102 | 4:463abe5f5135 | 493 | if (pattern_buffer[i][j]==1) { |
cjw851102 | 4:463abe5f5135 | 494 | right_boundary[i][j]=1; |
cjw851102 | 4:463abe5f5135 | 495 | for(int k=i-1; k>=0; k--) { |
cjw851102 | 4:463abe5f5135 | 496 | right_boundary[k][j] = 0; |
cjw851102 | 4:463abe5f5135 | 497 | } |
cjw851102 | 4:463abe5f5135 | 498 | break; |
cjw851102 | 4:463abe5f5135 | 499 | } else { |
cjw851102 | 4:463abe5f5135 | 500 | right_boundary[i][j]=0; |
cjw851102 | 4:463abe5f5135 | 501 | } |
cjw851102 | 4:463abe5f5135 | 502 | } |
cjw851102 | 4:463abe5f5135 | 503 | } |
cjw851102 | 4:463abe5f5135 | 504 | |
cjw851102 | 4:463abe5f5135 | 505 | //check right collision |
cjw851102 | 4:463abe5f5135 | 506 | int x = pos.x; |
cjw851102 | 4:463abe5f5135 | 507 | int y = pos.y; |
cjw851102 | 4:463abe5f5135 | 508 | for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square |
cjw851102 | 4:463abe5f5135 | 509 | for(int j=y; j <= y+5; j++) { |
cjw851102 | 4:463abe5f5135 | 510 | if(right_boundary[i-x][j-y]==1) { |
cjw851102 | 4:463abe5f5135 | 511 | if(j>=0) { |
cjw851102 | 4:463abe5f5135 | 512 | if(i >= 29) { // most RHS of gaming screen |
cjw851102 | 4:463abe5f5135 | 513 | right_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 514 | break; |
cjw851102 | 4:463abe5f5135 | 515 | } else if (lcd.getPixel(i+1,j)) {//check the pixel status away from right boundary for one pixel distance |
cjw851102 | 4:463abe5f5135 | 516 | right_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 517 | break; |
cjw851102 | 4:463abe5f5135 | 518 | } else { |
cjw851102 | 4:463abe5f5135 | 519 | right_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 520 | } |
cjw851102 | 4:463abe5f5135 | 521 | } |
cjw851102 | 4:463abe5f5135 | 522 | } |
cjw851102 | 4:463abe5f5135 | 523 | } |
cjw851102 | 4:463abe5f5135 | 524 | if (right_collision_flag == 1) { |
cjw851102 | 4:463abe5f5135 | 525 | break; |
cjw851102 | 4:463abe5f5135 | 526 | } |
cjw851102 | 4:463abe5f5135 | 527 | } |
cjw851102 | 4:463abe5f5135 | 528 | } |
cjw851102 | 4:463abe5f5135 | 529 | |
cjw851102 | 4:463abe5f5135 | 530 | |
cjw851102 | 4:463abe5f5135 | 531 | void bottom_collisionDetect() |
cjw851102 | 4:463abe5f5135 | 532 | { |
cjw851102 | 4:463abe5f5135 | 533 | int bot_boundary[6][6]; |
cjw851102 | 4:463abe5f5135 | 534 | get_pattern(pos.type,pos.rotation); |
cjw851102 | 4:463abe5f5135 | 535 | |
cjw851102 | 4:463abe5f5135 | 536 | /* get the left boundary pixel settings |
cjw851102 | 4:463abe5f5135 | 537 | e.g: if pattern is L |
cjw851102 | 4:463abe5f5135 | 538 | left boundary is |
cjw851102 | 4:463abe5f5135 | 539 | 0 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 540 | 0 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 541 | 0 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 542 | 0 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 543 | 0 0 0 0 0 0 |
cjw851102 | 4:463abe5f5135 | 544 | 1 1 1 1 0 0 |
cjw851102 | 4:463abe5f5135 | 545 | */ |
cjw851102 | 4:463abe5f5135 | 546 | for (int i=0; i<=5; i++) { |
cjw851102 | 4:463abe5f5135 | 547 | for (int j=5; j>=0; j--) { |
cjw851102 | 4:463abe5f5135 | 548 | if (pattern_buffer[i][j]==1) { |
cjw851102 | 4:463abe5f5135 | 549 | bot_boundary[i][j]=1; |
cjw851102 | 4:463abe5f5135 | 550 | for(int k=j-1; k>=0; k--) { |
cjw851102 | 4:463abe5f5135 | 551 | bot_boundary[i][k] = 0; |
cjw851102 | 4:463abe5f5135 | 552 | } |
cjw851102 | 4:463abe5f5135 | 553 | break; |
cjw851102 | 4:463abe5f5135 | 554 | } else { |
cjw851102 | 4:463abe5f5135 | 555 | bot_boundary[i][j]=0; |
cjw851102 | 4:463abe5f5135 | 556 | } |
cjw851102 | 4:463abe5f5135 | 557 | } |
cjw851102 | 4:463abe5f5135 | 558 | } |
cjw851102 | 4:463abe5f5135 | 559 | |
cjw851102 | 4:463abe5f5135 | 560 | //check bottom collision |
cjw851102 | 4:463abe5f5135 | 561 | int x = pos.x; |
cjw851102 | 4:463abe5f5135 | 562 | int y = pos.y; |
cjw851102 | 4:463abe5f5135 | 563 | for(int i = x; i <= x+5; i++) { //check from left |
cjw851102 | 4:463abe5f5135 | 564 | for(int j=y+5; j >= y; j--) { //check from bottom |
cjw851102 | 4:463abe5f5135 | 565 | if (j>=-1) { //start check when pattern fall in the screen |
cjw851102 | 4:463abe5f5135 | 566 | if(bot_boundary[i-x][j-y]==1) { |
cjw851102 | 4:463abe5f5135 | 567 | if(j >= 47) { // pattern at bottom |
cjw851102 | 4:463abe5f5135 | 568 | bottom_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 569 | break; // jump out of inner for loop |
cjw851102 | 4:463abe5f5135 | 570 | } else if (lcd.getPixel(i,j+1)) {//check the pixel status away from bottom boundary for one pixel distance |
cjw851102 | 4:463abe5f5135 | 571 | bottom_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 572 | break; |
cjw851102 | 4:463abe5f5135 | 573 | } else { |
cjw851102 | 4:463abe5f5135 | 574 | bottom_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 575 | } |
cjw851102 | 4:463abe5f5135 | 576 | } |
cjw851102 | 4:463abe5f5135 | 577 | } else { //at bottom of screen |
cjw851102 | 4:463abe5f5135 | 578 | bottom_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 579 | } |
cjw851102 | 4:463abe5f5135 | 580 | } |
cjw851102 | 4:463abe5f5135 | 581 | if( bottom_collision_flag == 1) { |
cjw851102 | 4:463abe5f5135 | 582 | break; // jump out of inner for loop |
cjw851102 | 4:463abe5f5135 | 583 | } |
cjw851102 | 4:463abe5f5135 | 584 | } |
cjw851102 | 4:463abe5f5135 | 585 | } |
cjw851102 | 4:463abe5f5135 | 586 | |
cjw851102 | 4:463abe5f5135 | 587 | |
cjw851102 | 4:463abe5f5135 | 588 | void rotation_collisionDetect() |
cjw851102 | 4:463abe5f5135 | 589 | { |
cjw851102 | 4:463abe5f5135 | 590 | int rotation = pos.rotation+1; |
cjw851102 | 4:463abe5f5135 | 591 | if (rotation>3) { |
cjw851102 | 4:463abe5f5135 | 592 | rotation=0; |
cjw851102 | 4:463abe5f5135 | 593 | } |
cjw851102 | 4:463abe5f5135 | 594 | get_pattern(pos.type,rotation); |
cjw851102 | 4:463abe5f5135 | 595 | |
cjw851102 | 4:463abe5f5135 | 596 | //check pixel status of upcoming rotation |
cjw851102 | 4:463abe5f5135 | 597 | int x = pos.x; |
cjw851102 | 4:463abe5f5135 | 598 | int y = pos.y; |
cjw851102 | 4:463abe5f5135 | 599 | for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square |
cjw851102 | 4:463abe5f5135 | 600 | for(int j=y; j <= y+5; j++) { |
cjw851102 | 4:463abe5f5135 | 601 | if(pattern_buffer[i-x][j-y]==1) { |
cjw851102 | 4:463abe5f5135 | 602 | if(i<0) { // out of LHS screen |
cjw851102 | 4:463abe5f5135 | 603 | rotation_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 604 | } else if(lcd.getPixel(i,j)) { // there is pixel set |
cjw851102 | 4:463abe5f5135 | 605 | rotation_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 606 | break; //jump out of inner for loop |
cjw851102 | 4:463abe5f5135 | 607 | } else { |
cjw851102 | 4:463abe5f5135 | 608 | rotation_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 609 | } |
cjw851102 | 4:463abe5f5135 | 610 | } |
cjw851102 | 4:463abe5f5135 | 611 | } |
cjw851102 | 4:463abe5f5135 | 612 | if (rotation_collision_flag == 1) { |
cjw851102 | 4:463abe5f5135 | 613 | break; //jump out of inner for loop |
cjw851102 | 4:463abe5f5135 | 614 | } |
cjw851102 | 4:463abe5f5135 | 615 | } |
cjw851102 | 4:463abe5f5135 | 616 | } |
cjw851102 | 4:463abe5f5135 | 617 | |
cjw851102 | 4:463abe5f5135 | 618 | |
cjw851102 | 4:463abe5f5135 | 619 | void top_collisionDetect() |
cjw851102 | 4:463abe5f5135 | 620 | { |
cjw851102 | 4:463abe5f5135 | 621 | if (pos.y==-6) { //pattern is about to fall |
cjw851102 | 4:463abe5f5135 | 622 | bottom_collisionDetect(); |
cjw851102 | 4:463abe5f5135 | 623 | if (bottom_collision_flag == 1) { //if can't fall |
cjw851102 | 4:463abe5f5135 | 624 | top_collision_flag = 1; // top collision |
cjw851102 | 4:463abe5f5135 | 625 | } else { |
cjw851102 | 4:463abe5f5135 | 626 | top_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 627 | } |
cjw851102 | 4:463abe5f5135 | 628 | } |
cjw851102 | 4:463abe5f5135 | 629 | } |
cjw851102 | 4:463abe5f5135 | 630 | |
cjw851102 | 4:463abe5f5135 | 631 | |
cjw851102 | 4:463abe5f5135 | 632 | void fastmove_bottom_collisionDetect() |
cjw851102 | 4:463abe5f5135 | 633 | { |
cjw851102 | 4:463abe5f5135 | 634 | int bot_boundary[6][6]; |
cjw851102 | 4:463abe5f5135 | 635 | get_pattern(pos.type,pos.rotation); |
cjw851102 | 4:463abe5f5135 | 636 | |
cjw851102 | 4:463abe5f5135 | 637 | // get the bottom boundary pattern |
cjw851102 | 4:463abe5f5135 | 638 | for (int i=0; i<=5; i++) { |
cjw851102 | 4:463abe5f5135 | 639 | for (int j=5; j>=0; j--) { |
cjw851102 | 4:463abe5f5135 | 640 | if (pattern_buffer[i][j]==1) { |
cjw851102 | 4:463abe5f5135 | 641 | bot_boundary[i][j]=1; |
cjw851102 | 4:463abe5f5135 | 642 | for(int k=j-1; k>=0; k--) { |
cjw851102 | 4:463abe5f5135 | 643 | bot_boundary[i][k] = 0; |
cjw851102 | 4:463abe5f5135 | 644 | } |
cjw851102 | 4:463abe5f5135 | 645 | break; |
cjw851102 | 4:463abe5f5135 | 646 | } else { |
cjw851102 | 4:463abe5f5135 | 647 | bot_boundary[i][j]=0; |
cjw851102 | 4:463abe5f5135 | 648 | } |
cjw851102 | 4:463abe5f5135 | 649 | } |
cjw851102 | 4:463abe5f5135 | 650 | } |
cjw851102 | 4:463abe5f5135 | 651 | |
cjw851102 | 4:463abe5f5135 | 652 | //check bottom collision for 4 pixel distance away from bottom boundary |
cjw851102 | 4:463abe5f5135 | 653 | int x = pos.x; |
cjw851102 | 4:463abe5f5135 | 654 | int y = pos.y; |
cjw851102 | 4:463abe5f5135 | 655 | for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square |
cjw851102 | 4:463abe5f5135 | 656 | for(int j=y+5; j >= y; j--) { |
cjw851102 | 4:463abe5f5135 | 657 | if (j>=-1) { |
cjw851102 | 4:463abe5f5135 | 658 | if(bot_boundary[i-x][j-y]==1) { |
cjw851102 | 4:463abe5f5135 | 659 | if(j >= 42) { // pattern is about to fall on the bottom |
cjw851102 | 4:463abe5f5135 | 660 | fastmove_bottom_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 661 | break; |
cjw851102 | 4:463abe5f5135 | 662 | } else if (lcd.getPixel(i,j+4)) {//check bottom collision for 4 pixel distance away from bottom boundary |
cjw851102 | 4:463abe5f5135 | 663 | fastmove_bottom_collision_flag = 1; |
cjw851102 | 4:463abe5f5135 | 664 | break; |
cjw851102 | 4:463abe5f5135 | 665 | } else { |
cjw851102 | 4:463abe5f5135 | 666 | fastmove_bottom_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 667 | } |
cjw851102 | 4:463abe5f5135 | 668 | } |
cjw851102 | 4:463abe5f5135 | 669 | } else { |
cjw851102 | 4:463abe5f5135 | 670 | fastmove_bottom_collision_flag = 0; |
cjw851102 | 4:463abe5f5135 | 671 | } |
cjw851102 | 4:463abe5f5135 | 672 | } |
cjw851102 | 4:463abe5f5135 | 673 | if( fastmove_bottom_collision_flag == 1) { |
cjw851102 | 4:463abe5f5135 | 674 | break; |
cjw851102 | 4:463abe5f5135 | 675 | } |
cjw851102 | 4:463abe5f5135 | 676 | } |
cjw851102 | 4:463abe5f5135 | 677 | } |
cjw851102 | 4:463abe5f5135 | 678 | |
cjw851102 | 4:463abe5f5135 | 679 | |
cjw851102 | 4:463abe5f5135 | 680 | void game_isr() |
cjw851102 | 4:463abe5f5135 | 681 | { |
cjw851102 | 4:463abe5f5135 | 682 | g_game_flag = 1; |
cjw851102 | 4:463abe5f5135 | 683 | } |
cjw851102 | 4:463abe5f5135 | 684 | |
cjw851102 | 4:463abe5f5135 | 685 | |
cjw851102 | 4:463abe5f5135 | 686 | void cancelLine() |
cjw851102 | 4:463abe5f5135 | 687 | { |
cjw851102 | 4:463abe5f5135 | 688 | // int linePattern[30][2]; //the pixel setting for one line(30x2 square) |
cjw851102 | 4:463abe5f5135 | 689 | int count; // count setting pixels two by two |
cjw851102 | 4:463abe5f5135 | 690 | for(int j=0; j<=46; j+=2) { |
cjw851102 | 4:463abe5f5135 | 691 | for(int i=0; i<=29; i++) { |
cjw851102 | 4:463abe5f5135 | 692 | if (lcd.getPixel(i,j)==0||lcd.getPixel(i,j+1)==0) { // there is clear pixel |
cjw851102 | 4:463abe5f5135 | 693 | count=0; |
cjw851102 | 4:463abe5f5135 | 694 | break; |
cjw851102 | 4:463abe5f5135 | 695 | } else if (lcd.getPixel(i,j)&&lcd.getPixel(i,j+1)) { |
cjw851102 | 4:463abe5f5135 | 696 | count++; |
cjw851102 | 4:463abe5f5135 | 697 | } |
cjw851102 | 4:463abe5f5135 | 698 | } |
cjw851102 | 4:463abe5f5135 | 699 | if(count==30) { // one line is filled |
cjw851102 | 4:463abe5f5135 | 700 | count=0; // reset the variable count |
cjw851102 | 4:463abe5f5135 | 701 | lcd.drawRect(0,j,29,1,2); //clear the line |
cjw851102 | 4:463abe5f5135 | 702 | buzzer = 0.5; |
cjw851102 | 4:463abe5f5135 | 703 | score+=10; // add the score |
cjw851102 | 4:463abe5f5135 | 704 | //update the score |
cjw851102 | 4:463abe5f5135 | 705 | char scoreBuffer[14]; |
cjw851102 | 4:463abe5f5135 | 706 | sprintf(scoreBuffer,"%d",score); |
cjw851102 | 4:463abe5f5135 | 707 | lcd.printString(scoreBuffer,42,3); |
cjw851102 | 4:463abe5f5135 | 708 | scan(); |
cjw851102 | 4:463abe5f5135 | 709 | // move the patterns above the line down for 2 pixels' hight |
cjw851102 | 4:463abe5f5135 | 710 | for (int x=0; x<=29; x++) { |
cjw851102 | 4:463abe5f5135 | 711 | for (int y=j; y>=0; y--) { |
cjw851102 | 4:463abe5f5135 | 712 | if (buffer[x][y]) { |
cjw851102 | 4:463abe5f5135 | 713 | lcd.clearPixel(x,y); |
cjw851102 | 4:463abe5f5135 | 714 | lcd.setPixel(x,y+2); |
cjw851102 | 4:463abe5f5135 | 715 | } |
cjw851102 | 4:463abe5f5135 | 716 | } |
cjw851102 | 4:463abe5f5135 | 717 | } |
cjw851102 | 4:463abe5f5135 | 718 | } |
cjw851102 | 4:463abe5f5135 | 719 | } |
cjw851102 | 4:463abe5f5135 | 720 | } |
cjw851102 | 4:463abe5f5135 | 721 | |
cjw851102 | 4:463abe5f5135 | 722 | |
cjw851102 | 4:463abe5f5135 | 723 | void finishAnimation() |
cjw851102 | 4:463abe5f5135 | 724 | { |
cjw851102 | 4:463abe5f5135 | 725 | for (int j=47; j>=0; j--) { |
cjw851102 | 4:463abe5f5135 | 726 | lcd.drawRect(0,j,29,1,1); |
cjw851102 | 4:463abe5f5135 | 727 | wait(0.05); |
cjw851102 | 4:463abe5f5135 | 728 | lcd.refresh(); |
cjw851102 | 4:463abe5f5135 | 729 | } |
cjw851102 | 4:463abe5f5135 | 730 | } |
cjw851102 | 4:463abe5f5135 | 731 | |
cjw851102 | 4:463abe5f5135 | 732 | |
cjw851102 | 4:463abe5f5135 | 733 | bool buttonPressedInGame() |
cjw851102 | 4:463abe5f5135 | 734 | { |
cjw851102 | 4:463abe5f5135 | 735 | bool exit_game; |
cjw851102 | 4:463abe5f5135 | 736 | if (g_button_flag) { // user press button finish game |
cjw851102 | 4:463abe5f5135 | 737 | g_button_flag=0; |
cjw851102 | 4:463abe5f5135 | 738 | scan(); // save the currnet gaming screen |
cjw851102 | 4:463abe5f5135 | 739 | game.detach(); // detach the game ticker |
cjw851102 | 4:463abe5f5135 | 740 | lcd.clear(); |
cjw851102 | 4:463abe5f5135 | 741 | while(1) { |
cjw851102 | 4:463abe5f5135 | 742 | lcd.printString("Exit The Game?",1,1); |
cjw851102 | 4:463abe5f5135 | 743 | lcd.printString("YES",38,3); |
cjw851102 | 4:463abe5f5135 | 744 | lcd.printString("NO",38,4); |
cjw851102 | 4:463abe5f5135 | 745 | pointer(); // invoke pointer function |
cjw851102 | 4:463abe5f5135 | 746 | if (g_button_flag) { |
cjw851102 | 4:463abe5f5135 | 747 | g_button_flag=0; |
cjw851102 | 4:463abe5f5135 | 748 | if(pointer_position==0) { //"YES" -exit game |
cjw851102 | 4:463abe5f5135 | 749 | lcd.clear(); |
cjw851102 | 4:463abe5f5135 | 750 | state=0; // back to main menu |
cjw851102 | 4:463abe5f5135 | 751 | pointer_position=0; |
cjw851102 | 4:463abe5f5135 | 752 | exit_game=true; |
cjw851102 | 4:463abe5f5135 | 753 | int stored_score=read_score_SD(); |
cjw851102 | 4:463abe5f5135 | 754 | if (score>stored_score) { // if the score is higher than highest score, save it |
cjw851102 | 4:463abe5f5135 | 755 | save_score_SD(score); |
cjw851102 | 4:463abe5f5135 | 756 | } |
cjw851102 | 4:463abe5f5135 | 757 | score=0; //clear socre |
cjw851102 | 4:463abe5f5135 | 758 | red_led=1; |
cjw851102 | 4:463abe5f5135 | 759 | green_led=0; |
cjw851102 | 4:463abe5f5135 | 760 | break; |
cjw851102 | 4:463abe5f5135 | 761 | } else { //"NO" - continue the game |
cjw851102 | 4:463abe5f5135 | 762 | exit_game=false; |
cjw851102 | 4:463abe5f5135 | 763 | if(state==3) { // game level is easy |
cjw851102 | 4:463abe5f5135 | 764 | lcd.clear(); |
cjw851102 | 4:463abe5f5135 | 765 | for(int i=0; i<=83; i++) { // back to the gaming screen before press button |
cjw851102 | 4:463abe5f5135 | 766 | for(int j=0; j<=47; j++) { |
cjw851102 | 4:463abe5f5135 | 767 | if(buffer[i][j]) { |
cjw851102 | 4:463abe5f5135 | 768 | lcd.setPixel(i,j); |
cjw851102 | 4:463abe5f5135 | 769 | } |
cjw851102 | 4:463abe5f5135 | 770 | } |
cjw851102 | 4:463abe5f5135 | 771 | } |
cjw851102 | 4:463abe5f5135 | 772 | game.attach(&game_isr,0.2); // easy game |
cjw851102 | 4:463abe5f5135 | 773 | exit_game=false; |
cjw851102 | 4:463abe5f5135 | 774 | break; |
cjw851102 | 4:463abe5f5135 | 775 | } else if(state==4) {// game level is hard |
cjw851102 | 4:463abe5f5135 | 776 | lcd.clear(); |
cjw851102 | 4:463abe5f5135 | 777 | for(int i=0; i<=83; i++) {// back to the gaming screen before press button |
cjw851102 | 4:463abe5f5135 | 778 | for(int j=0; j<=47; j++) { |
cjw851102 | 4:463abe5f5135 | 779 | if(buffer[i][j]) { |
cjw851102 | 4:463abe5f5135 | 780 | lcd.setPixel(i,j); |
cjw851102 | 4:463abe5f5135 | 781 | } |
cjw851102 | 4:463abe5f5135 | 782 | } |
cjw851102 | 4:463abe5f5135 | 783 | } |
cjw851102 | 4:463abe5f5135 | 784 | game.attach(&game_isr,0.1);// hard game |
cjw851102 | 4:463abe5f5135 | 785 | break; |
cjw851102 | 4:463abe5f5135 | 786 | } |
cjw851102 | 4:463abe5f5135 | 787 | } |
cjw851102 | 4:463abe5f5135 | 788 | break; |
cjw851102 | 4:463abe5f5135 | 789 | } |
cjw851102 | 4:463abe5f5135 | 790 | } |
cjw851102 | 4:463abe5f5135 | 791 | } |
cjw851102 | 4:463abe5f5135 | 792 | if(exit_game) { |
cjw851102 | 4:463abe5f5135 | 793 | return true; |
cjw851102 | 4:463abe5f5135 | 794 | } else { |
cjw851102 | 4:463abe5f5135 | 795 | return false; |
cjw851102 | 4:463abe5f5135 | 796 | } |
cjw851102 | 4:463abe5f5135 | 797 | } |
cjw851102 | 4:463abe5f5135 | 798 | |
cjw851102 | 4:463abe5f5135 | 799 | |
cjw851102 | 4:463abe5f5135 | 800 | int read_score_SD() |
cjw851102 | 4:463abe5f5135 | 801 | { |
cjw851102 | 4:463abe5f5135 | 802 | fp = fopen("/sd/topscore.txt", "r"); //open file |
cjw851102 | 4:463abe5f5135 | 803 | int stored_top_score; |
cjw851102 | 4:463abe5f5135 | 804 | fscanf(fp, "%d",&stored_top_score); // ensure data type matches - note address operator (&) |
cjw851102 | 4:463abe5f5135 | 805 | fclose(fp); // ensure you close the file after reading |
cjw851102 | 4:463abe5f5135 | 806 | return stored_top_score; |
cjw851102 | 4:463abe5f5135 | 807 | } |
cjw851102 | 4:463abe5f5135 | 808 | |
cjw851102 | 4:463abe5f5135 | 809 | |
cjw851102 | 4:463abe5f5135 | 810 | void save_score_SD(int score) |
cjw851102 | 4:463abe5f5135 | 811 | { |
cjw851102 | 4:463abe5f5135 | 812 | fp = fopen("/sd/topscore.txt", "w"); |
cjw851102 | 4:463abe5f5135 | 813 | fprintf(fp, "%d",score); // ensure data type matches |
cjw851102 | 4:463abe5f5135 | 814 | fclose(fp); // ensure you close the file after writing |
cjw851102 | 4:463abe5f5135 | 815 | } |
cjw851102 | 4:463abe5f5135 | 816 | #endif |