Introducción
¡Revive la nostalgia de un clásico moderno con este emocionante proyecto! Te mostraremos cómo construir tu propia versión del adictivo juego Flappy Bird, pero esta vez, en un pequeño dispositivo electrónico basado en el potente microcontrolador ESP32. Con una pantalla a color, un botón para el control y un zumbador para los efectos de sonido, este proyecto es perfecto para aficionados a la electrónica que quieren llevar sus habilidades al siguiente nivel, combinando hardware y software para crear una experiencia de juego interactiva.
Materiales Necesarios
- Placa de desarrollo ESP32 (por ejemplo, ESP32-DevKitC)
- Pantalla LCD TFT de 1.8 pulgadas (ST7735 o similar con interfaz SPI)
- Protoboard
- Cables Dupont (macho-macho)
- Buzzer pasivo
- Botón pulsador
- Resistencia de 10k Ohm (para el botón)
- Cable USB para alimentación y programación del ESP32
Esquema del montaje
El montaje se realizará en una protoboard, conectando los componentes principales al ESP32. La pantalla TFT se comunicará con el ESP32 a través del protocolo SPI, lo que requiere varias conexiones de datos y control. El botón se conectará a un pin GPIO del ESP32 y a tierra, usando una resistencia pull-up para asegurar una lectura estable. El zumbador se conectará a otro pin GPIO para generar los sonidos del juego. Asegúrate de que todas las conexiones sean firmes y correctas para evitar problemas de funcionamiento.
Conexiones:
- Pantalla LCD TFT (ST7735 1.8"):
- VCC (Voltaje) -> 3.3V del ESP32
- GND (Tierra) -> GND del ESP32
- SCL (Clock SPI) -> GPIO18 del ESP32
- SDA (MOSI SPI) -> GPIO23 del ESP32
- RES (Reset) -> GPIO4 del ESP32
- DC (Data/Command) -> GPIO2 del ESP32
- CS (Chip Select) -> GPIO5 del ESP32
- BL (Backlight) -> 3.3V del ESP32 (o a un GPIO si deseas controlarlo)
- Botón Pulsador:
- Una pata del botón -> GPIO13 del ESP32
- Otra pata del botón -> GND del ESP32
- Resistencia de 10k Ohm -> entre GPIO13 y 3.3V (configuración pull-up interna o externa)
- Buzzer Pasivo:
- Pata positiva del Buzzer -> GPIO27 del ESP32
- Pata negativa del Buzzer -> GND del ESP32
Código Arduino
Para este proyecto, utilizaremos el entorno de desarrollo de Arduino IDE. Necesitarás instalar las bibliotecas Adafruit GFX Library y Adafruit ST7735 Library a través del Gestor de Bibliotecas de Arduino. Además, para la funcionalidad del zumbador en ESP32, es útil la librería ESP32-Tone. El código a continuación proporciona la estructura básica para implementar el juego Flappy Bird. Ten en cuenta que la lógica de juego completa (generación de tuberías, física de la gravedad, detección de colisiones) puede ser extensa y se implementará dentro de las funciones mencionadas.
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h> // SPI library
#include <Tone32.h> // Library for tone generation on ESP32
// Definiciones de pines para la pantalla ST7735
#define TFT_CS 5 // Chip select pin
#define TFT_DC 2 // Data/Command pin
#define TFT_RST 4 // Reset pin (or connect to ESP32 RST, see your display's docs)
// Definiciones de pines para el botón y el buzzer
#define BUTTON_PIN 13 // Pin para el botón de "flap"
#define BUZZER_PIN 27 // Pin para el buzzer
// Colores del juego
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define WHITE 0xFFFF
#define YELLOW 0xFFE0
#define ORANGE 0xFC00
// Objeto de la pantalla
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// Variables del juego
int birdY; // Posición vertical del pájaro
float birdVelocity; // Velocidad vertical del pájaro
int score; // Puntuación del jugador
bool gameOver; // Estado del juego
unsigned long lastFlapTime; // Último momento en que el pájaro aleteó
// Estructura para las tuberías (pipes)
struct Pipe {
int x; // Posición horizontal de la tubería
int gapY; // Posición vertical del centro del hueco
bool counted; // Si la tubería ya fue contada para la puntuación
};
#define MAX_PIPES 3 // Número máximo de tuberías en pantalla
Pipe pipes[MAX_PIPES];
// --- Funciones del juego ---
// Inicializa el juego a su estado original
void resetGame() {
birdY = tft.height() / 2; // Pájaro en el centro vertical
birdVelocity = 0;
score = 0;
gameOver = false;
lastFlapTime = millis();
// Inicializa las tuberías fuera de la pantalla
for (int i = 0; i < MAX_PIPES; i++) {
pipes[i].x = tft.width() + (i * (tft.width() / MAX_PIPES)) + 50; // Offset para que aparezcan progresivamente
pipes[i].gapY = random(30, tft.height() - 30); // Hueco aleatorio
pipes[i].counted = false;
}
}
// Dibuja el pájaro en la pantalla
void drawBird(int prevY, int currentY) {
tft.fillRect(10, prevY, 8, 8, BLUE); // Borra el pájaro de la posición anterior
tft.fillRect(10, currentY, 8, 8, YELLOW); // Dibuja el pájaro en la nueva posición
}
// Dibuja las tuberías en la pantalla
void drawPipes() {
tft.fillRect(0, 0, tft.width(), tft.height(), BLUE);
for (int i = 0; i < MAX_PIPES; i++) {
if (pipes[i].x < tft.width() && pipes[i].x > -20) {
tft.fillRect(pipes[i].x, 0, 15, pipes[i].gapY - 20, GREEN);
tft.fillRect(pipes[i].x, pipes[i].gapY + 20, 15, tft.height() - (pipes[i].gapY + 20), GREEN);
}
}
}
// Actualiza la posición del pájaro (gravedad y aleteo)
void updateBird() {
birdVelocity += 0.2;
birdY += birdVelocity;
if (birdY < 0) {
birdY = 0;
birdVelocity = 0;
}
if (birdY > tft.height() - 8) {
birdY = tft.height() - 8;
birdVelocity = 0;
gameOver = true;
tone(BUZZER_PIN, 200, 100);
}
}
// Mueve las tuberías y genera nuevas
void updatePipes() {
for (int i = 0; i < MAX_PIPES; i++) {
pipes[i].x -= 2;
if (pipes[i].x < -15) {
pipes[i].x = tft.width();
pipes[i].gapY = random(30, tft.height() - 30);
pipes[i].counted = false;
}
if (!pipes[i].counted && pipes[i].x + 15 < 10) {
score++;
pipes[i].counted = true;
tone(BUZZER_PIN, 1000, 50);
}
}
}
// Comprueba colisiones del pájaro con las tuberías
bool checkCollision() {
for (int i = 0; i < MAX_PIPES; i++) {
if (10 + 8 >= pipes[i].x && 10 <= pipes[i].x + 15) {
if (birdY < pipes[i].gapY - 20 || birdY + 8 > pipes[i].gapY + 20) {
tone(BUZZER_PIN, 200, 100);
return true;
}
}
}
return false;
}
// Muestra la puntuación en la pantalla
void displayScore() {
tft.setTextColor(WHITE);
tft.setTextSize(1);
tft.setCursor(tft.width() - 30, 5);
tft.print(score);
}
// Muestra la pantalla de "Game Over"
void showGameOver() {
tft.fillScreen(ORANGE);
tft.setCursor(20, tft.height() / 2 - 10);
tft.setTextColor(RED);
tft.setTextSize(2);
tft.print("GAME OVER");
tft.setCursor(20, tft.height() / 2 + 10);
tft.setTextColor(WHITE);
tft.setTextSize(1);
tft.print("Score: ");
tft.print(score);
tft.setCursor(5, tft.height() - 20);
tft.print("Press button to restart");
}
// --- Setup y Loop del Arduino ---
void setup() {
Serial.begin(115200);
Serial.println("Inicializando Flappy Bird en ESP32...");
tft.initR(INITR_BLACKTAB);
tft.setRotation(1);
tft.fillScreen(BLUE);
tft.setTextWrap(false);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
randomSeed(analogRead(0));
resetGame();
}
void loop() {
if (gameOver) {
showGameOver();
while (digitalRead(BUTTON_PIN) == HIGH) {
delay(10);
}
delay(50);
while (digitalRead(BUTTON_PIN) == LOW) {
delay(10);
}
resetGame();
tft.fillScreen(BLUE);
} else {
if (digitalRead(BUTTON_PIN) == LOW && (millis() - lastFlapTime > 150)) {
birdVelocity = -3.5;
tone(BUZZER_PIN, 2000, 30);
lastFlapTime = millis();
}
int prevBirdY = birdY;
updateBird();
updatePipes();
if (checkCollision()) {
gameOver = true;
}
drawPipes();
drawBird(prevBirdY, birdY);
displayScore();
delay(30);
}
}
Cómo funciona
El Corazón del Juego: ESP32
El ESP32 es el cerebro de este proyecto. Su alta velocidad de procesamiento y la capacidad de manejar múltiples tareas lo hacen ideal para juegos sencillos. El código cargado en el ESP32 se encarga de:
- Inicialización: Configura la pantalla TFT, los pines del botón y el zumbador. Establece el estado inicial del juego (puntuación cero, pájaro en el centro, etc.).
- Bucle Principal (loop): Esta es la parte más importante donde ocurre toda la magia del juego:
- Lectura del Botón: Constantemente verifica si el botón ha sido presionado. Cuando lo detecta, aplica un impulso hacia arriba al pájaro.
- Física del Pájaro: Calcula la nueva posición del pájaro en función de la gravedad (que lo hace caer constantemente) y los impulsos del botón.
- Movimiento de Tuberías: Mueve las tuberías de derecha a izquierda a través de la pantalla y genera nuevas tuberías cuando una sale del campo de visión.
- Detección de Colisiones: Comprueba si el pájaro ha tocado alguna tubería o el suelo. Si lo hace, se activa el estado de "Game Over".
- Actualización de Puntuación: Incrementa la puntuación cada vez que el pájaro pasa con éxito entre un par de tuberías.
- Renderizado Gráfico: Dibuja el pájaro, las tuberías y la puntuación en la pantalla TFT, actualizando la imagen constantemente para crear la ilusión de movimiento.
- Efectos de Sonido: Utiliza el zumbador para emitir un sonido cada vez que el pájaro aletea, gana un punto o colisiona.
La Pantalla TFT: Tus Ojos en el Juego
La pantalla TFT es donde verás la acción. Conectada al ESP32 mediante SPI (Serial Peripheral Interface), permite dibujar gráficos y texto rápidamente. El código utiliza las librerías Adafruit GFX y ST7735 para simplificar el proceso de dibujar formas, colores y texto, creando la interfaz visual del juego.
El Botón y el Buzzer: Interacción y Sonido
El botón actúa como el control principal del juego. Cada vez que lo presionas, le indicas al pájaro que "aleteé" y gane un impulso hacia arriba. El zumbador proporciona retroalimentación auditiva, haciendo que el juego sea más inmersivo con sonidos para las acciones clave.
En resumen, este proyecto combina programación, electrónica y un poco de creatividad para construir una versión funcional de Flappy Bird, demostrando las capacidades del ESP32 como una plataforma versátil para el desarrollo de pequeños videojuegos y proyectos interactivos.
Material
Aquí os dejamos los materiales que nosotros compramos cuando empezamos. Si quieres darnos una pequeña ayuda puedes comprar desde este link. Gracias por leernos!
- Placa arduino: https://amzn.to/43LM4k4
- Protoboard: https://amzn.to/3LZaZdM
- Cables: https://amzn.to/3K5N3ox
- Leds: https://amzn.to/4iryuse
- Buzzer: https://amzn.to/4ilPlfX
- Pack de lo necesario para empezar: https://amzn.to/3MmuDAs
