Touchscreen Tetris Game Using TFT LCD & Arduino

by priyanshu9569999 in Circuits > Arduino

38 Views, 3 Favorites, 0 Comments

Touchscreen Tetris Game Using TFT LCD & Arduino

Touchscreen-Tetris-Game-Using-TFT-LCD-_-Arduino_jpg_1c9ef305-5ad2-4f93-87fa-b530a72a3483.jpg
Arduino Touchscreen Tetris Game! 🔥

Build your own touchscreen Arduino Tetris game. This project brings the classic puzzle game to your fingertips using an Arduino Uno. The TFT shield works as both the vibrant color display and the touch controller, allowing you to move and rotate blocks with simple taps. The system supports full Tetromino arrays, smooth block rendering, collision detection, and score tracking. The project demonstrates practical implementation of game loops, touchscreen interfacing, and 2D array matrix manipulation using embedded hardware.

Supplies

Overview

Build your own touchscreen Arduino Tetris game. This project brings the classic puzzle game to your fingertips using an Arduino Uno. The TFT shield works as both the vibrant color display and the touch controller, allowing you to move and rotate blocks with simple taps. The system supports full Tetromino arrays, smooth block rendering, collision detection, and score tracking. The project demonstrates practical implementation of game loops, touchscreen interfacing, and 2D array matrix manipulation using embedded hardware.

Game Board and Variables

#include <MCUFRIEND_kbv.h>
#include <TouchScreen.h>

MCUFRIEND_kbv tft;

const int XP = 6;
const int XM = A2;
const int YP = A1;
const int YM = 7;

const int TS_LEFT = 907;
const int TS_RT = 136;
const int TS_TOP = 942;
const int TS_BOT = 139;

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF


The code begins by including the required libraries for the TFT LCD display and resistive touchscreen. The MCUFRIEND_kbv library handles graphical rendering while the TouchScreen library reads touch input from the shield.

Touchscreen calibration values are defined to correctly map raw touch readings into screen coordinates. Color constants are also created for rendering the Tetromino blocks and user interface.

Game Board and Variables

The game board is represented using a 2D integer array where each cell stores either an empty state or the color index of a locked block. Variables are also used for tracking the current falling piece, previous drawing position, next piece preview, score, level, line count, and game speed.

The board dimensions are configured as a 14×20 Tetris grid while the block size determines the pixel dimensions of each rendered square.

#define COLS 14
#define ROWS 20
#define BLOCK 12

int board[ROWS][COLS];

int pieceX = 0;
int pieceY = 0;
int currentPiece = 0;
int rotation = 0;

int prevX = 0;
int prevY = 0;
int prevRot = 0;
int prevPiece = 0;

int nextPiece = 0;

unsigned long lastDrop = 0;
int dropDelay = 500;

bool gameOver = false;
long score = 0;
int level = 1;
int totalLines = 0;

Tetromino Shape Arrays

The seven classic Tetris pieces are stored in a four-dimensional array. Every Tetromino contains four different rotation states represented using 4×4 matrix grids.

This structure allows the code to rotate blocks dynamically and render different shapes efficiently during gameplay.

const byte tetromino[7][4][4][4] = {

// Piece 0 : I Block
{
{ {0,0,0,0}, {1,1,1,1}, {0,0,0,0}, {0,0,0,0} },
{ {0,1,0,0}, {0,1,0,0}, {0,1,0,0}, {0,1,0,0} },
{ {0,0,0,0}, {1,1,1,1}, {0,0,0,0}, {0,0,0,0} },
{ {0,1,0,0}, {0,1,0,0}, {0,1,0,0}, {0,1,0,0} }
},

// Piece 1 : J Block
{
{ {1,0,0,0}, {1,1,1,0}, {0,0,0,0}, {0,0,0,0} },
{ {0,1,1,0}, {0,1,0,0}, {0,1,0,0}, {0,0,0,0} },
{ {0,0,0,0}, {1,1,1,0}, {0,0,1,0}, {0,0,0,0} },
{ {0,1,0,0}, {0,1,0,0}, {1,1,0,0}, {0,0,0,0} }
}
};

Rendering and Flicker-Free Drawing

The rendering system is optimized to reduce screen flickering by updating only the modified cells instead of redrawing the entire display every frame.

The drawCell() function renders individual Tetris squares while erasePiece() removes the previous block position. The drawGame() function restores hidden board cells and redraws the active piece at its updated position.

The redrawBoard() function performs a full board refresh only when necessary, such as after clearing lines or spawning a new piece.


void drawCell(int col, int row, uint16_t color) {
tft.fillRect(
GAME_X + col * BLOCK,
GAME_Y + row * BLOCK,
BLOCK - 1,
BLOCK - 1,
color
);
}

void erasePiece(int col, int row, int oldRotation, int oldPiece) {
for (int r = 0; r < 4; r++) {
for (int c = 0; c < 4; c++) {
if (tetromino[oldPiece][oldRotation][r][c]) {
drawCell(col + c, row + r, BLACK);
}
}
}
}

void drawPiece(int col, int row, int rot, int piece) {
for (int r = 0; r < 4; r++) {
for (int c = 0; c < 4; c++) {
if (tetromino[piece][rot][r][c]) {
drawCell(col + c, row + r, pieceColors[piece]);
}
}
}
}

User Interface System

The TFT display includes a complete user interface with score display, level indicator, next-piece preview window, game border, and touch control buttons.

The bottom panel contains four touch buttons for moving left, moving right, dropping downward, and rotating the Tetromino piece.


void drawStaticUI() {
tft.fillScreen(BLACK);
drawBoardBorder();
drawScorePanel();
drawButtons();
}

void drawBoardBorder() {
tft.drawRect(GAME_X - 1, GAME_Y, GAME_W + 2, GAME_H, WHITE);
tft.drawRect(GAME_X - 2, GAME_Y, GAME_W + 4, GAME_H, WHITE);
}

Touch Controls and Collision Detection

The touchscreen controls use circular hit detection to identify button presses. The code maps raw touchscreen coordinates into screen positions and checks whether the user touched one of the four virtual control buttons.

Collision detection prevents Tetromino blocks from moving outside the board boundaries or overlapping with already locked pieces.

bool checkCollision(int newX, int newY, int newRotation) {
for (int row = 0; row < 4; row++) {
for (int col = 0; col < 4; col++) {

if (tetromino[currentPiece][newRotation][row][col]) {

int boardX = newX + col;
int boardY = newY + row;

if (boardX < 0 || boardX >= COLS || boardY >= ROWS) {
return true;
}

if (boardY >= 0 && board[boardY][boardX]) {
return true;
}
}
}
}

return false;
}

Score System and Level Progression

The game rewards points based on the number of cleared lines. Completed rows are removed from the board and all rows above shift downward automatically.

The level increases every 10 cleared lines and the falling speed becomes progressively faster, increasing gameplay difficulty.

void addScore(int lines) {

const int pointsPerLine[5] = {
0, 100, 300, 500, 800
};

if (lines >= 1 && lines <= 4) {
score += (long)pointsPerLine[lines] * level;
}

totalLines += lines;
level = totalLines / 10 + 1;

dropDelay = max(80, 500 - (level - 1) * 45);
}

Main Game Loop


The main game loop continuously handles touch input, automatically drops the active Tetromino piece using a timer, checks collisions, merges locked blocks into the board, clears completed rows, updates the score panel, and spawns new pieces.

If a new Tetromino immediately collides after spawning, the game displays a GAME OVER screen along with the final score.

void loop() {

if (gameOver) {

tft.fillScreen(BLACK);

tft.drawRect(15, 100, 210, 120, WHITE);

tft.setTextColor(RED);
tft.setTextSize(3);

tft.setCursor(50, 115);
tft.print("GAME");

tft.setCursor(50, 150);
tft.print("OVER");

while (1);
}

handleTouch();

if (millis() - lastDrop > dropDelay) {

if (!checkCollision(pieceX, pieceY + 1, rotation)) {

pieceY++;
drawGame();

} else {

mergePiece();

int lines = clearLines();

if (lines > 0) {
addScore(lines);
}

newPiece();
redrawBoard();
}

lastDrop = millis();
}
}


Result

Screenshot 2026-06-08 at 5.22.35 PM.png

The Arduino Uno successfully runs a complete touchscreen-based Tetris game using the TFT LCD shield. The project features smooth block rendering, responsive touch controls, score tracking, level progression, next-piece preview, collision handling, and dynamic game speed adjustment.

The optimized rendering system minimizes display flickering while maintaining stable gameplay performance on the ATmega328P microcontroller.

Reference Video

Arduino Touchscreen Tetris Game! 🔥