Dependencies:   4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player

Files at this revision

API Documentation at this revision

Comitter:
jsanchez307
Date:
Wed Nov 30 21:57:25 2022 +0000
Commit message:
Tetris Skeleton V 1.0

Changed in this revision

4DGL-uLCD-SE.lib Show annotated file Show diff for this revision Revisions of this file
Board.cpp Show annotated file Show diff for this revision Revisions of this file
Board.h Show annotated file Show diff for this revision Revisions of this file
Game.cpp Show annotated file Show diff for this revision Revisions of this file
Game.h Show annotated file Show diff for this revision Revisions of this file
Pieces.cpp Show annotated file Show diff for this revision Revisions of this file
Pieces.h Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
wave_player.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/4DGL-uLCD-SE.lib	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/4180_1/code/4DGL-uLCD-SE/#2cb1845d7681
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Board.cpp	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,208 @@
+#include "Board.h"
+
+/*
+==================
+Init
+==================
+*/
+Board::Board (Pieces *pPieces, int pScreenHeight)
+{
+    // Get the screen height
+    mScreenHeight = pScreenHeight;
+
+    // Get the pointer to the pieces class
+    mPieces = pPieces;
+
+    //Init the board blocks with free positions
+    InitBoard();
+}
+
+/*
+======================================                                  
+Init the board blocks with free positions
+====================================== 
+*/
+void Board::InitBoard()
+{
+    for (int i = 0; i < BOARD_WIDTH; i++)
+        for (int j = 0; j < BOARD_HEIGHT; j++)
+            mBoard[i][j] = POS_FREE;
+}
+
+/* 
+======================================                                  
+Store a piece in the board by filling the blocks
+
+Parameters:
+
+>> pX:      Horizontal position in blocks
+>> pY:      Vertical position in blocks
+>> pPiece:  Piece to draw
+>> pRotation:   1 of the 4 possible rotations
+====================================== 
+*/
+void Board::StorePiece (int pX, int pY, int pPiece, int pRotation)
+{
+    // Store each block of the piece into the board
+    for (int i1 = pX, i2 = 0; i1 < pX + PIECE_BLOCKS; i1++, i2++)
+    {
+        for (int j1 = pY, j2 = 0; j1 < pY + PIECE_BLOCKS; j1++, j2++)
+        {   
+            // Store only the blocks of the piece that are not holes
+            if (mPieces->GetBlockType (pPiece, pRotation, j2, i2) != 0)     
+                mBoard[i1][j1] = POS_FILLED;    
+        }
+    }
+}
+
+/* 
+======================================                                  
+Check if the game is over becase a piece have achived the upper position
+
+Returns true or false
+====================================== 
+*/
+bool Board::IsGameOver()
+{
+    //If the first line has blocks, then, game over
+    for (int i = 0; i < BOARD_WIDTH; i++)
+    {
+        if (mBoard[i][0] == POS_FILLED) return true;
+    }
+
+    return false;
+}
+
+/* 
+======================================                                  
+Delete a line of the board by moving all above lines down
+
+Parameters:
+
+>> pY:      Vertical position in blocks of the line to delete
+====================================== 
+*/
+void Board::DeleteLine (int pY)
+{
+    // Moves all the upper lines one row down
+    for (int j = pY; j > 0; j--)
+    {
+        for (int i = 0; i < BOARD_WIDTH; i++)
+        {
+            mBoard[i][j] = mBoard[i][j-1];
+        }
+    }   
+}
+
+/* 
+======================================                                  
+Delete all the lines that should be removed
+====================================== 
+*/
+int Board::DeletePossibleLines ()
+{
+    int count =0;
+    for (int j = 0; j < BOARD_HEIGHT; j++)
+    {
+        int i = 0;
+        while (i < BOARD_WIDTH)
+        {
+            if (mBoard[i][j] != POS_FILLED) break;
+            i++;
+        }
+
+        if (i == BOARD_WIDTH) 
+        {
+            DeleteLine (j);
+            count++;
+        }
+    }
+    return count;
+}
+
+/* 
+======================================                                  
+Returns 1 (true) if the this block of the board is empty, 0 if it is filled
+
+Parameters:
+
+>> pX:      Horizontal position in blocks
+>> pY:      Vertical position in blocks
+====================================== 
+*/
+bool Board::IsFreeBlock (int pX, int pY)
+{
+    if (mBoard [pX][pY] == POS_FREE) return true; else return false;
+}
+
+/* 
+======================================                                  
+Returns the horizontal position (isn pixels) of the block given like parameter
+
+Parameters:
+
+>> pPos:    Horizontal position of the block in the board
+====================================== 
+*/
+int Board::GetXPosInPixels (int pPos)
+{
+    return  ( ( BOARD_POSITION - (BLOCK_SIZE * (BOARD_WIDTH / 2)) ) + (pPos * BLOCK_SIZE) );
+}
+
+/* 
+======================================                                  
+Returns the vertical position (in pixels) of the block given like parameter
+
+Parameters:
+
+>> pPos:    Horizontal position of the block in the board
+====================================== 
+*/
+int Board::GetYPosInPixels (int pPos)
+{
+    return ( (mScreenHeight - (BLOCK_SIZE * BOARD_HEIGHT)) + (pPos * BLOCK_SIZE) );
+}
+
+/* 
+======================================                                  
+Check if the piece can be stored at this position without any collision
+Returns true if the movement is  possible, false if it not possible
+
+Parameters:
+
+>> pX:      Horizontal position in blocks
+>> pY:      Vertical position in blocks
+>> pPiece:  Piece to draw
+>> pRotation:   1 of the 4 possible rotations
+====================================== 
+*/
+bool Board::IsPossibleMovement (int pX, int pY, int pPiece, int pRotation)
+{
+    // Checks collision with pieces already stored in the board or the board limits
+    // This is just to check the 5x5 blocks of a piece with the appropiate area in the board
+    for (int i1 = pX, i2 = 0; i1 < pX + PIECE_BLOCKS; i1++, i2++)
+    {
+        for (int j1 = pY, j2 = 0; j1 < pY + PIECE_BLOCKS; j1++, j2++)
+        {   
+            // Check if the piece is outside the limits of the board
+            if (    i1 < 0          || 
+                i1 > BOARD_WIDTH  - 1   ||
+                j1 > BOARD_HEIGHT - 1)
+            {
+                if (mPieces->GetBlockType (pPiece, pRotation, j2, i2) != 0)
+                    return 0;       
+            }
+
+            // Check if the piece have collisioned with a block already stored in the map
+            if (j1 >= 0)    
+            {
+                if ((mPieces->GetBlockType (pPiece, pRotation, j2, i2) != 0) &&
+                    (!IsFreeBlock (i1, j1)) )
+                    return false;
+            }
+        }
+    }
+
+    // No collision
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Board.h	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,50 @@
+#ifndef _BOARD_
+#define _BOARD_
+
+// ------ Includes -----
+
+#include "Pieces.h"
+
+// ------ Defines -----
+
+#define BOARD_LINE_WIDTH 6          // Width of each of the two lines that delimit the board
+#define BLOCK_SIZE 6              // Width and Height of each block of a piece
+#define BOARD_POSITION 50          // Center position of the board from the left of the screen
+#define BOARD_WIDTH 10              // Board width in blocks 
+#define BOARD_HEIGHT 20             // Board height in blocks
+#define MIN_VERTICAL_MARGIN 8      // Minimum vertical margin for the board limit      
+#define MIN_HORIZONTAL_MARGIN 20    // Minimum horizontal margin for the board limit
+#define PIECE_BLOCKS 5              // Number of horizontal and vertical blocks of a matrix piece
+
+
+// --------------------------------------------------------------------------------
+//                                   Board
+// --------------------------------------------------------------------------------
+
+class Board
+{
+public:
+
+    Board                       (Pieces *pPieces, int pScreenHeight);
+
+    int GetXPosInPixels         (int pPos);
+    int GetYPosInPixels         (int pPos);
+    bool IsFreeBlock            (int pX, int pY);
+    bool IsPossibleMovement     (int pX, int pY, int pPiece, int pRotation);
+    void StorePiece             (int pX, int pY, int pPiece, int pRotation);
+    int DeletePossibleLines    ();
+    bool IsGameOver             ();
+
+private:
+
+        // enum holds no value besides the described properties
+    enum { POS_FREE, POS_FILLED };          // POS_FREE = free position of the board; POS_FILLED = filled position of the board
+    int mBoard [BOARD_WIDTH][BOARD_HEIGHT]; // Board that contains the pieces
+    Pieces *mPieces;
+    int mScreenHeight;
+
+    void InitBoard();
+    void DeleteLine (int pY);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Game.cpp	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,190 @@
+#include "Game.h"
+
+/* 
+======================================                                  
+Init
+====================================== 
+*/
+Game::Game(Board *pBoard, Pieces *pPieces, int pScreenHeight, uLCD_4DGL *pLCD,int initPiece,int initPos,int initNextPiece,int initNextPos) 
+{
+    mScreenHeight = pScreenHeight;
+    
+    // Get the pointer to the Board and Pieces classes
+    mBoard = pBoard;
+    mPieces = pPieces;
+    uLCD = pLCD;
+    // Game initialization
+    InitGame (initPiece,initPos,initNextPiece,initNextPos);
+}
+
+/* 
+======================================                                  
+Initial parameters of the game
+====================================== 
+*/
+void Game::InitGame(int initPiece,int initPos,int initNextPiece,int initNextPos)
+{
+    //points
+    points = 0;
+    clearedLineCount=0;
+
+    // First piece
+    mPiece          = initPiece;
+    mRotation       = initPos;
+    mPosX           = (BOARD_WIDTH / 2) + mPieces->GetXInitialPosition (mPiece, mRotation);
+    mPosY           = mPieces->GetYInitialPosition (mPiece, mRotation);
+
+    //  Next piece
+    mNextPiece      = initNextPiece;
+    mNextRotation   = initNextPos;
+    mNextPosX       = BOARD_WIDTH + 2;
+    mNextPosY       = 2;    
+}
+
+/* 
+======================================                                  
+Create a random piece
+====================================== 
+*/
+void Game::CreateNewPiece(int piece,int pos)
+{
+    // The new piece
+    mPiece          = mNextPiece;
+    mRotation       = mNextRotation;
+    mPosX           = (BOARD_WIDTH / 2) + mPieces->GetXInitialPosition (mPiece, mRotation);
+    mPosY           = mPieces->GetYInitialPosition (mPiece, mRotation);
+
+    // Random next piece
+    mNextPiece      = piece;
+    mNextRotation   = pos;
+}
+
+/* 
+======================================                                  
+Draw piece
+
+Parameters:
+
+>> pX:      Horizontal position in blocks
+>> pY:      Vertical position in blocks
+>> pPiece:  Piece to draw
+>> pRotation:   1 of the 4 possible rotations
+====================================== 
+*/
+void Game::DrawPiece (int pX, int pY, int pPiece, int pRotation, int colorIndex)
+{
+    // Obtain the position in pixel in the screen of the block we want to draw
+    int mPixelsX = mBoard->GetXPosInPixels (pX);
+    int mPixelsY = mBoard->GetYPosInPixels (pY);
+    int mColors [7]={16711680, 15955765, 16761893, 45401, 44763, 12462572, 29669};
+    // Travel the matrix of blocks of the piece and draw the blocks that are filled
+    for (int i = 0; i < PIECE_BLOCKS; i++)
+    {
+        for (int j = 0; j < PIECE_BLOCKS; j++)
+        {
+            if (mPieces->GetBlockType (pPiece, pRotation, j, i) != 0)
+                uLCD->filled_rectangle  (mPixelsX + i * BLOCK_SIZE, 
+                                    mPixelsY + j * BLOCK_SIZE, 
+                                    (mPixelsX + i * BLOCK_SIZE) + BLOCK_SIZE - 1, 
+                                    (mPixelsY + j * BLOCK_SIZE) + BLOCK_SIZE - 1, 
+                                    mColors[colorIndex]);
+        }
+    }
+}
+
+/* 
+======================================                                  
+Draw board
+
+Draw the two lines that delimit the board
+====================================== 
+*/
+void Game::DrawBoard ()
+{
+    // Calculate the limits of the board in pixels  
+    int mX1 = BOARD_POSITION - (BLOCK_SIZE * (BOARD_WIDTH / 2)) - 1;
+    int mX2 = BOARD_POSITION + (BLOCK_SIZE * (BOARD_WIDTH / 2));
+    int mY = mScreenHeight - (BLOCK_SIZE * BOARD_HEIGHT);
+    
+    // Check that the vertical margin is not to small
+    //assert (mY > MIN_VERTICAL_MARGIN);
+
+    // Rectangles that delimits the board
+    uLCD->filled_rectangle (mX1 - BOARD_LINE_WIDTH, mY, mX1, mScreenHeight - 1, BLUE);
+    uLCD->filled_rectangle (mX2, mY, mX2 + BOARD_LINE_WIDTH, mScreenHeight - 1, BLUE);
+    
+    // Check that the horizontal margin is not to small
+    //assert (mX1 > MIN_HORIZONTAL_MARGIN);
+
+    // Drawing the blocks that are already stored in the board
+    mX1 += 1;
+    for (int i = 0; i < BOARD_WIDTH; i++)
+    {
+        for (int j = 0; j < BOARD_HEIGHT; j++)
+        {   
+            // Check if the block is filled, if so, draw it
+            if (!mBoard->IsFreeBlock(i, j)) 
+                uLCD->filled_rectangle (    mX1 + i * BLOCK_SIZE, 
+                                        mY + j * BLOCK_SIZE, 
+                                        (mX1 + i * BLOCK_SIZE) + BLOCK_SIZE - 1, 
+                                        (mY + j * BLOCK_SIZE) + BLOCK_SIZE - 1, 
+                                        10066329);
+        }
+    }   
+}
+
+/* 
+======================================                                  
+Draw scene
+
+Draw all the objects of the scene
+====================================== 
+*/
+void Game::DrawScene ()
+{
+    DrawBoard();
+    DrawPiece (mPosX, mPosY, mPiece, mRotation, mPiece);                    // Draw the playing piece
+    DrawPiece (mNextPosX, mNextPosY, mNextPiece, mNextRotation, mNextPiece);    // Draw the next piece
+}
+
+void Game::ErasePiece (int pX, int pY, int pPiece, int pRotation)
+{
+    if(pPiece==-1) return;
+    // Obtain the position in pixel in the screen of the block we want to draw
+    int mPixelsX = mBoard->GetXPosInPixels (pX);
+    int mPixelsY = mBoard->GetYPosInPixels (pY);
+
+    // Travel the matrix of blocks of the piece and draw the blocks that are filled
+    for (int i = 0; i < PIECE_BLOCKS; i++)
+    {
+        for (int j = 0; j < PIECE_BLOCKS; j++)
+        {
+            if (mPieces->GetBlockType (pPiece, pRotation, j, i) != 0)
+                uLCD->filled_rectangle  (mPixelsX + i * BLOCK_SIZE, 
+                                    mPixelsY + j * BLOCK_SIZE, 
+                                    (mPixelsX + i * BLOCK_SIZE) + BLOCK_SIZE - 1, 
+                                    (mPixelsY + j * BLOCK_SIZE) + BLOCK_SIZE - 1, 
+                                    0);
+        }
+    }
+}
+
+void Game::AddPoints(int newGain)
+{
+    points+=newGain;
+}
+
+void Game::AddClearedLines(int newGain)
+{
+    clearedLineCount+=newGain;
+}
+
+int Game::GetPoints()
+{
+    return points;
+}
+
+int Game::GetClearedLines()
+{
+    return clearedLineCount;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Game.h	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,58 @@
+#ifndef _GAME_
+#define _GAME_
+
+// ------ Includes -----
+
+#include "Board.h"
+#include "Pieces.h"
+#include "uLCD_4DGL.h"
+
+// ------ Defines -----
+
+#define WAIT_TIME 700           // Number of milliseconds that the piece remains before going 1 block down */ 
+
+
+// -----------------------------------------------------
+// Game
+// -----------------------------------------------------
+
+class Game
+{
+public:
+
+    Game (Board *pBoard, Pieces *pPieces, int pScreenHeight, uLCD_4DGL *uLCD,int,int,int,int);
+
+    void DrawScene ();
+    void CreateNewPiece (int,int);
+    
+    void ErasePiece(int x,int y,int piece, int rotation);
+    void DrawBoard ();
+    void AddPoints(int);
+    void AddClearedLines(int);
+    int GetPoints();
+    int GetClearedLines();
+    
+    int mPosX, mPosY;               // Position of the piece that is falling down
+    int mPiece, mRotation;          // Kind and rotation the piece that is falling down
+    
+    int points;
+    int clearedLineCount;
+    
+
+private:
+
+    int mScreenHeight;              // Screen height in pixels
+    int mNextPosX, mNextPosY;       // Position of the next piece
+    int mNextPiece, mNextRotation;  // Kind and rotation of the next piece
+    
+    Board *mBoard;
+    Pieces *mPieces;
+    uLCD_4DGL *uLCD;
+
+    
+    void InitGame(int,int,int,int);
+    void DrawPiece (int pX, int pY, int pPiece, int pRotation, int colorIndex);
+    
+};
+
+#endif // _GAME_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Pieces.cpp	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,328 @@
+#include Pieces.h
+
+// Define the Pieces
+char mPieces [7 /*kind */ ][4 /* rotation */ ][5 /* horizontal blocks */ ][5 /* vertical blocks */ ] =
+{
+// Square
+  {
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 2, 1, 0},
+    {0, 0, 1, 1, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 2, 1, 0},
+    {0, 0, 1, 1, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 2, 1, 0},
+    {0, 0, 1, 1, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 2, 1, 0},
+    {0, 0, 1, 1, 0},
+    {0, 0, 0, 0, 0}
+    }
+   },
+
+// I
+  {
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 1, 2, 1, 1},
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 0, 0}, 
+    {0, 0, 2, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 1, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {1, 1, 2, 1, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 1, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 2, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 0, 0, 0}
+    }
+   }
+  ,
+// L
+  {
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 2, 0, 0},
+    {0, 0, 1, 1, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 1, 2, 1, 0},
+    {0, 1, 0, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 1, 1, 0, 0},
+    {0, 0, 2, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 1, 0},
+    {0, 1, 2, 1, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0}
+    }
+   },
+// L mirrored
+  {
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 2, 0, 0},
+    {0, 1, 1, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 1, 0, 0, 0},
+    {0, 1, 2, 1, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 1, 0},
+    {0, 0, 2, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 1, 2, 1, 0},
+    {0, 0, 0, 1, 0},
+    {0, 0, 0, 0, 0}
+    }
+   },
+// N
+  {
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 1, 0},
+    {0, 0, 2, 1, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 1, 2, 0, 0},
+    {0, 0, 1, 1, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 1, 2, 0, 0},
+    {0, 1, 0, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 1, 1, 0, 0},
+    {0, 0, 2, 1, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0}
+    }
+   },
+// N mirrored
+  {
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 2, 1, 0},
+    {0, 0, 0, 1, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 2, 1, 0},
+    {0, 1, 1, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 1, 0, 0, 0},
+    {0, 1, 2, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 1, 0},
+    {0, 1, 2, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0}
+    }
+   },
+// T
+  {
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 2, 1, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0},
+    {0, 1, 2, 1, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 1, 2, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 0, 0, 0}
+    },
+   {
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 1, 2, 1, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 0}
+    }
+   }
+};
+
+// Displacement of the piece to the position where it is first drawn in the board when it is created
+int mPiecesInitialPosition  [7 /*kind */ ][4 /* rotation */ ][2 /* position */] =
+{
+/* Square */
+  {
+    {-2, -3}, 
+    {-2, -3},
+    {-2, -3},
+    {-2, -3}
+   },
+/* I */
+  {
+    {-2, -2},
+    {-2, -3},
+    {-2, -2},
+    {-2, -3}
+   },
+/* L */
+  {
+    {-2, -3},
+    {-2, -3},
+    {-2, -3},
+    {-2, -2}
+   },
+/* L mirrored */
+  {
+    {-2, -3},
+    {-2, -2},
+    {-2, -3},
+    {-2, -3}
+   },
+/* N */
+  {
+    {-2, -3},
+    {-2, -3},
+    {-2, -3},
+    {-2, -2}
+   },
+/* N mirrored */
+  {
+    {-2, -3},
+    {-2, -3},
+    {-2, -3},
+    {-2, -2}
+   },
+/* T */
+  {
+    {-2, -3},
+    {-2, -3},
+    {-2, -3},
+    {-2, -2}
+   },
+};
+
+/* 
+======================================                                  
+Return the type of a block (0 = no-block, 1 = normal block, 2 = pivot block)
+
+Parameters:
+
+int pPiece:      Piece to draw
+int pRotation:   1 of the 4 possible rotations
+int pX:          Horizontal position in blocks
+int pY:          Vertical position in blocks
+====================================== 
+*/
+int Pieces::GetBlockType (int pPiece, int pRotation, int pX, int pY)
+{
+    return mPieces [pPiece][pRotation][pX][pY];
+}
+
+/* 
+======================================                                  
+Returns the horizontal displacement of the piece that has to be applied in order to create it in the
+correct position.
+
+Parameters:
+
+int pPiece:  Piece to draw
+int pRotation:   1 of the 4 possible rotations
+====================================== 
+*/
+int Pieces::GetXInitialPosition (int pPiece, int pRotation)
+{
+    return mPiecesInitialPosition [pPiece][pRotation][0];
+}
+
+/* 
+======================================                                  
+Returns the vertical displacement of the piece that has to be applied in order to create it in the
+correct position.
+
+Parameters:
+
+int pPiece:  Piece to draw
+int pRotation:   1 of the 4 possible rotations
+====================================== 
+*/
+int Pieces::GetYInitialPosition (int pPiece, int pRotation)
+{
+    return mPiecesInitialPosition [pPiece][pRotation][1];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Pieces.h	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,15 @@
+#ifndef _PIECES_
+#define _PIECES_
+
+// Pieces Header to Support Game Pieces
+
+class Pieces
+{
+    public:
+    
+    int GetBlockType(int pPiece, int pRotation, int pX, int pY);
+    int GetXInitialPosition(int pPiece, int pRotation);
+    int GetYInitialPosition(int pPiece, int pRotation);
+};
+
+#endif  // _PIECES_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/SDFileSystem/#c8f66dc765d4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,492 @@
+#include "mbed.h"
+#include "Game.h"
+//#include "PinDetect.h"
+//#include "Speaker.h"
+//#include "TextLCD.h"
+//#include "Shiftbrite.h"
+//#include "SDFileSystem.h"
+#include "wave_player.h"
+#include "rtos.h"
+
+uLCD_4DGL uLCD(p28, p27, p29);
+//TextLCD textLCD(p26, p25, p24, p23, p22, p15); 
+//Speaker mySpeaker(p21);
+//Shiftbrite myShiftbrite(p9, p10, p11, p12, p13);
+//SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card
+Serial pc(USBTX, USBRX);
+
+PinDetect LEFT_KEY(p16);    // need to use NavSwitch for this
+PinDetect RIGHT_KEY(p19);
+PinDetect ROTATE_KEY(p17);
+PinDetect DOWN_KEY(p30);
+
+int SinglePiecePoints = 50;
+int LineClearPoints = 200;
+int key_input = 0;
+bool gameStarted = false;
+void input_left()   // FIX
+{
+    if(!gameStarted)
+    {   gameStarted=true;
+        return;
+    }
+    key_input = 1;
+    //mySpeaker.PlayNote(400.0,0.05,0.025);
+    //mySpeaker.PlayNote(500.0,0.05,0.025);
+}
+
+void input_right()
+{
+    if(!gameStarted)
+    {   gameStarted=true;
+        return;
+    }
+    key_input = 2;
+    //mySpeaker.PlayNote(400.0,0.05,0.025);
+    //mySpeaker.PlayNote(500.0,0.05,0.025);
+}
+
+void input_rotate()
+{
+    if(!gameStarted)
+    {   gameStarted=true;
+        return;
+    }
+    key_input = 3;
+    /*mySpeaker.PlayNote(600.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);*/
+}
+
+void input_down()
+{
+    if(!gameStarted)
+    {   gameStarted=true;
+        return;
+    }
+    key_input=4;
+    /*mySpeaker.PlayNote(500.0,0.05,0.025);
+    mySpeaker.PlayNote(1500.0,0.05,0.025);
+    mySpeaker.PlayNote(500.0,0.05,0.025);
+    mySpeaker.PlayNote(1500.0,0.05,0.025);*/
+}
+
+void clear_board()
+{
+    uLCD.filled_rectangle(20,0,79,128,0);
+}
+
+void clear_next_piece()
+{
+    uLCD.filled_rectangle(92,20,122,50,0);
+}
+
+/*
+void UpdateGameStatus(int points,int lines)
+{
+    textLCD.locate(7,0);
+    textLCD.printf("%d",points);
+    textLCD.locate(13,1);
+    textLCD.printf("%d",lines);
+}*/
+
+/* ShiftBright Code
+void FlashLight(void const *args)
+{
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+        
+    myShiftbrite.RGB(0,0,42);
+    myShiftbrite.RGB(0,0,42);
+    Thread::wait(100);
+        
+        
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,42,0);
+    Thread::wait(100);
+        
+    myShiftbrite.RGB(0,0,42);
+    myShiftbrite.RGB(0,0,42);
+    Thread::wait(100);
+        
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);    
+}
+
+void GameOverLight(void const *args)
+{
+    
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+        
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0); 
+}
+
+void GameStartLight(void const *args)
+{
+    
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+        
+    myShiftbrite.RGB(0,200,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,200,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0); 
+    myShiftbrite.RGB(0,0,0); 
+    Thread::wait(100);
+    myShiftbrite.RGB(0,200,0);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0); 
+    myShiftbrite.RGB(0,0,0); 
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,200,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);  
+    myShiftbrite.RGB(0,0,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,200,0);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+    
+} */
+
+/* Speaker Code
+void PlayStartSound()
+{
+    mySpeaker.PlayNote(500.0,0.05,0.025);
+    mySpeaker.PlayNote(600.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(600.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(1300.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(1300.0,0.05,0.025);
+    mySpeaker.PlayNote(1400.0,0.05,0.025);
+}
+
+void PlayOverSound()
+{
+    mySpeaker.PlayNote(1400.0,0.05,0.025);
+    mySpeaker.PlayNote(1300.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(1300.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(600.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(600.0,0.05,0.025);
+    mySpeaker.PlayNote(500.0,0.05,0.025);
+}
+
+void PlayClearSound()
+{
+    mySpeaker.PlayNote(900.0,0.2,0.025);
+    mySpeaker.PlayNote(1000.0,0.2,0.025);
+    mySpeaker.PlayNote(1100.0,0.2,0.025);
+    mySpeaker.PlayNote(1000.0,0.2,0.025);
+    mySpeaker.PlayNote(9000.0,0.2,0.025);
+} */
+
+int RandomGen(char range)
+{
+    pc.printf("%c",range);
+    while(!pc.readable()) wait(0.5);
+    char buffer[4];
+    pc.gets(buffer,4);
+    int i = buffer[0]-'0';
+    return i;
+}
+
+int main()
+{
+    //hardware setup    // FIX
+    LEFT_KEY.mode(PullUp);
+    RIGHT_KEY.mode(PullUp);
+    ROTATE_KEY.mode(PullUp);
+    DOWN_KEY.mode(PullUp);
+    
+    LEFT_KEY.attach_deasserted(&input_left);
+    RIGHT_KEY.attach_deasserted(&input_right);
+    ROTATE_KEY.attach_deasserted(&input_rotate);
+    DOWN_KEY.attach_deasserted(&input_down);
+    
+    LEFT_KEY.setSampleFrequency();
+    RIGHT_KEY.setSampleFrequency();
+    ROTATE_KEY.setSampleFrequency();
+    DOWN_KEY.setSampleFrequency();  // FIX
+    uLCD.baudrate(3000000);
+    
+    //myShiftbrite.RGB(0,0,0);
+    //myShiftbrite.RGB(0,0,0);
+    
+    /* SD card used for Startup Image
+    sd.disk_initialize();   // ? might need to delete
+    uLCD.media_init();
+    uLCD.set_sector_address(0x001D, 0x7801);
+    uLCD.display_image(0,0);*/
+    
+    /*textLCD.cls();
+    textLCD.locate(0,0);
+    textLCD.printf("Waiting for PC...");*/
+    
+    pc.baud(9600);
+    pc.format(8,SerialBase::None,1);
+    pc.printf("0");
+    while(!pc.readable()) wait(0.5);
+    char buffer[4];
+    pc.gets(buffer,4);
+    /*
+    //wait for game start
+    textLCD.cls();
+    textLCD.locate(0,0);
+    textLCD.printf("TETRIS READY!!");
+    textLCD.locate(0,1);
+    textLCD.printf("PRESS ANY KEY...");
+    while(!gameStarted) wait(0.5);
+    PlayStartSound();
+    textLCD.cls();
+    textLCD.printf("Starting game   now...");
+    wait(2);
+    textLCD.cls();
+    textLCD.locate(0,0);
+    textLCD.printf("Points");
+    textLCD.locate(0,1);
+    textLCD.printf("Cleared Line");*/
+    
+    //Thread t1(GameStartLight);
+    //game classes init
+    bool isGameOver = false;
+    int mScreenHeight = 128;
+    Pieces mPieces;
+    Board mBoard (&mPieces, mScreenHeight);
+    int a = RandomGen('a');
+    int b = RandomGen('b');
+    int c = RandomGen('a');
+    int d = RandomGen('b');
+    Game mGame (&mBoard, &mPieces, mScreenHeight, &uLCD,a,b,c,d);
+
+
+    // ----- Main Loop -----
+    int prevX=0;
+    int prevY=0;
+    int prevPiece=-1;
+    int prevRot=0;
+    Timer timer;
+    timer.start();
+    key_input=0;
+    bool needErase = false;
+    uLCD.cls();
+    while (1)
+    {
+        if(isGameOver) 
+        {
+            wait(1);
+            continue;
+        }
+        // ----- Draw ----
+        if(needErase)
+        {
+            mGame.ErasePiece(prevX,prevY,prevPiece,prevRot);
+            needErase=false;
+        }
+        mGame.DrawScene();
+        
+        prevX=mGame.mPosX;
+        prevY=mGame.mPosY;
+        prevPiece=mGame.mPiece;
+        prevRot=mGame.mRotation;
+
+        // ----- Input -----
+        switch (key_input)
+        {
+            case (2): //right
+            {
+                if (mBoard.IsPossibleMovement (mGame.mPosX + 1, mGame.mPosY, mGame.mPiece, mGame.mRotation))
+                    {mGame.mPosX++;needErase=true;}
+                break;
+            }
+
+            case (1): //left
+            {
+                if (mBoard.IsPossibleMovement (mGame.mPosX - 1, mGame.mPosY, mGame.mPiece, mGame.mRotation))
+                    {mGame.mPosX--;needErase=true;}  
+                break;
+            }
+
+            case (4)://down
+            {
+                // Check collision from up to down
+                while (mBoard.IsPossibleMovement(mGame.mPosX, mGame.mPosY, mGame.mPiece, mGame.mRotation)) { mGame.mPosY++; }
+                needErase=true;
+                mBoard.StorePiece (mGame.mPosX, mGame.mPosY - 1, mGame.mPiece, mGame.mRotation);
+                mGame.AddPoints(SinglePiecePoints);
+                int linesDeleted = mBoard.DeletePossibleLines ();
+                if(linesDeleted>0)
+                {
+                    mGame.AddClearedLines(linesDeleted);
+                    mGame.AddPoints(LineClearPoints*linesDeleted);
+                    //Thread t1(FlashLight);
+                    //PlayClearSound();
+                    clear_board();
+                }
+                UpdateGameStatus(mGame.GetPoints(),mGame.GetClearedLines());
+
+                if (mBoard.IsGameOver())
+                {
+                    isGameOver=true;
+                    uLCD.cls();
+                    
+                    // FIX add Game Over mechanic
+                    
+                    //uLCD.media_init();
+                    //uLCD.set_sector_address(0x001D, 0x7842);
+                    //uLCD.display_image(0,0);
+                    //Thread t2(GameOverLight);
+                    //PlayOverSound();
+                    
+                }
+                
+                if(!isGameOver)
+                {
+                mGame.CreateNewPiece(RandomGen('a'),RandomGen('b'));
+                clear_next_piece();
+                }
+                break;
+            }
+
+            case (3)://rotate
+            {
+                if (mBoard.IsPossibleMovement (mGame.mPosX, mGame.mPosY, mGame.mPiece, (mGame.mRotation + 1) % 4))
+                    {mGame.mRotation = (mGame.mRotation + 1) % 4;needErase=true;}
+                break;
+            }
+            
+            case (0):{break;}
+        }
+        key_input = 0;
+        
+        // ----- Vertical movement -----
+
+        if(timer.read_ms()>WAIT_TIME)
+        {
+            needErase=true;
+            if(!isGameOver)
+            {
+                if (mBoard.IsPossibleMovement (mGame.mPosX, mGame.mPosY + 1, mGame.mPiece, mGame.mRotation))
+                {
+                    mGame.mPosY++;
+                }
+                else
+                {
+                    mBoard.StorePiece (mGame.mPosX, mGame.mPosY, mGame.mPiece, mGame.mRotation);
+                    mGame.AddPoints(SinglePiecePoints);
+                    int linesDeleted = mBoard.DeletePossibleLines ();
+                    if(linesDeleted>0)
+                    {
+                        mGame.AddClearedLines(linesDeleted);
+                        mGame.AddPoints(LineClearPoints*linesDeleted);
+                        //Thread t1(FlashLight);
+                        //PlayClearSound();
+                        clear_board();
+                    }
+                    UpdateGameStatus(mGame.GetPoints(),mGame.GetClearedLines());
+                        
+                    if (mBoard.IsGameOver())
+                    {
+                        isGameOver=true;
+                        uLCD.cls();
+                        
+                        // FIX add Game Over mechanic
+                        
+                        //uLCD.media_init();
+                        //uLCD.set_sector_address(0x001D, 0x7842);
+                        //uLCD.display_image(0,0);
+                        //Thread t2(GameOverLight);
+                        //PlayOverSound();
+                    }
+                    
+                    if(!isGameOver)
+                    {
+                    mGame.CreateNewPiece(RandomGen('a'),RandomGen('b'));
+                    clear_next_piece();
+                    }
+                }
+            }
+            timer.reset();
+        }
+            wait(0.1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/mbed_official/code/mbed-rtos/#631c0f1008c3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wave_player.lib	Wed Nov 30 21:57:25 2022 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/sravet/code/wave_player/#acc3e18e77ad