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.

Committer:
WiredHome
Date:
Sun Mar 29 18:21:14 2020 +0000
Revision:
11:2bdc83648d7f
Parent:
10:a09d9bb9c5c8
Pick up a bug-fix on jpeg rendering

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 5:5ce8976cd303 1 #include "mbed.h"
WiredHome 5:5ce8976cd303 2 #include "playGround.h"
WiredHome 5:5ce8976cd303 3 #include "Piece.h"
WiredHome 5:5ce8976cd303 4 #include "Block.h"
WiredHome 5:5ce8976cd303 5 #include "Field.h"
WiredHome 5:5ce8976cd303 6 #include "BPG_Arial20x20.h"
WiredHome 5:5ce8976cd303 7 #include "BPG_Arial10x10.h"
WiredHome 5:5ce8976cd303 8 #include "Define.h"
WiredHome 5:5ce8976cd303 9 #include <ctime>
WiredHome 5:5ce8976cd303 10
WiredHome 5:5ce8976cd303 11 #ifdef CAP_TOUCH
WiredHome 5:5ce8976cd303 12 RA8875 TFT(p5,p6,p7,p12,NC, p9,p10,p13, "tft"); // SPI:{MOSI,MISO,SCK,/ChipSelect,/reset}, I2C:{SDA,SCL,/IRQ}, name
WiredHome 5:5ce8976cd303 13 #else
WiredHome 5:5ce8976cd303 14 RA8875 TFT(p5,p6,p7,p12,NC, "tft"); // SPI:{MOSI,MISO,SCK,/ChipSelect,/reset}, name
WiredHome 5:5ce8976cd303 15 #endif
WiredHome 5:5ce8976cd303 16
WiredHome 5:5ce8976cd303 17 // Hot-Spots
WiredHome 10:a09d9bb9c5c8 18 static const rect_t Drop = { DROP };
WiredHome 10:a09d9bb9c5c8 19 static const rect_t rLeft = { ROT_LEFT };
WiredHome 10:a09d9bb9c5c8 20 static const rect_t rRight = { ROT_RIGHT };
WiredHome 10:a09d9bb9c5c8 21 static const rect_t mLeft = { MOV_LEFT };
WiredHome 10:a09d9bb9c5c8 22 static const rect_t mRight = { MOV_RIGHT };
WiredHome 10:a09d9bb9c5c8 23 static const rect_t Replay = { REPLAY };
WiredHome 10:a09d9bb9c5c8 24 static const point_t orig = { ORIGIN_X,ORIGIN_Y };
WiredHome 10:a09d9bb9c5c8 25 static const point_t sb_orig = { SB_X, SB_Y };
WiredHome 7:0e426e81c566 26 // Convert cell coordinates to a rectangle location
WiredHome 7:0e426e81c566 27 //
WiredHome 7:0e426e81c566 28 rect_t CellPosToRect(int x, int y, point_t o = orig, int bs = BLOCK_SIZE) {
WiredHome 7:0e426e81c566 29 rect_t r;
WiredHome 7:0e426e81c566 30
WiredHome 7:0e426e81c566 31 r.p1.x = o.x + bs * (x + 1);
WiredHome 7:0e426e81c566 32 r.p1.y = o.y + bs * (y + 0);
WiredHome 7:0e426e81c566 33 r.p2.x = o.x + bs * (x + 2);
WiredHome 7:0e426e81c566 34 r.p2.y = o.y + bs * (y + 1);
WiredHome 7:0e426e81c566 35 return r;
WiredHome 7:0e426e81c566 36 }
WiredHome 5:5ce8976cd303 37
WiredHome 5:5ce8976cd303 38 // Draws Field on the screen. Draw both black and colored blocks
WiredHome 5:5ce8976cd303 39 // It does delete everything on the PlayGround what shouldn't be there
WiredHome 7:0e426e81c566 40 //
WiredHome 5:5ce8976cd303 41 void drawMap()
WiredHome 5:5ce8976cd303 42 {
WiredHome 6:d2aa47c92687 43 int y, x;
WiredHome 5:5ce8976cd303 44
WiredHome 5:5ce8976cd303 45 for ( y = 0 ; y < MAXY ; y++ ) {
WiredHome 5:5ce8976cd303 46 for ( x = 0 ; x < MAXX ; x++ ) {
WiredHome 5:5ce8976cd303 47 if ( Field[y][x] != 0 ) {
WiredHome 7:0e426e81c566 48 rect_t r = CellPosToRect(x,y);
WiredHome 7:0e426e81c566 49 TFT.fillrect(r, Field[y][x]);
WiredHome 7:0e426e81c566 50 TFT.rect(r, White );
WiredHome 5:5ce8976cd303 51 }
WiredHome 5:5ce8976cd303 52 }
WiredHome 5:5ce8976cd303 53 }
WiredHome 5:5ce8976cd303 54 }
WiredHome 5:5ce8976cd303 55
WiredHome 7:0e426e81c566 56
WiredHome 5:5ce8976cd303 57 // Draws Field on the screen. Draw only colored blocks
WiredHome 5:5ce8976cd303 58 // It doesn't delete anything on the playground what shouldn't be there
WiredHome 7:0e426e81c566 59 //
WiredHome 5:5ce8976cd303 60 void drawMapV2()
WiredHome 5:5ce8976cd303 61 {
WiredHome 5:5ce8976cd303 62 int y , x;
WiredHome 5:5ce8976cd303 63
WiredHome 5:5ce8976cd303 64 for ( y = 0 ; y < MAXY ; y++ ) {
WiredHome 5:5ce8976cd303 65 for ( x = 0 ; x < MAXX ; x++ ) {
WiredHome 7:0e426e81c566 66 rect_t r = CellPosToRect(x,y);
WiredHome 7:0e426e81c566 67 TFT.fillrect(r, Field[y][x]);
WiredHome 5:5ce8976cd303 68 if ( Field[y][x] != 0 )
WiredHome 7:0e426e81c566 69 TFT.rect(r, White );
WiredHome 5:5ce8976cd303 70 }
WiredHome 5:5ce8976cd303 71 }
WiredHome 5:5ce8976cd303 72 }
WiredHome 5:5ce8976cd303 73
WiredHome 5:5ce8976cd303 74 // Draws NewBlock on the playground.
WiredHome 7:0e426e81c566 75 //
WiredHome 5:5ce8976cd303 76 void drawBlock(Block NewBlock)
WiredHome 5:5ce8976cd303 77 {
WiredHome 5:5ce8976cd303 78 int ix , iy , x , y;
WiredHome 5:5ce8976cd303 79 x = NewBlock.x;
WiredHome 5:5ce8976cd303 80 y = NewBlock.y;
WiredHome 5:5ce8976cd303 81 for ( ix = x - 2 ; ix < x + 2 ; ix++ ) {
WiredHome 5:5ce8976cd303 82 for ( iy = y - 2 ; iy < y + 2 ; iy++ ) {
WiredHome 5:5ce8976cd303 83 if ( Piece[NewBlock.form][NewBlock.angle][ix - x + 2][iy - y + 2] != 0 ) {
WiredHome 7:0e426e81c566 84 rect_t r = CellPosToRect(ix,iy);
WiredHome 7:0e426e81c566 85 TFT.fillrect(r, Piece[NewBlock.form][NewBlock.angle][ix - x + 2][iy - y + 2]);
WiredHome 7:0e426e81c566 86 TFT.rect(r, White );
WiredHome 5:5ce8976cd303 87 }
WiredHome 5:5ce8976cd303 88 }
WiredHome 5:5ce8976cd303 89 }
WiredHome 5:5ce8976cd303 90 }
WiredHome 5:5ce8976cd303 91
WiredHome 5:5ce8976cd303 92 // Removes NewBlock from the playground.
WiredHome 7:0e426e81c566 93 //
WiredHome 5:5ce8976cd303 94 void clrBlock(Block NewBlock)
WiredHome 5:5ce8976cd303 95 {
WiredHome 5:5ce8976cd303 96 int ix , iy , x , y;
WiredHome 5:5ce8976cd303 97 x = NewBlock.x;
WiredHome 5:5ce8976cd303 98 y = NewBlock.y;
WiredHome 5:5ce8976cd303 99 for ( ix = x - 2 ; ix < x + 2 ; ix++ ) {
WiredHome 5:5ce8976cd303 100 for ( iy = y - 2 ; iy < y + 2 ; iy++ ) {
WiredHome 5:5ce8976cd303 101 if ( Piece[NewBlock.form][NewBlock.angle][ix - x + 2][iy - y + 2] != 0 ) {
WiredHome 7:0e426e81c566 102 rect_t r = CellPosToRect(ix,iy);
WiredHome 7:0e426e81c566 103 TFT.fillrect(r, Black );
WiredHome 5:5ce8976cd303 104 }
WiredHome 5:5ce8976cd303 105 }
WiredHome 5:5ce8976cd303 106 }
WiredHome 5:5ce8976cd303 107 }
WiredHome 5:5ce8976cd303 108
WiredHome 7:0e426e81c566 109
WiredHome 5:5ce8976cd303 110 // Draws Purple frame around playground
WiredHome 7:0e426e81c566 111 //
WiredHome 5:5ce8976cd303 112 void drawFrame()
WiredHome 5:5ce8976cd303 113 {
WiredHome 5:5ce8976cd303 114 int x, y;
WiredHome 7:0e426e81c566 115
WiredHome 7:0e426e81c566 116 for ( y = 0 ; y < (MAXY) ; y++ ) {
WiredHome 7:0e426e81c566 117 rect_t r = CellPosToRect(-1,y);
WiredHome 7:0e426e81c566 118
WiredHome 7:0e426e81c566 119 TFT.fillrect(r, Purple );
WiredHome 7:0e426e81c566 120 TFT.rect(r, DarkGray );
WiredHome 7:0e426e81c566 121 r = CellPosToRect(MAXX,y);
WiredHome 7:0e426e81c566 122 TFT.fillrect(r, Purple );
WiredHome 7:0e426e81c566 123 TFT.rect(r, DarkGray );
WiredHome 5:5ce8976cd303 124 }
WiredHome 7:0e426e81c566 125 for ( x = -1 ; x < (MAXX + 1) ; x++ ) {
WiredHome 7:0e426e81c566 126 rect_t r = CellPosToRect(x,MAXY);
WiredHome 7:0e426e81c566 127
WiredHome 7:0e426e81c566 128 TFT.fillrect(r, Purple );
WiredHome 7:0e426e81c566 129 TFT.rect(r, DarkGray );
WiredHome 5:5ce8976cd303 130 }
WiredHome 5:5ce8976cd303 131 }
WiredHome 5:5ce8976cd303 132
WiredHome 7:0e426e81c566 133
WiredHome 5:5ce8976cd303 134 // Initializes screen parameters, sets orentation, background,
WiredHome 5:5ce8976cd303 135 // fonts and cleans screen.
WiredHome 7:0e426e81c566 136 //
WiredHome 5:5ce8976cd303 137 void TFTInit()
WiredHome 5:5ce8976cd303 138 {
WiredHome 5:5ce8976cd303 139 TFT.init(LCD_W,LCD_H,LCD_C);
WiredHome 5:5ce8976cd303 140 TFT.TouchPanelInit();
WiredHome 5:5ce8976cd303 141 TFT.Backlight_u8(BL_NORM);
WiredHome 10:a09d9bb9c5c8 142 TFT.SetGraphicsOrientation();
WiredHome 5:5ce8976cd303 143 }
WiredHome 5:5ce8976cd303 144
WiredHome 7:0e426e81c566 145
WiredHome 5:5ce8976cd303 146 void ReInitGame() {
WiredHome 5:5ce8976cd303 147 TFT.foreground(White);
WiredHome 5:5ce8976cd303 148 TFT.background(Black);
WiredHome 5:5ce8976cd303 149 TFT.cls();
WiredHome 5:5ce8976cd303 150 TFT.SetLayerMode(RA8875::BooleanOR);
WiredHome 5:5ce8976cd303 151 TFT.SelectUserFont(BPG_Arial20x20);
WiredHome 5:5ce8976cd303 152 TFT.SelectDrawingLayer(1);
WiredHome 5:5ce8976cd303 153 TFT.SetGraphicsCursor(TITLE_X,TITLE_Y);
WiredHome 5:5ce8976cd303 154 TFT.printf("Tetris for the RA8875\r\n");
WiredHome 5:5ce8976cd303 155 TFT.SelectUserFont(BPG_Arial10x10);
WiredHome 5:5ce8976cd303 156 TFT.printf(" adapted by Smartware Computing");
WiredHome 5:5ce8976cd303 157 TFT.rect(Drop, Charcoal);
WiredHome 5:5ce8976cd303 158 TFT.rect(rLeft, Charcoal);
WiredHome 5:5ce8976cd303 159 TFT.rect(rRight, Charcoal);
WiredHome 5:5ce8976cd303 160 TFT.rect(mLeft, Charcoal);
WiredHome 5:5ce8976cd303 161 TFT.rect(mRight, Charcoal);
WiredHome 5:5ce8976cd303 162 TFT.SelectDrawingLayer(0);
WiredHome 6:d2aa47c92687 163 for (int y=0; y<MAXY; y++) {
WiredHome 6:d2aa47c92687 164 for (int x=0; x<MAXX; x++) {
WiredHome 6:d2aa47c92687 165 Field[y][x] = 0;
WiredHome 6:d2aa47c92687 166 }
WiredHome 6:d2aa47c92687 167 }
WiredHome 7:0e426e81c566 168 drawFrame();
WiredHome 7:0e426e81c566 169 drawMap();
WiredHome 5:5ce8976cd303 170 }
WiredHome 5:5ce8976cd303 171
WiredHome 7:0e426e81c566 172
WiredHome 5:5ce8976cd303 173 void gameOver(int score)
WiredHome 5:5ce8976cd303 174 {
WiredHome 5:5ce8976cd303 175 drawScore(score);
WiredHome 5:5ce8976cd303 176 TFT.fillrect(Replay, Blue);
WiredHome 5:5ce8976cd303 177 TFT.rect(Replay, White);
WiredHome 5:5ce8976cd303 178 TFT.foreground(White);
WiredHome 5:5ce8976cd303 179 TFT.background(Blue);
WiredHome 7:0e426e81c566 180 TFT.SetTextCursor((Replay.p1.x+Replay.p2.x)/2-7*TFT.fontwidth()/2,(Replay.p1.y+Replay.p2.y)/2-TFT.fontheight()/2);
WiredHome 7:0e426e81c566 181 TFT.puts("Replay?");
WiredHome 5:5ce8976cd303 182 }
WiredHome 5:5ce8976cd303 183
WiredHome 7:0e426e81c566 184
WiredHome 5:5ce8976cd303 185 bool ReplayTouched() {
WiredHome 5:5ce8976cd303 186 point_t p;
WiredHome 5:5ce8976cd303 187
WiredHome 5:5ce8976cd303 188 if (TFT.TouchPanelReadable(&p))
WiredHome 5:5ce8976cd303 189 return true;
WiredHome 5:5ce8976cd303 190 else
WiredHome 5:5ce8976cd303 191 return false;
WiredHome 5:5ce8976cd303 192 }
WiredHome 5:5ce8976cd303 193
WiredHome 7:0e426e81c566 194 void drawPeriod(int period)
WiredHome 7:0e426e81c566 195 {
WiredHome 7:0e426e81c566 196 TFT.SelectUserFont(BPG_Arial10x10);
WiredHome 7:0e426e81c566 197 TFT.SetTextCursor(PACE_X, PACE_Y);
WiredHome 7:0e426e81c566 198 TFT.foreground(Brown);
WiredHome 7:0e426e81c566 199 TFT.printf("Pace : %i", period);
WiredHome 7:0e426e81c566 200 }
WiredHome 7:0e426e81c566 201
WiredHome 5:5ce8976cd303 202 void drawScore(int score)
WiredHome 5:5ce8976cd303 203 {
WiredHome 5:5ce8976cd303 204 TFT.SelectUserFont(BPG_Arial20x20);
WiredHome 5:5ce8976cd303 205 TFT.SetTextCursor(SCORE_X, SCORE_Y);
WiredHome 5:5ce8976cd303 206 TFT.foreground(BrightRed);
WiredHome 5:5ce8976cd303 207 TFT.printf("Score : %i", score);
WiredHome 5:5ce8976cd303 208 }
WiredHome 5:5ce8976cd303 209
WiredHome 5:5ce8976cd303 210
WiredHome 5:5ce8976cd303 211 // Reads gestures from the screen.
WiredHome 5:5ce8976cd303 212 // Returns : 0 for dropping object down
WiredHome 5:5ce8976cd303 213 // 1 for moving object to the right
WiredHome 5:5ce8976cd303 214 // 2 for moving object to the left
WiredHome 7:0e426e81c566 215 // 3 for rotating objec clockwise
WiredHome 7:0e426e81c566 216 // 4 for rotating object counter-clockwise
WiredHome 7:0e426e81c566 217 // 13 for ignore
WiredHome 7:0e426e81c566 218 gesture_t getGesture(point_t p)
WiredHome 5:5ce8976cd303 219 {
WiredHome 7:0e426e81c566 220 gesture_t gesture = ignore;
WiredHome 7:0e426e81c566 221
WiredHome 7:0e426e81c566 222 if (TFT.Intersect(Drop,p) ) { // below the bottom to drop
WiredHome 7:0e426e81c566 223 gesture = drop;
WiredHome 7:0e426e81c566 224 } else if (TFT.Intersect(rLeft, p) ) {
WiredHome 7:0e426e81c566 225 return spin_ccw;
WiredHome 7:0e426e81c566 226 } else if (TFT.Intersect(rRight, p) ) {
WiredHome 7:0e426e81c566 227 return spin_cw;
WiredHome 7:0e426e81c566 228 } else if (TFT.Intersect(mLeft, p) ) {
WiredHome 7:0e426e81c566 229 return move_left;
WiredHome 7:0e426e81c566 230 } else if (TFT.Intersect(mRight, p) ) {
WiredHome 7:0e426e81c566 231 return move_right;
WiredHome 5:5ce8976cd303 232 }
WiredHome 7:0e426e81c566 233 return gesture;
WiredHome 5:5ce8976cd303 234 }
WiredHome 5:5ce8976cd303 235
WiredHome 5:5ce8976cd303 236
WiredHome 5:5ce8976cd303 237
WiredHome 5:5ce8976cd303 238 // Moves NewBlock acording the gesture was read by function getGesture.
WiredHome 7:0e426e81c566 239 //
WiredHome 7:0e426e81c566 240 Block doGest(Block NewBlock, point_t p)
WiredHome 5:5ce8976cd303 241 {
WiredHome 5:5ce8976cd303 242 static bool lockout = false;
WiredHome 7:0e426e81c566 243 gesture_t gest = getGesture(p);
WiredHome 7:0e426e81c566 244 if ( gest != ignore ) {
WiredHome 5:5ce8976cd303 245 switch ( gest ) {
WiredHome 7:0e426e81c566 246 case drop: {
WiredHome 5:5ce8976cd303 247 while ( !NewBlock.CheckBottom() ) {
WiredHome 5:5ce8976cd303 248 NewBlock.y++;
WiredHome 5:5ce8976cd303 249 }
WiredHome 5:5ce8976cd303 250 saveToField(NewBlock);
WiredHome 5:5ce8976cd303 251 drawFrame();
WiredHome 5:5ce8976cd303 252 lockout = false;
WiredHome 5:5ce8976cd303 253 break;
WiredHome 5:5ce8976cd303 254 }
WiredHome 7:0e426e81c566 255 case move_right: {
WiredHome 5:5ce8976cd303 256 NewBlock.moveRight();
WiredHome 5:5ce8976cd303 257 lockout = false;
WiredHome 5:5ce8976cd303 258 break;
WiredHome 5:5ce8976cd303 259 }
WiredHome 7:0e426e81c566 260 case move_left: {
WiredHome 5:5ce8976cd303 261 NewBlock.moveLeft();
WiredHome 5:5ce8976cd303 262 lockout = false;
WiredHome 5:5ce8976cd303 263 break;
WiredHome 5:5ce8976cd303 264 }
WiredHome 7:0e426e81c566 265 case spin_ccw: {
WiredHome 5:5ce8976cd303 266 if (!lockout) {
WiredHome 5:5ce8976cd303 267 NewBlock.rotateLeft();
WiredHome 5:5ce8976cd303 268 }
WiredHome 5:5ce8976cd303 269 break;
WiredHome 5:5ce8976cd303 270 }
WiredHome 7:0e426e81c566 271 case spin_cw: {
WiredHome 5:5ce8976cd303 272 if (!lockout) {
WiredHome 5:5ce8976cd303 273 NewBlock.rotateRight();
WiredHome 5:5ce8976cd303 274 }
WiredHome 5:5ce8976cd303 275 break;
WiredHome 5:5ce8976cd303 276 }
WiredHome 5:5ce8976cd303 277 }
WiredHome 5:5ce8976cd303 278 } else {
WiredHome 5:5ce8976cd303 279 lockout = false;
WiredHome 5:5ce8976cd303 280 }
WiredHome 5:5ce8976cd303 281 return NewBlock;
WiredHome 5:5ce8976cd303 282 }
WiredHome 5:5ce8976cd303 283
WiredHome 5:5ce8976cd303 284
WiredHome 7:0e426e81c566 285 // Draws the next block on the screen.
WiredHome 7:0e426e81c566 286 // Block is sized of SB_SIZE
WiredHome 5:5ce8976cd303 287
WiredHome 5:5ce8976cd303 288 void drawNextBlock(Block NewBlock)
WiredHome 5:5ce8976cd303 289 {
WiredHome 5:5ce8976cd303 290 int ix, iy;
WiredHome 5:5ce8976cd303 291
WiredHome 7:0e426e81c566 292 for ( ix = 0 ; ix < 4 ; ix++ ) {
WiredHome 7:0e426e81c566 293 for ( iy = 0 ; iy < 4 ; iy++ ) {
WiredHome 7:0e426e81c566 294 rect_t r = CellPosToRect(ix,iy, sb_orig, SB_SIZE);
WiredHome 5:5ce8976cd303 295
WiredHome 7:0e426e81c566 296 if ( Piece[NewBlock.nextForm][NewBlock.angle][ix][iy] != 0 ) {
WiredHome 7:0e426e81c566 297 TFT.fillrect(r, Piece[NewBlock.nextForm][NewBlock.angle][ix][iy]);
WiredHome 5:5ce8976cd303 298 TFT.rect(r, White );
WiredHome 5:5ce8976cd303 299 }
WiredHome 5:5ce8976cd303 300 }
WiredHome 5:5ce8976cd303 301 }
WiredHome 5:5ce8976cd303 302 }
WiredHome 5:5ce8976cd303 303
WiredHome 7:0e426e81c566 304
WiredHome 7:0e426e81c566 305 // Clear the Next Block indicator
WiredHome 7:0e426e81c566 306 //
WiredHome 5:5ce8976cd303 307 void clrNextBlock(Block NewBlock)
WiredHome 5:5ce8976cd303 308 {
WiredHome 7:0e426e81c566 309 rect_t r0 = CellPosToRect(0,0, sb_orig, SB_SIZE);
WiredHome 7:0e426e81c566 310 rect_t r1 = CellPosToRect(3,3, sb_orig, SB_SIZE);
WiredHome 5:5ce8976cd303 311 rect_t r;
WiredHome 7:0e426e81c566 312 r.p1 = r0.p1;
WiredHome 7:0e426e81c566 313 r.p2 = r1.p2;
WiredHome 5:5ce8976cd303 314 TFT.fillrect( r, Black );
WiredHome 5:5ce8976cd303 315 }