Tetris for the RA8875, derived from another users implementation.

Dependencies:   RA8875

Fork of Tetris by Sergejs Popovs

Tetris, adapted to the RA8875 graphics library and display.

As currently implemented, this version is defined for the 800x480 display. A number of macros can adapt it for other screen resolutions.

Further, while presently configured for landscape mode, it should be fairly easy to reconfigure it for portrait mode.

Revision:
5:5ce8976cd303
Child:
6:d2aa47c92687
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tetris/playGround.cpp	Sat Mar 18 22:30:32 2017 +0000
@@ -0,0 +1,339 @@
+#include "mbed.h"
+#include "playGround.h"
+#include "Piece.h"
+#include "Block.h"
+#include "Field.h"
+#include "BPG_Arial20x20.h"
+#include "BPG_Arial10x10.h"
+#include "Define.h"
+#include <ctime>
+
+// Define this for 800x480 panel, undefine for 480x272
+#define BIG_SCREEN
+
+// Define this for Cap touch panel, undefine for resistive
+#define CAP_TOUCH
+
+#ifdef CAP_TOUCH
+RA8875 TFT(p5,p6,p7,p12,NC, p9,p10,p13, "tft"); // SPI:{MOSI,MISO,SCK,/ChipSelect,/reset}, I2C:{SDA,SCL,/IRQ}, name
+#else
+RA8875 TFT(p5,p6,p7,p12,NC, "tft");             // SPI:{MOSI,MISO,SCK,/ChipSelect,/reset}, name
+LocalFileSystem local("local");                     // access to calibration file for resistive touch.
+#endif
+
+#ifdef BIG_SCREEN
+    #define LCD_W 800
+    #define LCD_H 480
+    #define LCD_C 8         // color - bits per pixel
+    #define BL_NORM 25      // Backlight Normal setting (0 to 255)
+#else
+    #define LCD_W 480
+    #define LCD_H 272
+    #define LCD_C 8         // color - bits per pixel
+    #define BL_NORM 25      // Backlight Normal setting (0 to 255)
+#endif
+
+#if 0
+#define PIN_XP              p20
+#define PIN_XM              p19
+#define PIN_YP              p18
+#define PIN_YM              p17
+#define PIN_MOSI            p11
+#define PIN_MISO            p12
+#define PIN_SCLK            p13
+#define PIN_CS_TFT          p14
+#define PIN_DC_TFT          p21
+#define PIN_BL_TFT          p15
+#define PIN_CS_SD           p4
+#endif 
+
+// Hot-Spots
+static const rect_t Drop   = { DROP };
+static const rect_t rLeft  = { ROT_LEFT };
+static const rect_t rRight = { ROT_RIGHT };
+static const rect_t mLeft  = { MOV_LEFT };
+static const rect_t mRight = { MOV_RIGHT };
+static const rect_t Replay = { REPLAY };
+
+//  Draws Field on the screen. Draw both black and colored blocks
+//  It does delete everything on the PlayGround what shouldn't be there
+
+void drawMap()
+{
+    int y , x;
+
+    for ( y = 0 ; y < MAXY ; y++ ) {
+        for ( x = 0 ; x < MAXX ; x++ ) {
+            if ( Field[y][x] != 0 ) {
+                TFT.fillrect(ORIGIN_X + BLOCK_SIZE * ( x + 1 ), ORIGIN_Y + BLOCK_SIZE * y,
+                             ORIGIN_X + BLOCK_SIZE * ( x + 2 ), ORIGIN_Y + BLOCK_SIZE * ( y + 1 ),
+                             Field[y][x]);
+                TFT.rect(ORIGIN_X + BLOCK_SIZE * ( x + 1 ), ORIGIN_Y + BLOCK_SIZE * y,
+                         ORIGIN_X + BLOCK_SIZE * ( x + 2 ), ORIGIN_Y + BLOCK_SIZE * ( y + 1 ),
+                         White );
+            }
+        }
+    }
+}
+
+//  Draws Field on the screen. Draw only colored blocks
+//  It doesn't delete anything on the playground what shouldn't be there
+
+void drawMapV2()
+{
+    int y , x;
+
+    for ( y = 0 ; y < MAXY ; y++ ) {
+        for ( x = 0 ; x < MAXX ; x++ ) {
+            TFT.fillrect(ORIGIN_X + BLOCK_SIZE * ( x + 1 ), ORIGIN_Y + BLOCK_SIZE * y,
+                         ORIGIN_X + BLOCK_SIZE * ( x + 2 ), ORIGIN_Y + BLOCK_SIZE * ( y + 1 ),
+                         Field[y][x]);
+            if ( Field[y][x] != 0 )
+                TFT.rect(ORIGIN_X + BLOCK_SIZE * ( x + 1 ), ORIGIN_Y + BLOCK_SIZE * y,
+                         ORIGIN_X + BLOCK_SIZE * ( x + 2 ), ORIGIN_Y + BLOCK_SIZE * ( y + 1 ),
+                         White );
+        }
+    }
+}
+
+//  Draws NewBlock on the playground. 
+
+void drawBlock(Block NewBlock)
+{
+    int ix , iy , x , y;
+    x = NewBlock.x;
+    y = NewBlock.y;
+    for ( ix = x - 2 ; ix < x + 2 ; ix++ ) {
+        for ( iy = y - 2 ; iy < y + 2 ; iy++ ) {
+            if ( Piece[NewBlock.form][NewBlock.angle][ix - x + 2][iy - y + 2] != 0 ) {
+                TFT.fillrect(ORIGIN_X + BLOCK_SIZE * ( ix + 1 ), ORIGIN_Y + BLOCK_SIZE * iy,
+                             ORIGIN_X + BLOCK_SIZE * ( ix + 2 ), ORIGIN_Y + BLOCK_SIZE * ( iy + 1 ),
+                             Piece[NewBlock.form][NewBlock.angle][ix - x + 2][iy - y + 2]);
+                TFT.rect(ORIGIN_X + BLOCK_SIZE * ( ix + 1 ), ORIGIN_Y + BLOCK_SIZE * iy,
+                         ORIGIN_X + BLOCK_SIZE * ( ix + 2 ), ORIGIN_Y + BLOCK_SIZE * ( iy + 1 ),
+                         White );
+            }
+        }
+    }
+}
+
+//  Removes NewBlock from the playground. 
+
+void clrBlock(Block NewBlock)
+{
+    int ix , iy , x , y;
+    x = NewBlock.x;
+    y = NewBlock.y;
+    for ( ix = x - 2 ; ix < x + 2 ; ix++ ) {
+        for ( iy = y - 2 ; iy < y + 2 ; iy++ ) {
+            if ( Piece[NewBlock.form][NewBlock.angle][ix - x + 2][iy - y + 2] != 0 ) {
+                TFT.fillrect(ORIGIN_X + BLOCK_SIZE * ( ix + 1 ), ORIGIN_Y + BLOCK_SIZE * iy,
+                             ORIGIN_X + BLOCK_SIZE * ( ix + 2 ), ORIGIN_Y + BLOCK_SIZE * ( iy + 1 ),
+                             Black );
+            }
+        }
+    }
+}
+
+//  Draws Purple frame around playground
+
+void drawFrame()
+{
+    int x, y;
+    for ( y = 0 ; y < (MAXY + 1) * BLOCK_SIZE ; y += BLOCK_SIZE ) {
+        TFT.fillrect(ORIGIN_X + 0, ORIGIN_Y + y, ORIGIN_X + BLOCK_SIZE, ORIGIN_Y + y + BLOCK_SIZE, Purple );
+        TFT.rect(ORIGIN_X + 0, ORIGIN_Y + y, ORIGIN_X + BLOCK_SIZE, ORIGIN_Y + y + BLOCK_SIZE, DarkGray );
+        TFT.fillrect(ORIGIN_X + (MAXX + 1) * BLOCK_SIZE, ORIGIN_Y + y, ORIGIN_X + (MAXX + 2) * BLOCK_SIZE, ORIGIN_Y + y + BLOCK_SIZE, Purple );
+        TFT.rect(ORIGIN_X + (MAXX + 1) * BLOCK_SIZE, ORIGIN_Y + y, ORIGIN_X + (MAXX + 2) * BLOCK_SIZE, ORIGIN_Y + y + BLOCK_SIZE, DarkGray );
+    }
+    for ( x = 0 ; x < (MAXX + 2) * BLOCK_SIZE ; x += BLOCK_SIZE ) {
+        TFT.fillrect(ORIGIN_X + x, ORIGIN_Y + MAXY * BLOCK_SIZE, ORIGIN_X + x + BLOCK_SIZE, ORIGIN_Y + (MAXY + 1) * BLOCK_SIZE, Purple );
+        TFT.rect(ORIGIN_X + x, ORIGIN_Y + MAXY * BLOCK_SIZE, ORIGIN_X + x + BLOCK_SIZE, ORIGIN_Y + (MAXY + 1) * BLOCK_SIZE, DarkGray );
+    }
+}
+
+//  Initializes screen parameters, sets orentation, background,
+//  fonts and cleans screen.
+
+void TFTInit()
+{
+    TFT.init(LCD_W,LCD_H,LCD_C);
+    TFT.TouchPanelInit();
+    TFT.Backlight_u8(BL_NORM);
+    TFT.SetOrientation();
+}
+
+void ReInitGame() {
+    TFT.foreground(White);
+    TFT.background(Black);
+    TFT.cls();
+    TFT.SetLayerMode(RA8875::BooleanOR);
+    TFT.SelectUserFont(BPG_Arial20x20);
+    TFT.SelectDrawingLayer(1);
+    TFT.SetGraphicsCursor(TITLE_X,TITLE_Y);
+    TFT.printf("Tetris for the RA8875\r\n");
+    TFT.SelectUserFont(BPG_Arial10x10);
+    TFT.printf("   adapted by Smartware Computing");
+    TFT.rect(Drop, Charcoal);
+    TFT.rect(rLeft, Charcoal);
+    TFT.rect(rRight, Charcoal);
+    TFT.rect(mLeft, Charcoal);
+    TFT.rect(mRight, Charcoal);
+    TFT.SelectDrawingLayer(0);
+}
+
+void gameOver(int score)
+{
+    drawScore(score);
+    TFT.fillrect(Replay, Blue);
+    TFT.rect(Replay, White);
+    TFT.SetTextCursor(Replay.p1.x+15,(Replay.p1.y+Replay.p2.y)/2-TFT.fontheight()/2);
+    TFT.foreground(White);
+    TFT.background(Blue);
+    TFT.puts("Replay");
+}
+
+bool ReplayTouched() {
+    point_t p;
+    
+    if (TFT.TouchPanelReadable(&p))
+        return true;
+    else
+        return false;
+}
+
+void drawScore(int score)
+{
+    TFT.SelectUserFont(BPG_Arial20x20);
+    TFT.SetTextCursor(SCORE_X, SCORE_Y);
+    TFT.foreground(BrightRed);
+    TFT.printf("Score : %i", score);
+}
+
+
+//  Reads gestures from the screen. 
+//  Returns         :   0 for dropping object down
+//                      1 for moving object to the right
+//                      2 for moving object to the left
+//                      3 for rotating object counter-clockwise
+//                      4 for rotating objec clockwise
+int getGesture()
+{
+    point_t p;
+    clock_t start_s = clock();
+    int flag = 0;
+    while( !flag ) {
+        p.x=0;
+        p.y=0;
+        TouchCode_t t = TFT.TouchCode();
+        if ( t == touch || t == held ) {
+            p = TFT.TouchCoordinates();            // read analog pos.
+            flag = 1;
+        } else if ( start_s > 10 )
+            return 13;
+    }
+    if ( TFT.Intersect(Drop,p) ) {      // below the bottom to drop
+        return 0 ;
+    } else if ( TFT.Intersect(rLeft, p) ) {
+        return 3;
+    } else if ( TFT.Intersect(rRight, p) ) {
+        return 4;
+    } else if ( TFT.Intersect(mLeft, p) ) {
+        return 2;
+    } else if ( TFT.Intersect(mRight, p) ) {
+        return 1;
+    }
+    return 13;         //13 = IGNORE
+}
+
+//  Returns status of screen. If it was touched returns true, else false
+
+bool TouchStatus()
+{
+    if ( TFT.TouchPanelReadable() )
+        return true;
+    return false;
+}
+
+//  Moves NewBlock acording the gesture was read by function getGesture.
+
+Block doGest(Block NewBlock)
+{
+    static bool lockout = false;
+    int gest = getGesture();
+    if ( gest != 13 ) {
+        switch ( gest ) {
+            case 0: {
+                while ( !NewBlock.CheckBottom() ) {
+                    NewBlock.y++;
+                }
+                saveToField(NewBlock);
+                drawFrame();
+                lockout = false;
+                break;
+            }
+            case 1: {
+                NewBlock.moveRight();
+                lockout = false;
+                break;
+            }
+            case 2: {
+                NewBlock.moveLeft();
+                lockout = false;
+                break;
+            }
+            case 3: {
+                if (!lockout) {
+                    lockout = true;
+                    NewBlock.rotateLeft();
+                }
+                break;
+            }
+            case 4: {
+                if (!lockout) {
+                    lockout = true;
+                    NewBlock.rotateRight();
+                }
+                break;
+            }
+        }
+    } else {
+        lockout = false;
+    }
+    return NewBlock;
+}
+
+
+//  Draws the next block on the bottom of the screen. 
+//  Block is sized of SMALL_BLOCK_SIZED
+
+void drawNextBlock(Block NewBlock)
+{
+    int ix, iy;
+
+    for ( ix = - 2 ; ix < 2 ; ix++ ) {
+        for ( iy = - 2 ; iy < 2 ; iy++ ) {
+            rect_t r;
+
+            r.p1.x = SB_X - 2 * SMALL_BLOCK_SIZE + SMALL_BLOCK_SIZE * ( ix + 1 );
+            r.p1.y = SB_Y - 2 * SMALL_BLOCK_SIZE + SMALL_BLOCK_SIZE * iy;
+            r.p2.x = SB_X - 2 * SMALL_BLOCK_SIZE + SMALL_BLOCK_SIZE * ( ix + 2 );
+            r.p2.y = SB_Y - 2 * SMALL_BLOCK_SIZE + SMALL_BLOCK_SIZE * ( iy + 1 );
+            if ( Piece[NewBlock.nextForm][NewBlock.angle][ix + 2][iy + 2] != 0 ) {
+                TFT.fillrect(r, Piece[NewBlock.nextForm][NewBlock.angle][ix + 2][iy + 2]);
+                TFT.rect(r, White );
+            }
+        }
+    }
+}
+
+void clrNextBlock(Block NewBlock)
+{
+    rect_t r;
+    
+    r.p1.x = SB_X - 2 * SMALL_BLOCK_SIZE + SMALL_BLOCK_SIZE * ( -2 + 1 );
+    r.p1.y = SB_Y - 2 * SMALL_BLOCK_SIZE + SMALL_BLOCK_SIZE * -2;
+    r.p2.x = SB_X - 2 * SMALL_BLOCK_SIZE + SMALL_BLOCK_SIZE * ( 1 + 2 );
+    r.p2.y = SB_Y - 2 * SMALL_BLOCK_SIZE + SMALL_BLOCK_SIZE * ( 1 + 1 );
+    TFT.fillrect( r, Black );
+}