Simple tetris game to show usage of C12832 LCD.

Dependencies:   C12832_lcd mbed

Files at this revision

API Documentation at this revision

Comitter:
PrzemekWirkus
Date:
Mon Mar 17 19:47:49 2014 +0000
Child:
1:cdd5880742fc
Commit message:
First draft, game loop is still poor.

Changed in this revision

C12832_lcd.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
mtrix.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C12832_lcd.lib	Mon Mar 17 19:47:49 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/dreschpe/code/C12832_lcd/#8f86576007d6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Mar 17 19:47:49 2014 +0000
@@ -0,0 +1,74 @@
+#include "mbed.h"
+#include "C12832_lcd.h"
+#include "mtrix.h"
+
+MBEDtrisTheGame<char> game;
+ 
+C12832_LCD lcd;
+BusIn joy(p15,p12,p13,p16);
+DigitalIn fire(p14);
+BusOut leds(LED1,LED2,LED3,LED4);
+
+#define KEY_LEFT    2
+#define KEY_RIGHT   1
+#define KEY_UP      4
+#define KEY_DOWN    8
+
+#define BOUNCER_SIZE 2
+
+int main()
+{
+    // Welcome message
+    lcd.cls();
+ 
+    while(1) {
+        int joy_key = joy.read();
+        switch (joy_key) {
+            case KEY_LEFT:  { game.try_rotate();      break; }
+            case KEY_RIGHT: { game.try_move_right();  break; }
+            case KEY_UP:    { game.try_rotate();      break; }
+            case KEY_DOWN:  { game.move_brick_down(); break; }
+        }
+        
+        // PRINT MATRIX
+        for (int x = 0; x < LCD_W; x++)
+        {
+            for (int y = 0; y < LCD_H; y++)
+            {               
+                // This should be replaces with just 'putpixel on LCD'
+                int draw_pix_x = x*BOUNCER_SIZE;
+                int draw_pix_y = y*BOUNCER_SIZE;
+
+                if (game.get_matrix_cell(x, y))
+                {
+                    lcd.rect(draw_pix_x, draw_pix_y, draw_pix_x+BOUNCER_SIZE-1, draw_pix_y+BOUNCER_SIZE-1, 1);
+                }
+                else
+                {
+                    lcd.rect(draw_pix_x, draw_pix_y, draw_pix_x+BOUNCER_SIZE-1, draw_pix_y+BOUNCER_SIZE-1, 0);
+                }
+            }
+        }
+   
+        // PRINT BRICK
+        for (int x = 0; x < BRICK_SIZE_X; x++)
+        {
+            for (int y = 0; y < BRICK_SIZE_Y; y++)
+            {
+                if (game.get_brick_cell(x, y))
+                {
+                    std::pair<int, int> brick_pos = game.get_brick_pos();
+
+                    int draw_pix_x = (brick_pos.first + x) * BOUNCER_SIZE;
+                    int draw_pix_y = (brick_pos.second + y) * BOUNCER_SIZE;
+                    lcd.rect(draw_pix_x, draw_pix_y, draw_pix_x+BOUNCER_SIZE-1, draw_pix_y+BOUNCER_SIZE-1, 1);
+                }
+            }
+        }
+   
+        
+        lcd.copy_to_lcd();
+        wait(1.0);
+        game.move_brick_down();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Mar 17 19:47:49 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/8e73be2a2ac1
\ No newline at end of file
--- /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