#include <TFT_eSPI.h>
#include "dino.h"
// --- Configurações do Display ---
TFT_eSPI tft = TFT_eSPI();
// --- Definições do Jogo ---
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define GROUND_Y SCREEN_HEIGHT - 40
#define JUMP_HEIGHT 80
#define DINO_X_POS 20
#define DINO_WIDTH 40
#define DINO_HEIGHT 44
#define CACTUS_WIDTH 24
#define CACTUS_HEIGHT 48
#define JUMP_BTN 0 // Pino para o botão de pulo (use o pino BOOT do ESP32)
// --- Variáveis do Jogo ---
int dino_y = GROUND_Y - DINO_HEIGHT;
int dino_y_velocity = 0;
bool is_jumping = false;
unsigned long score = 0;
int game_speed = 6;
bool game_over = false;
struct Obstacle {
int x;
bool active;
};
Obstacle cactus;
void setup() {
Serial.begin(115200);
pinMode(JUMP_BTN, INPUT_PULLUP);
tft.init();
tft.setRotation(1); // Ajuste a rotação conforme necessário
tft.fillScreen(TFT_WHITE);
startGame();
}
void loop() {
if (!game_over) {
handleInput();
updateGame();
draw();
delay(30); // Controla a velocidade geral do jogo
} else {
// Se o jogo acabou, espera o botão ser pressionado para reiniciar
if (digitalRead(JUMP_BTN) == LOW) {
startGame();
}
}
}
void startGame() {
tft.fillScreen(TFT_WHITE);
drawGround();
dino_y = GROUND_Y - DINO_HEIGHT;
dino_y_velocity = 0;
is_jumping = false;
score = 0;
game_speed = 6;
game_over = false;
cactus.x = SCREEN_WIDTH;
cactus.active = true;
tft.setTextColor(TFT_BLACK);
tft.setTextSize(2);
}
void handleInput() {
// Pula se o botão for pressionado e o dinossauro não estiver pulando
if (digitalRead(JUMP_BTN) == LOW && !is_jumping) {
is_jumping = true;
dino_y_velocity = -18; // Força inicial do pulo
}
}
void updateGame() {
// Atualiza a posição do dinossauro (pulo)
if (is_jumping) {
dino_y += dino_y_velocity;
dino_y_velocity += 1; // Gravidade
if (dino_y >= GROUND_Y - DINO_HEIGHT) {
dino_y = GROUND_Y - DINO_HEIGHT;
is_jumping = false;
dino_y_velocity = 0;
}
}
// Move o cacto
if (cactus.active) {
cactus.x -= game_speed;
if (cactus.x < -CACTUS_WIDTH) {
cactus.x = SCREEN_WIDTH + random(0, 100);
}
}
// Aumenta a velocidade com o tempo
if(score > 0 && score % 100 == 0) {
game_speed++;
}
// Detecção de colisão
if (cactus.active &&
DINO_X_POS + DINO_WIDTH > cactus.x &&
DINO_X_POS < cactus.x + CACTUS_WIDTH &&
dino_y + DINO_HEIGHT > GROUND_Y - CACTUS_HEIGHT) {
gameOver();
}
score++;
}
void draw() {
// Limpa a área do jogo
tft.fillRect(0, 0, SCREEN_WIDTH, GROUND_Y - 1, TFT_WHITE);
// Desenha o dinossauro
static bool dino_frame = true;
if(is_jumping){
tft.drawXBitmap(DINO_X_POS, dino_y, dino_run1_bits, DINO_WIDTH, DINO_HEIGHT, TFT_BLACK);
} else {
if (dino_frame) {
tft.drawXBitmap(DINO_X_POS, dino_y, dino_run1_bits, DINO_WIDTH, DINO_HEIGHT, TFT_BLACK);
} else {
tft.drawXBitmap(DINO_X_POS, dino_y, dino_run2_bits, DINO_WIDTH, DINO_HEIGHT, TFT_BLACK);
}
}
dino_frame = !dino_frame; // Alterna o frame da animação de corrida
// Desenha o cacto
if (cactus.active) {
tft.drawXBitmap(cactus.x, GROUND_Y - CACTUS_HEIGHT, cactus_bits, CACTUS_WIDTH, CACTUS_HEIGHT, TFT_BLACK);
}
// Desenha o chão
drawGround();
// Desenha a pontuação
tft.setCursor(10, 10);
tft.print("Score: ");
tft.print(score);
}
void drawGround() {
tft.drawFastHLine(0, GROUND_Y, SCREEN_WIDTH, TFT_BLACK);
}
void gameOver() {
game_over = true;
tft.setCursor(SCREEN_WIDTH / 2 - 80, SCREEN_HEIGHT / 2 - 20);
tft.setTextColor(TFT_BLACK);
tft.setTextSize(3);
tft.print("GAME OVER");
tft.setCursor(SCREEN_WIDTH / 2 - 120, SCREEN_HEIGHT / 2 + 20);
tft.setTextSize(2);
tft.print("Pressione para reiniciar");
}