
Simple tetris game to show usage of C12832 LCD.
Diff: mtrix.h
- Revision:
- 0:644f70b470b5
- Child:
- 1:cdd5880742fc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mtrix.h Mon Mar 17 19:47:49 2014 +0000 @@ -0,0 +1,319 @@ +#ifndef MBED_MTRIS_MAIN_HEADER_H +#define MBED_MTRIS_MAIN_HEADER_H + +#include <string> +#include <utility> + +#define LCD_W 16 +#define LCD_H 16 +#define BRICK_SIZE_X 4 +#define BRICK_SIZE_Y 4 + +/* QUBE +.... .... .... .... +.##. .##. .##. .##. +.##. .##. .##. .##. +.... .... .... .... +*/ +#define BRICK_QUBE_1 {0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0} +#define BRICK_QUBE_2 {0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0} +#define BRICK_QUBE_3 {0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0} +#define BRICK_QUBE_4 {0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0} + +/* T-agon + .... .... .... .... + .#.. #... .... .#.. + ###. ##.. ###. ##.. + .... #... .#.. .#.. +*/ +#define BRICK_T_1 {0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0} +#define BRICK_T_2 {0,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0} +#define BRICK_T_3 {0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0} +#define BRICK_T_4 {0,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0} + +/* L-agon + #... .... .... .... + #... ###. ##.. ..#. + ##.. #... .#.. ###. + .... .... .#.. .... +*/ +#define BRICK_L_1 {1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0} +#define BRICK_L_2 {0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0} +#define BRICK_L_3 {0,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0} +#define BRICK_L_4 {0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0} + +/* I-agon + .#.. .... .#.. .... + .#.. #### .#.. #### + .#.. .... .#.. .... + .#.. .... .#.. .... +*/ +#define BRICK_I_1 {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0} +#define BRICK_I_2 {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0} +#define BRICK_I_3 {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0} +#define BRICK_I_4 {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0} + + +/* +-agon + .#.. .#.. .#.. .#.. + ###. ###. ###. ###. + .#.. .#.. .#.. .#.. + .... .... .... .... +*/ +#define BRICK_P_1 {0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0} +#define BRICK_P_2 {0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0} +#define BRICK_P_3 {0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0} +#define BRICK_P_4 {0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0} + +/* *-agon + .... .... .... .... + .#.. .#.. .#.. .#.. + .... .... .... .... + .... .... .... .... +*/ +#define BRICK_S_1 {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0} +#define BRICK_S_2 {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0} +#define BRICK_S_3 {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0} +#define BRICK_S_4 {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0} + +/* 4-agon + #... .... #... .... + ##.. .##. ##.. .##. + .#.. ##.. .#.. ##.. + .... .... .... .... +*/ +#define BRICK_4_1 {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0} +#define BRICK_4_2 {0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0} +#define BRICK_4_3 {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0} +#define BRICK_4_4 {0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0} + +#define MTRIX_BRICOK_COUNT 7 + +template <class T> +class MBEDtrisBrick +{ +public: + typedef T brick_pattern[BRICK_SIZE_X][BRICK_SIZE_Y]; + + MBEDtrisBrick::MBEDtrisBrick() + { + brick_index = 0; + brick_rotate_index = 0; + } + + char getcell(int posx, int posy) + { + static T brick[MTRIX_BRICOK_COUNT][4][BRICK_SIZE_X][BRICK_SIZE_Y] = + { + {BRICK_QUBE_1, BRICK_QUBE_2, BRICK_QUBE_3, BRICK_QUBE_4}, + {BRICK_T_1, BRICK_T_2, BRICK_T_3, BRICK_T_4}, + {BRICK_L_1, BRICK_L_2, BRICK_L_3, BRICK_L_4}, + {BRICK_I_1, BRICK_I_2, BRICK_I_3, BRICK_I_4}, + {BRICK_P_1, BRICK_P_2, BRICK_P_3, BRICK_P_4}, + {BRICK_S_1, BRICK_S_2, BRICK_S_3, BRICK_S_4}, + {BRICK_4_1, BRICK_4_2, BRICK_4_3, BRICK_4_4} + }; + + return brick[brick_index][brick_rotate_index][posx][posy]; + } + + int rotate_next() { return brick_rotate_index = (brick_rotate_index + 1) % 4; } + int rotate_prev() { return brick_rotate_index = (brick_rotate_index == 0) ? 3 : brick_rotate_index - 1; } + + int brick_next() { return brick_index = (brick_index + 1) % MTRIX_BRICOK_COUNT; } + int brick_prev() { return brick_index = (brick_index == 0) ? (MTRIX_BRICOK_COUNT - 1) : brick_rotate_index - 1; } + +protected: + int brick_index; + int brick_rotate_index; +}; + + +template <class T> +class MBEDtrisTheGame +{ +public: + MBEDtrisTheGame::MBEDtrisTheGame() + { + fill_matrix(0); + } + + void set_new_brick_pos() + { + int g_brick_pos_x = (LCD_W) / 2; + int g_brick_pos_y = 0; + } + + void fill_matrix(char pattern) + { + for (int x = 0; x < LCD_W; x++) + { + for (int y = 0; y < LCD_H; y++) + { + lcd_matrix[x][y] = pattern; + } + } + } + +public: + bool detect_brick_bottom_collision(int offset_x, int offset_y); + bool detect_brick_collision(int offset_x, int offset_y); + bool detect_brick_side_collision(int offset_x, int offset_y); + bool append_brick_to_matrix(); + + bool try_move_left(); + bool try_move_right(); + bool try_move_down(); + bool try_rotate(); + + void move_brick_left(int offset = 1) { g_brick_pos_x -= offset; } + void move_brick_right(int offset = 1) { g_brick_pos_x += offset; } + void move_brick_up(int offset = 1) { g_brick_pos_y -= offset; } + void move_brick_down(int offset = 1) { try_move_down(); } + + T get_matrix_cell(int pos_x, int pos_y) { return lcd_matrix[pos_x][pos_y]; } + T get_brick_cell(int pos_x, int pos_y) { return brick.getcell(pos_x, pos_y); } + std::pair<int, int> get_brick_pos() { return std::make_pair(g_brick_pos_x, g_brick_pos_y); } + +protected: + // Brick in use + MBEDtrisBrick<T> brick; + + // Display with solid elements + T lcd_matrix[LCD_W][LCD_H]; + + // Curent brick screen posiotion + int g_brick_pos_x; + int g_brick_pos_y; +}; + +template <class T> +bool MBEDtrisTheGame<T>::detect_brick_bottom_collision(int offset_x, int offset_y) +{ + for (int x = 0; x < BRICK_SIZE_X; x++) + { + for (int y = 0; y < BRICK_SIZE_Y; y++) + { + if (brick.getcell(x, y) && (g_brick_pos_y + offset_y + y >= LCD_H)) + { + return true; + } + } + } + return false; +} + +template <class T> +bool MBEDtrisTheGame<T>::detect_brick_collision(int offset_x, int offset_y) +{ + for (int x = 0; x < BRICK_SIZE_X; x++) + { + for (int y = 0; y < BRICK_SIZE_Y; y++) + { + if (brick.getcell(x, y) && lcd_matrix[g_brick_pos_x + offset_x + x][g_brick_pos_y + offset_y + y]) + { + return true; + } + } + } + return false; +} + +template <class T> +bool MBEDtrisTheGame<T>::detect_brick_side_collision(int offset_x, int offset_y) +{ + for (int x = 0; x < BRICK_SIZE_X; x++) + { + for (int y = 0; y < BRICK_SIZE_Y; y++) + { + if (brick.getcell(x, y) && g_brick_pos_x + offset_x + x < 0) + { + return true; + } + if (brick.getcell(x, y) && (g_brick_pos_x + offset_x + x >= LCD_W)) + { + return true; + } + } + } + return false; +} + +template <class T> +bool MBEDtrisTheGame<T>::append_brick_to_matrix() +{ + for (int x = 0; x < BRICK_SIZE_X; x++) + { + for (int y = 0; y < BRICK_SIZE_Y; y++) + { + if (brick.getcell(x, y)) + { + lcd_matrix[g_brick_pos_x + x][g_brick_pos_y + y] = brick.getcell(x, y); + } + } + } + return true; +} + +template <class T> +bool MBEDtrisTheGame<T>::try_move_left() +{ + bool collision_size = detect_brick_side_collision(-1, 0); + bool collision_brick = detect_brick_collision(-1, 0); + if (!collision_size && !collision_brick) + { + g_brick_pos_x--; + return true; + } + return false; +} + +template <class T> +bool MBEDtrisTheGame<T>::try_move_right() +{ + bool collision_size = detect_brick_side_collision(1, 0); + bool collision_brick = detect_brick_collision(1, 0); + if (!collision_size && !collision_brick) + { + g_brick_pos_x++; + return true; + } + return false; +} + +template <class T> +bool MBEDtrisTheGame<T>::try_move_down() +{ + bool brick_collision = detect_brick_collision(0, 1); + bool brick_bottom_collision = detect_brick_bottom_collision(0, 1); + + if (brick_collision || brick_bottom_collision) + { + append_brick_to_matrix(); + // Create new brick + brick.brick_next(); + g_brick_pos_x = (LCD_W - BRICK_SIZE_X) / 2; + g_brick_pos_y = 0; + return false; + } + g_brick_pos_y++; + return true; +} + +template <class T> +bool MBEDtrisTheGame<T>::try_rotate() +{ + brick.rotate_next(); + bool brick_collision = detect_brick_collision(0, 1); + bool brick_bottom_collision = detect_brick_bottom_collision(0, 1); + bool brick_side_collision = detect_brick_side_collision(0, 0); + + if (brick_collision || brick_bottom_collision || brick_side_collision) + { + brick.rotate_prev(); + return false; + } + return true; +} + +#endif