Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player
Revision 0:1858f2b100fd, committed 2022-11-30
- Comitter:
- jsanchez307
- Date:
- Wed Nov 30 21:57:25 2022 +0000
- Commit message:
- Tetris Skeleton V 1.0
Changed in this revision
--- /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