Simple tetris game to show usage of C12832 LCD.

Dependencies:   C12832_lcd mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mtrix.h Source File

mtrix.h

00001 #ifndef MBED_MTRIS_MAIN_HEADER_H
00002 #define MBED_MTRIS_MAIN_HEADER_H
00003 
00004 #include <string>
00005 #include <utility>
00006 
00007 #define LCD_W           8
00008 #define LCD_H           24
00009 #define BRICK_SIZE_X    4
00010 #define BRICK_SIZE_Y    4
00011 
00012 /* QUBE
00013 .... .... .... ....
00014 .##. .##. .##. .##.
00015 .##. .##. .##. .##.
00016 .... .... .... ....
00017 */
00018 #define BRICK_QUBE_1 {0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0}
00019 #define BRICK_QUBE_2 {0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0}
00020 #define BRICK_QUBE_3 {0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0}
00021 #define BRICK_QUBE_4 {0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0}
00022 
00023 /* T-agon
00024     .... .... .... ....
00025     .#.. #... .... .#..
00026     ###. ##.. ###. ##..
00027     .... #... .#.. .#..
00028 */
00029 #define BRICK_T_1 {0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0}
00030 #define BRICK_T_2 {0,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0}
00031 #define BRICK_T_3 {0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0}
00032 #define BRICK_T_4 {0,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0}
00033 
00034 /* L-agon
00035     #... .... .... ....
00036     #... ###. ##.. ..#.
00037     ##.. #... .#.. ###.
00038     .... .... .#.. ....
00039 */
00040 #define BRICK_L_1 {1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0}
00041 #define BRICK_L_2 {0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0}
00042 #define BRICK_L_3 {0,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0}
00043 #define BRICK_L_4 {0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0}
00044 
00045 /* I-agon
00046     .#.. .... .#.. ....
00047     .#.. #### .#.. ####
00048     .#.. .... .#.. ....
00049     .#.. .... .#.. ....
00050 */
00051 #define BRICK_I_1 {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}
00052 #define BRICK_I_2 {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0}
00053 #define BRICK_I_3 {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}
00054 #define BRICK_I_4 {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0}
00055 
00056 
00057 /* +-agon
00058     .#.. .#.. .#.. .#..
00059     ###. ###. ###. ###.
00060     .#.. .#.. .#.. .#..
00061     .... .... .... ....
00062 */
00063 #define BRICK_P_1 {0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0}
00064 #define BRICK_P_2 {0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0}
00065 #define BRICK_P_3 {0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0}
00066 #define BRICK_P_4 {0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0}                                     
00067 
00068 /* *-agon
00069     .... .... .... ....
00070     .#.. .#.. .#.. .#..
00071     .... .... .... ....
00072     .... .... .... ....
00073 */
00074 #define BRICK_S_1 {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}
00075 #define BRICK_S_2 {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}
00076 #define BRICK_S_3 {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}
00077 #define BRICK_S_4 {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}                                           
00078 
00079 /* 4-agon
00080     #... .... #... ....
00081     ##.. .##. ##.. .##.
00082     .#.. ##.. .#.. ##..
00083     .... .... .... ....
00084 */
00085 #define BRICK_4_1 {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}
00086 #define BRICK_4_2 {0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0}
00087 #define BRICK_4_3 {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}
00088 #define BRICK_4_4 {0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0}
00089 
00090 #define MTRIX_BRICOK_COUNT 7
00091 
00092 template <class T>
00093 class MBEDtrisBrick
00094 {
00095 public:
00096     typedef T brick_pattern[BRICK_SIZE_X][BRICK_SIZE_Y];
00097 
00098     MBEDtrisBrick::MBEDtrisBrick()
00099     {
00100         brick_index = 0;
00101         brick_rotate_index = 0;
00102     }
00103 
00104     char getcell(int posx, int posy)
00105     {
00106         static T brick[MTRIX_BRICOK_COUNT][4][BRICK_SIZE_X][BRICK_SIZE_Y] = 
00107         {
00108             {BRICK_QUBE_1, BRICK_QUBE_2, BRICK_QUBE_3, BRICK_QUBE_4},
00109             {BRICK_T_1,    BRICK_T_2,    BRICK_T_3,    BRICK_T_4},
00110             {BRICK_L_1,    BRICK_L_2,    BRICK_L_3,    BRICK_L_4},
00111             {BRICK_I_1,    BRICK_I_2,    BRICK_I_3,    BRICK_I_4},
00112             {BRICK_P_1,    BRICK_P_2,    BRICK_P_3,    BRICK_P_4},
00113             {BRICK_S_1,    BRICK_S_2,    BRICK_S_3,    BRICK_S_4},
00114             {BRICK_4_1,    BRICK_4_2,    BRICK_4_3,    BRICK_4_4}
00115         };
00116 
00117         return brick[brick_index][brick_rotate_index][posx][posy];
00118     }
00119 
00120     int rotate_next() { return brick_rotate_index = (brick_rotate_index + 1) % 4; }
00121     int rotate_prev() { return brick_rotate_index = (brick_rotate_index == 0) ? 3 : brick_rotate_index - 1; }
00122 
00123     int brick_next() { return brick_index = (brick_index + 1) % MTRIX_BRICOK_COUNT; }
00124     int brick_prev() { return brick_index = (brick_index == 0) ? (MTRIX_BRICOK_COUNT - 1) : brick_rotate_index - 1; }
00125 
00126 protected:
00127     int brick_index;
00128     int brick_rotate_index;
00129 };
00130 
00131 
00132 template <class T>
00133 class MBEDtrisTheGame
00134 {
00135 public:
00136     MBEDtrisTheGame::MBEDtrisTheGame()
00137     {
00138         fill_matrix(0);
00139     }
00140 
00141     void set_new_brick_pos()
00142     {
00143         int g_brick_pos_x = (LCD_W) / 2;
00144         int g_brick_pos_y = 0;
00145     }
00146 
00147     void fill_matrix(char pattern)
00148     {
00149         for (int x = 0; x < LCD_W; x++)
00150         {
00151             for (int y = 0; y < LCD_H; y++)
00152             {
00153                 lcd_matrix[x][y] = pattern;
00154             }
00155         }
00156     }
00157 
00158 public:
00159     bool detect_brick_bottom_collision(int offset_x, int offset_y);
00160     bool detect_brick_collision(int offset_x, int offset_y);
00161     bool detect_brick_side_collision(int offset_x, int offset_y);
00162     bool append_brick_to_matrix();
00163 
00164     bool try_move_left();
00165     bool try_move_right();
00166     bool try_move_down();
00167     bool try_rotate();
00168 
00169     void move_brick_left(int offset = 1)    { g_brick_pos_x -= offset; }
00170     void move_brick_right(int offset = 1)   { g_brick_pos_x += offset; }
00171     void move_brick_up(int offset = 1)      { g_brick_pos_y -= offset; }
00172     void move_brick_down(int offset = 1)    { try_move_down(); }
00173 
00174     T get_matrix_cell(int pos_x, int pos_y) { return lcd_matrix[pos_x][pos_y]; }
00175     T get_brick_cell(int pos_x, int pos_y)  { return brick.getcell(pos_x, pos_y); }
00176     std::pair<int, int> get_brick_pos()     { return std::make_pair(g_brick_pos_x, g_brick_pos_y); }
00177 
00178 protected:
00179     // Brick in use
00180     MBEDtrisBrick<T> brick;
00181 
00182     // Display with solid elements
00183     T lcd_matrix[LCD_W][LCD_H];
00184 
00185     // Curent brick screen posiotion
00186     int g_brick_pos_x;
00187     int g_brick_pos_y;
00188 };
00189 
00190 template <class T>
00191 bool MBEDtrisTheGame<T>::detect_brick_bottom_collision(int offset_x, int offset_y)
00192 {
00193     for (int x = 0; x < BRICK_SIZE_X; x++)
00194     {
00195         for (int y = 0; y < BRICK_SIZE_Y; y++)
00196         {
00197             if (brick.getcell(x, y) && (g_brick_pos_y + offset_y + y >= LCD_H))
00198             {
00199                 return true;
00200             }
00201         }
00202     }
00203     return false;
00204 }
00205 
00206 template <class T>
00207 bool MBEDtrisTheGame<T>::detect_brick_collision(int offset_x, int offset_y)
00208 {
00209     for (int x = 0; x < BRICK_SIZE_X; x++)
00210     {
00211         for (int y = 0; y < BRICK_SIZE_Y; y++)
00212         {
00213             if (brick.getcell(x, y) && lcd_matrix[g_brick_pos_x + offset_x + x][g_brick_pos_y + offset_y + y])
00214             {
00215                 return true;
00216             }
00217         }
00218     }
00219     return false;
00220 }
00221 
00222 template <class T>
00223 bool MBEDtrisTheGame<T>::detect_brick_side_collision(int offset_x, int offset_y)
00224 {
00225     for (int x = 0; x < BRICK_SIZE_X; x++)
00226     {
00227         for (int y = 0; y < BRICK_SIZE_Y; y++)
00228         {
00229             if (brick.getcell(x, y) && g_brick_pos_x + offset_x + x < 0)
00230             {
00231                 return true;
00232             }
00233             if (brick.getcell(x, y) && (g_brick_pos_x + offset_x + x >= LCD_W))
00234             {
00235                 return true;
00236             }
00237         }
00238     }
00239     return false;
00240 }
00241 
00242 template <class T>
00243 bool MBEDtrisTheGame<T>::append_brick_to_matrix()
00244 {
00245     for (int x = 0; x < BRICK_SIZE_X; x++)
00246     {
00247         for (int y = 0; y < BRICK_SIZE_Y; y++)
00248         {
00249             if (brick.getcell(x, y))
00250             {
00251                 lcd_matrix[g_brick_pos_x + x][g_brick_pos_y + y] = brick.getcell(x, y);
00252             }
00253         }
00254     }
00255     return true;
00256 }
00257 
00258 template <class T>
00259 bool MBEDtrisTheGame<T>::try_move_left()
00260 {
00261     bool collision_size = detect_brick_side_collision(-1, 0);
00262     bool collision_brick = detect_brick_collision(-1, 0);
00263     if (!collision_size && !collision_brick)
00264     {
00265         g_brick_pos_x--;
00266         return true;
00267     }
00268     return false;
00269 }
00270 
00271 template <class T>
00272 bool MBEDtrisTheGame<T>::try_move_right()
00273 {
00274     bool collision_size = detect_brick_side_collision(1, 0);
00275     bool collision_brick = detect_brick_collision(1, 0);
00276     if (!collision_size && !collision_brick)
00277     {
00278         g_brick_pos_x++;
00279         return true;
00280     }
00281     return false;
00282 }
00283 
00284 template <class T>
00285 bool MBEDtrisTheGame<T>::try_move_down()
00286 {
00287     bool brick_collision = detect_brick_collision(0, 1);
00288     bool brick_bottom_collision = detect_brick_bottom_collision(0, 1);
00289 
00290     if (brick_collision || brick_bottom_collision)
00291     {
00292         append_brick_to_matrix();
00293         // Create new brick
00294         brick.brick_next();
00295         g_brick_pos_x = (LCD_W - BRICK_SIZE_X) / 2;
00296         g_brick_pos_y = 0;
00297         return false;
00298     }
00299     g_brick_pos_y++;
00300     return true;
00301 }
00302 
00303 template <class T>
00304 bool MBEDtrisTheGame<T>::try_rotate()
00305 {
00306     brick.rotate_next();
00307     bool brick_collision = detect_brick_collision(0, 1);
00308     bool brick_bottom_collision = detect_brick_bottom_collision(0, 1);
00309     bool brick_side_collision = detect_brick_side_collision(0, 0);
00310 
00311     if (brick_collision || brick_bottom_collision || brick_side_collision)
00312     {
00313         brick.rotate_prev();
00314         return false;
00315     }
00316     return true;
00317 }
00318 
00319 #endif