#include <Adafruit_ILI9341.h>
#define TFT_CS 53
#define TFT_DC 49
// Additional pins
#define TFT_RST 48
#define TFT_MISO 50
#define TFT_MOSI 51
#define TFT_SCK 52
// Rest of the code...
unsigned long startTime;
unsigned long elapsedTime;
unsigned long gameTimeLimit = 120000; // 2 minutes in milliseconds
unsigned long previousTime = 0;
unsigned long refreshInterval = 1000; // Refresh interval in milliseconds
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
const int upButtonPin = 2;
const int downButtonPin = 3;
const int leftButtonPin = 5;
const int rightButtonPin = 4;
const int startButtonPin = 6;
enum Direction {
UP,
DOWN,
LEFT,
RIGHT
};
const int BOARD_SIZE = 4;
const int TILE_SIZE = 50;
const int TILE_MARGIN = 10;
const int SCREEN_WIDTH = 280;
const int SCREEN_HEIGHT = 280;
int board[BOARD_SIZE][BOARD_SIZE] = {0};
int score = 0;
bool gameover = false;
// Define custom colors using RGB values
#define COLOR_BLUE 0x001F // Blue
#define COLOR_RED 0xF800 // Red
#define COLOR_GREEN 0x07E0 // Green
#define COLOR_YELLOW 0xFFE0 // Yellow
#define COLOR_CYAN 0x07FF // Cyan
#define COLOR_MAGENTA 0xF81F // Magenta
#define COLOR_ORANGE 0xFD20 // Orange
#define COLOR_PURPLE 0x780F // Purple
#define COLOR_PINK 0xFC18 // Pink
#define COLOR_BROWN 0x9A60 // Brown
#define COLOR_LIGHTGREY 0xC618 // Light Grey
void setup() {
startTime = millis(); // Set the start time
pinMode(upButtonPin, INPUT_PULLUP);
pinMode(downButtonPin, INPUT_PULLUP);
pinMode(leftButtonPin, INPUT_PULLUP);
pinMode(rightButtonPin, INPUT_PULLUP);
pinMode(startButtonPin, INPUT_PULLUP);
tft.begin();
tft.setRotation(4);
tft.fillScreen(ILI9341_BLACK);
attachInterrupt(digitalPinToInterrupt(upButtonPin), moveUp, FALLING);
attachInterrupt(digitalPinToInterrupt(downButtonPin), moveDown, FALLING);
attachInterrupt(digitalPinToInterrupt(leftButtonPin), moveLeft, FALLING);
attachInterrupt(digitalPinToInterrupt(rightButtonPin), moveRight, FALLING);
attachInterrupt(digitalPinToInterrupt(startButtonPin), startGame, FALLING);
startGame();
}
void checkButtons() {
if (digitalRead(upButtonPin) == LOW) {
// Handle up button press
// Perform corresponding action in the game (e.g., move tiles up)
moveTiles(UP);
addRandomTile();
drawBoard();
delay(100); // Delay to debounce the button
}
if (digitalRead(downButtonPin) == LOW) {
// Handle down button press
// Perform corresponding action in the game (e.g., move tiles down)
moveTiles(DOWN);
addRandomTile();
drawBoard();
delay(100); // Delay to debounce the button
}
if (digitalRead(leftButtonPin) == LOW) {
// Handle left button press
// Perform corresponding action in the game (e.g., move tiles left)
moveTiles(LEFT);
addRandomTile();
drawBoard();
delay(100); // Delay to debounce the button
}
if (digitalRead(rightButtonPin) == LOW) {
// Handle right button press
// Perform corresponding action in the game (e.g., move tiles right)
moveTiles(RIGHT);
addRandomTile();
drawBoard();
delay(100); // Delay to debounce the button
}
if (digitalRead(startButtonPin) == LOW) {
// Handle start button press
// Perform corresponding action in the game (e.g., restart the game)
startGame();
delay(100); // Delay to debounce the button
}
}
void loop() {
// ...
unsigned long currentTime = millis();
if (currentTime - previousTime >= refreshInterval) {
previousTime = currentTime;
drawScore(); // Refresh the time display
}
elapsedTime = millis() - startTime; // Calculate elapsed time
if (elapsedTime >= gameTimeLimit) {
gameover = true;
drawGameOver();
}
if (digitalRead(startButtonPin) == LOW) {
if (!gameover) {
gameover = true;
drawGameOver();
} else {
startGame(); // Restart the game
}
}
}
void drawTile(int row, int col, int value) {
int x = (BOARD_SIZE - col - 1) * (TILE_SIZE + TILE_MARGIN) + TILE_MARGIN;
int y = row * (TILE_SIZE + TILE_MARGIN) + TILE_MARGIN;
tft.fillRect(x, y, TILE_SIZE, TILE_SIZE, getColor(value));
tft.setTextColor(ILI9341_BLACK);
tft.setTextSize(2);
tft.setCursor(x + (TILE_SIZE / 2) - 12, y + (TILE_SIZE / 2) - 12);
tft.print(value);
}
uint16_t getColor(int value) {
switch (value) {
case 2: return COLOR_BLUE;
case 4: return COLOR_RED;
case 8: return COLOR_GREEN;
case 16: return COLOR_YELLOW;
case 32: return COLOR_CYAN;
case 64: return COLOR_MAGENTA;
case 128: return COLOR_ORANGE;
case 256: return COLOR_PURPLE;
case 512: return COLOR_PINK;
case 1024: return COLOR_BROWN;
case 2048: return COLOR_LIGHTGREY;
default: return ILI9341_WHITE;
}
}
void resetGame() {
// Reset game variables and board
// ...
startTime = millis(); // Reset the start time
}
void drawBoard() {
tft.fillScreen(ILI9341_BLACK);
for (int row = 0; row < BOARD_SIZE; row++) {
for (int col = 0; col < BOARD_SIZE; col++) {
int value = board[row][col];
drawTile(row, col, value);
}
}
drawScore();
}
void drawScore() {
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.setCursor(20, SCREEN_HEIGHT - 35);
tft.print("Score: ");
tft.print(score);
int minutes = (elapsedTime / 1000) / 60; // Calculate minutes
int seconds = (elapsedTime / 1000) % 60; // Calculate seconds
// Clear the area where the time is displayed
tft.fillRect(SCREEN_WIDTH / 2 + 200, 275, 60, 10, ILI9341_BLACK);
tft.setCursor(SCREEN_WIDTH / 2 + 200, 275);
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK); // Set text color and background color
tft.print("Time: " + String(minutes) + "m " + String(seconds) + "s");
}
void startGame() {
score = 0;
gameover = false;
for (int row = 0; row < BOARD_SIZE; row++) {
for (int col = 0; col < BOARD_SIZE; col++) {
board[row][col] = 0;
}
}
addRandomTile();
addRandomTile();
drawBoard();
resetGame(); // Reset the game state
}
int getMaxTileValue() {
int maxTileValue = 0;
for (int row = 0; row < BOARD_SIZE; row++) {
for (int col = 0; col < BOARD_SIZE; col++) {
maxTileValue = max(maxTileValue, board[row][col]);
}
}
return maxTileValue;
}
void moveUp() {
if (!gameover) {
moveTiles(UP);
}
}
void moveDown() {
if (!gameover) {
moveTiles(DOWN);
}
}
void moveLeft() {
if (!gameover) {
moveTiles(LEFT);
}
}
void moveRight() {
if (!gameover) {
moveTiles(RIGHT);
}
}
void addRandomTile() {
int count = 0;
for (int row = 0; row < BOARD_SIZE; row++) {
for (int col = 0; col < BOARD_SIZE; col++) {
if (board[row][col] == 0) {
count++;
}
}
}
if (count > 0) {
int index = random(count);
count = 0;
for (int row = 0; row < BOARD_SIZE; row++) {
for (int col = 0; col < BOARD_SIZE; col++) {
if (board[row][col] == 0) {
if (count == index) {
int value = random(100) < (90 + getLevel() * 2) ? 2 : 4; // Adjust probability based on current level
int level = max(getMaxTileValue() / 128, 1); // Adjust level based on current maximum tile value (divided by 128)
value *= level; // Multiply tile value by level
board[row][col] = value;
return;
}
count++;
}
}
}
}
}
int getLevel() {
int maxTileValue = getMaxTileValue();
if (maxTileValue >= 2048) {
return 5; // Adjust level according to your preference
} else if (maxTileValue >= 512) {
return 4;
} else if (maxTileValue >= 128) {
return 3;
} else if (maxTileValue >= 64) {
return 2;
} else {
return 1;
}
}
void moveTiles(Direction direction) {
int dr = 0, dc = 0;
if (direction == UP) dr = -1;
else if (direction == DOWN) dr = 1;
else if (direction == LEFT) dc = -1;
else if (direction == RIGHT) dc = 1;
bool moved = false;
if (dr != 0) {
for (int col = 0; col < BOARD_SIZE; col++) {
for (int row = (dr > 0 ? BOARD_SIZE - 1 : 0); (dr > 0 ? row >= 0 : row < BOARD_SIZE); row -= dr) {
if (board[row][col] != 0) {
int newRow = row;
while (newRow + dr >= 0 && newRow + dr < BOARD_SIZE && board[newRow + dr][col] == 0) {
newRow += dr;
}
if (newRow != row) {
board[newRow][col] = board[row][col];
board[row][col] = 0;
moved = true;
}
}
}
}
} else if (dc != 0) {
for (int row = 0; row < BOARD_SIZE; row++) {
for (int col = (dc > 0 ? BOARD_SIZE - 1 : 0); (dc > 0 ? col >= 0 : col < BOARD_SIZE); col -= dc) {
if (board[row][col] != 0) {
int newCol = col;
while (newCol + dc >= 0 && newCol + dc < BOARD_SIZE && board[row][newCol + dc] == 0) {
newCol += dc;
}
if (newCol != col) {
board[row][newCol] = board[row][col];
board[row][col] = 0;
moved = true;
}
}
}
}
}
if (moved) {
mergeTiles(direction);
addRandomTile();
drawBoard();
if (!canMove()) {
gameover = true;
drawGameOver();
}
}
}
void mergeTiles(Direction direction) {
int dr = 0, dc = 0;
if (direction == UP) dr = -1;
else if (direction == DOWN) dr = 1;
else if (direction == LEFT) dc = -1;
else if (direction == RIGHT) dc = 1;
if (dr != 0) {
for (int col = 0; col < BOARD_SIZE; col++) {
for (int row = (dr > 0 ? BOARD_SIZE - 1 : 0); (dr > 0 ? row >= 0 : row < BOARD_SIZE); row -= dr) {
if (board[row][col] != 0 && row + dr >= 0 && row + dr < BOARD_SIZE && board[row][col] == board[row + dr][col]) {
board[row][col] *= 2;
score += board[row][col];
board[row + dr][col] = 0;
}
}
}
} else if (dc != 0) {
for (int row = 0; row < BOARD_SIZE; row++) {
for (int col = (dc > 0 ? BOARD_SIZE - 1 : 0); (dc > 0 ? col >= 0 : col < BOARD_SIZE); col -= dc) {
if (board[row][col] != 0 && col + dc >= 0 && col + dc < BOARD_SIZE && board[row][col] == board[row][col + dc]) {
board[row][col] *= 2;
score += board[row][col];
board[row][col + dc] = 0;
}
}
}
}
}
bool canMove() {
for (int row = 0; row < BOARD_SIZE; row++) {
for (int col = 0; col < BOARD_SIZE; col++) {
if (board[row][col] == 0) {
return true;
}
if (row - 1 >= 0 && board[row][col] == board[row - 1][col]) {
return true;
}
if (row + 1 < BOARD_SIZE && board[row][col] == board[row + 1][col]) {
return true;
}
if (col - 1 >= 0 && board[row][col] == board[row][col - 1]) {
return true;
}
if (col + 1 < BOARD_SIZE && board[row][col] == board[row][col + 1]) {
return true;
}
}
}
return false;
}
void drawGameOver() {
tft.setTextColor(ILI9341_WHITE, ILI9341_RED);
tft.setTextSize(4);
tft.setCursor(SCREEN_WIDTH / 2 -120, SCREEN_HEIGHT / 2 - 25);
tft.print("Game Over");
}