Tetris for the RA8875, derived from another users implementation.
Fork of Tetris by
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.
Diff: Tetris/playGround.cpp
- 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 ); +}