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.
Tetris/playGround.cpp
- Committer:
- WiredHome
- Date:
- 2019-07-28
- Revision:
- 9:b97b336ab36a
- Parent:
- 7:0e426e81c566
- Child:
- 10:a09d9bb9c5c8
File content as of revision 9:b97b336ab36a:
#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> #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 // Hot-Spots static const rect_t Drop = rect_t( DROP ); static const rect_t rLeft = rect_t( ROT_LEFT ); static const rect_t rRight = rect_t( ROT_RIGHT ); static const rect_t mLeft = rect_t( MOV_LEFT ); static const rect_t mRight = rect_t( MOV_RIGHT ); static const rect_t Replay = rect_t( REPLAY ); static const point_t orig = point_t(ORIGIN_X,ORIGIN_Y); static const point_t sb_orig = point_t(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; for ( y = 0 ; y < MAXY ; y++ ) { for ( x = 0 ; x < MAXX ; x++ ) { if ( Field[y][x] != 0 ) { 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++ ) { rect_t r = CellPosToRect(x,y); TFT.fillrect(r, Field[y][x]); if ( Field[y][x] != 0 ) TFT.rect(r, 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 ) { 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; 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 ) { 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) ; 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 = -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); 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); for (int y=0; y<MAXY; y++) { for (int x=0; x<MAXX; x++) { Field[y][x] = 0; } } drawFrame(); drawMap(); } void gameOver(int score) { drawScore(score); TFT.fillrect(Replay, Blue); TFT.rect(Replay, White); TFT.foreground(White); TFT.background(Blue); 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; if (TFT.TouchPanelReadable(&p)) return true; else 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); 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 objec clockwise // 4 for rotating object counter-clockwise // 13 for ignore gesture_t getGesture(point_t p) { 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; } return gesture; } // Moves NewBlock acording the gesture was read by function getGesture. // Block doGest(Block NewBlock, point_t p) { static bool lockout = false; gesture_t gest = getGesture(p); if ( gest != ignore ) { switch ( gest ) { case drop: { while ( !NewBlock.CheckBottom() ) { NewBlock.y++; } saveToField(NewBlock); drawFrame(); lockout = false; break; } case move_right: { NewBlock.moveRight(); lockout = false; break; } case move_left: { NewBlock.moveLeft(); lockout = false; break; } case spin_ccw: { if (!lockout) { NewBlock.rotateLeft(); } break; } case spin_cw: { if (!lockout) { NewBlock.rotateRight(); } break; } } } else { lockout = false; } return NewBlock; } // Draws the next block on the screen. // Block is sized of SB_SIZE void drawNextBlock(Block NewBlock) { int ix, iy; for ( ix = 0 ; ix < 4 ; ix++ ) { for ( iy = 0 ; iy < 4 ; iy++ ) { rect_t r = CellPosToRect(ix,iy, sb_orig, SB_SIZE); 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 = r0.p1; r.p2 = r1.p2; TFT.fillrect( r, Black ); }