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:
7:0e426e81c566
Parent:
6:d2aa47c92687
Child:
9:b97b336ab36a
--- a/Tetris/playGround.cpp	Sat Mar 18 23:53:12 2017 +0000
+++ b/Tetris/playGround.cpp	Sat Aug 18 22:20:38 2018 +0000
@@ -8,31 +8,12 @@
 #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
 #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
-
-
 // Hot-Spots
 static const rect_t Drop   = { DROP };
 static const rect_t rLeft  = { ROT_LEFT };
@@ -40,10 +21,23 @@
 static const rect_t mLeft  = { MOV_LEFT };
 static const rect_t mRight = { MOV_RIGHT };
 static const rect_t Replay = { REPLAY };
+static const point_t orig  = {ORIGIN_X,ORIGIN_Y};
+static const point_t sb_orig = {SB_X, SB_Y};
+// Convert cell coordinates to a rectangle location
+//
+rect_t CellPosToRect(int x, int y, point_t o = orig, int bs = BLOCK_SIZE) {
+    rect_t r;
+    
+    r.p1.x = o.x + bs * (x + 1);
+    r.p1.y = o.y + bs * (y + 0);
+    r.p2.x = o.x + bs * (x + 2);
+    r.p2.y = o.y + bs * (y + 1);
+    return r;
+}
 
 //  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;
@@ -51,39 +45,34 @@
     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 );
+                rect_t r = CellPosToRect(x,y);
+                TFT.fillrect(r, Field[y][x]);
+                TFT.rect(r, 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]);
+            rect_t r = CellPosToRect(x,y);
+            TFT.fillrect(r, 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 );
+                TFT.rect(r, White );
         }
     }
 }
 
 //  Draws NewBlock on the playground. 
-
+//
 void drawBlock(Block NewBlock)
 {
     int ix , iy , x , y;
@@ -92,19 +81,16 @@
     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 );
+                rect_t r = CellPosToRect(ix,iy);
+                TFT.fillrect(r, Piece[NewBlock.form][NewBlock.angle][ix - x + 2][iy - y + 2]);
+                TFT.rect(r, White );
             }
         }
     }
 }
 
 //  Removes NewBlock from the playground. 
-
+//
 void clrBlock(Block NewBlock)
 {
     int ix , iy , x , y;
@@ -113,34 +99,41 @@
     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 );
+                rect_t r = CellPosToRect(ix,iy);
+                TFT.fillrect(r, 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 ( y = 0 ; y < (MAXY) ; y++ ) {
+        rect_t r = CellPosToRect(-1,y);
+
+        TFT.fillrect(r, Purple );
+        TFT.rect(r, DarkGray );
+        r = CellPosToRect(MAXX,y);
+        TFT.fillrect(r, Purple );
+        TFT.rect(r, 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 );
+    for ( x = -1 ; x < (MAXX + 1) ; x++ ) {
+        rect_t r = CellPosToRect(x,MAXY);
+
+        TFT.fillrect(r, Purple );
+        TFT.rect(r, DarkGray );
     }
 }
 
+
 //  Initializes screen parameters, sets orentation, background,
 //  fonts and cleans screen.
-
+//
 void TFTInit()
 {
     TFT.init(LCD_W,LCD_H,LCD_C);
@@ -149,6 +142,7 @@
     TFT.SetOrientation();
 }
 
+
 void ReInitGame() {
     TFT.foreground(White);
     TFT.background(Black);
@@ -171,19 +165,23 @@
             Field[y][x] = 0;
         }
     }
+    drawFrame();
+    drawMap();
 }
 
+
 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");
+    TFT.SetTextCursor((Replay.p1.x+Replay.p2.x)/2-7*TFT.fontwidth()/2,(Replay.p1.y+Replay.p2.y)/2-TFT.fontheight()/2);
+    TFT.puts("Replay?");
 }
 
+
 bool ReplayTouched() {
     point_t p;
     
@@ -193,6 +191,14 @@
         return false;
 }
 
+void drawPeriod(int period)
+{
+    TFT.SelectUserFont(BPG_Arial10x10);
+    TFT.SetTextCursor(PACE_X, PACE_Y);
+    TFT.foreground(Brown);
+    TFT.printf("Pace : %i", period);    
+}
+
 void drawScore(int score)
 {
     TFT.SelectUserFont(BPG_Arial20x20);
@@ -206,55 +212,38 @@
 //  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()
+//                      3 for rotating objec clockwise
+//                      4 for rotating object counter-clockwise
+//                      13 for ignore
+gesture_t getGesture(point_t p)
 {
-    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;
+    gesture_t gesture = ignore;
+
+    if (TFT.Intersect(Drop,p) ) {      // below the bottom to drop
+        gesture = drop;
+    } else if (TFT.Intersect(rLeft, p) ) {
+        return spin_ccw;
+    } else if (TFT.Intersect(rRight, p) ) {
+        return spin_cw;
+    } else if (TFT.Intersect(mLeft, p) ) {
+        return move_left;
+    } else if (TFT.Intersect(mRight, p) ) {
+        return move_right;
     }
-    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
+    return gesture;
 }
 
-//  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)
+//
+Block doGest(Block NewBlock, point_t p)
 {
     static bool lockout = false;
-    int gest = getGesture();
-    if ( gest != 13 ) {
+    gesture_t gest = getGesture(p);
+    if ( gest != ignore ) {
         switch ( gest ) {
-            case 0: {
+            case drop: {
                 while ( !NewBlock.CheckBottom() ) {
                     NewBlock.y++;
                 }
@@ -263,26 +252,24 @@
                 lockout = false;
                 break;
             }
-            case 1: {
+            case move_right: {
                 NewBlock.moveRight();
                 lockout = false;
                 break;
             }
-            case 2: {
+            case move_left: {
                 NewBlock.moveLeft();
                 lockout = false;
                 break;
             }
-            case 3: {
+            case spin_ccw: {
                 if (!lockout) {
-                    lockout = true;
                     NewBlock.rotateLeft();
                 }
                 break;
             }
-            case 4: {
+            case spin_cw: {
                 if (!lockout) {
-                    lockout = true;
                     NewBlock.rotateRight();
                 }
                 break;
@@ -295,36 +282,34 @@
 }
 
 
-//  Draws the next block on the bottom of the screen. 
-//  Block is sized of SMALL_BLOCK_SIZED
+//  Draws the next block on the screen. 
+//  Block is sized of SB_SIZE
 
 void drawNextBlock(Block NewBlock)
 {
     int ix, iy;
 
-    for ( ix = - 2 ; ix < 2 ; ix++ ) {
-        for ( iy = - 2 ; iy < 2 ; iy++ ) {
-            rect_t r;
+    for ( ix = 0 ; ix < 4 ; ix++ ) {
+        for ( iy = 0 ; iy < 4 ; iy++ ) {
+            rect_t r = CellPosToRect(ix,iy, sb_orig, SB_SIZE);
 
-            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]);
+            if ( Piece[NewBlock.nextForm][NewBlock.angle][ix][iy] != 0 ) {
+                TFT.fillrect(r, Piece[NewBlock.nextForm][NewBlock.angle][ix][iy]);
                 TFT.rect(r, White );
             }
         }
     }
 }
 
+
+//  Clear the Next Block indicator
+//
 void clrNextBlock(Block NewBlock)
 {
+    rect_t r0 = CellPosToRect(0,0, sb_orig, SB_SIZE);
+    rect_t r1 = CellPosToRect(3,3, sb_orig, SB_SIZE);
     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 );
+    r.p1 = r0.p1;
+    r.p2 = r1.p2;
     TFT.fillrect( r, Black );
 }