#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP32Servo.h>
#define OLED_ANCHO 128
#define OLED_ALTO 64
#define NUM_FANTASMAS 5
#define TAM_GALLETA 1
const int BOTON_X_PIN = 32;
const int BOTON_X_NEG_PIN = 27;
const int BOTON_Y_PIN = 25;
const int BOTON_Y_NEG_PIN = 33;
unsigned long lastMoveTime = 0;
const unsigned long moveInterval = 500;
Servo servo;
#define pin 19
#define pwmServo 13
bool estadoBotonXActual, estadoBotonXAnterior;
bool estadoBotonXNegActual, estadoBotonXNegAnterior;
bool estadoBotonYActual, estadoBotonYAnterior;
bool estadoBotonYNegActual, estadoBotonYNegAnterior;
bool gameOver = false;
bool winner = false;
int numGalletas = 0;
int posicionX = 8;
int posicionY = 8;
int fantasmas[NUM_FANTASMAS][2];
int numFantasmasGenerados = 0;
int paso = 8;
int contadorMovimientos = 0;
Adafruit_SSD1306 pantalla(OLED_ANCHO, OLED_ALTO, &Wire, -1);
// 'universidad', 128x64px
const unsigned char epd_bitmap_universidad [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0x8c, 0xfc, 0xf8, 0xf8, 0x04, 0x3e, 0x78, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0x8c, 0x7c, 0x78, 0xf8, 0x04, 0x3e, 0x78, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0x8c, 0x7c, 0x78, 0xf8, 0x06, 0x3c, 0x78, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xcc, 0x7e, 0x78, 0xf8, 0x06, 0x3c, 0x78, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xcc, 0x7e, 0x38, 0xf8, 0x06, 0x3c, 0x78, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xcc, 0x7e, 0x38, 0xf8, 0x07, 0x1c, 0xf8, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xcc, 0x7f, 0x38, 0xf8, 0x07, 0x1c, 0xf8, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xce, 0x3f, 0x18, 0xf8, 0x07, 0x1c, 0xf8, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xce, 0x3f, 0x18, 0xf8, 0x07, 0x18, 0xf8, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xce, 0x3f, 0x08, 0xf8, 0x00, 0x00, 0xf8, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc6, 0x3f, 0x88, 0xf8, 0x00, 0x03, 0xf8, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc6, 0x3f, 0x80, 0xf8, 0x07, 0x0f, 0xf8, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc6, 0x3f, 0xc0, 0xf8, 0x07, 0x0f, 0xf8, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc6, 0x1f, 0xe0, 0x08, 0x07, 0x8f, 0xf8, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc7, 0x1f, 0xf8, 0x00, 0x07, 0x8f, 0xf0, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc7, 0x1f, 0xf9, 0xc0, 0x07, 0x8f, 0xf0, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc7, 0x1f, 0xf9, 0xf8, 0x07, 0x8f, 0xf0, 0xf9, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc7, 0x0f, 0xf9, 0xf8, 0x07, 0x8f, 0xf0, 0xf9, 0xfc, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc7, 0x0f, 0xf9, 0xf8, 0x07, 0x8f, 0xf0, 0xe1, 0xf8, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc7, 0x0f, 0xf9, 0xf8, 0x07, 0x8f, 0xf0, 0x01, 0xf8, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc7, 0x0f, 0xf9, 0xf8, 0x07, 0x8f, 0xf0, 0x0f, 0xf0, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xc3, 0x8f, 0xf9, 0xf8, 0x07, 0x87, 0x00, 0x3f, 0xe0, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x07, 0xc0, 0x07, 0xf9, 0xf8, 0x07, 0x80, 0x00, 0xff, 0xe2, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x03, 0xf8, 0x03, 0xf9, 0xf8, 0x07, 0x00, 0x38, 0xff, 0xc2, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x01, 0xff, 0x00, 0x11, 0xf8, 0x00, 0x07, 0xf8, 0xff, 0x86, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0xff, 0x80, 0x01, 0xf8, 0x00, 0xff, 0xf8, 0xff, 0x06, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x08, 0x3f, 0xc3, 0x80, 0x38, 0x07, 0xff, 0xf8, 0xfc, 0x0e, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x08, 0x1f, 0xc3, 0xf8, 0x00, 0x07, 0xff, 0xf8, 0x00, 0x1e, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0c, 0x0f, 0xc3, 0xff, 0x80, 0x07, 0xfe, 0x00, 0x00, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0e, 0x03, 0xc1, 0xff, 0xf8, 0x04, 0x00, 0x00, 0x7f, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0x80, 0x01, 0xff, 0xf8, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xe0, 0x01, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xfc, 0x00, 0x00, 0x78, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0x80, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff,
0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff,
0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xc0, 0x1f, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xfe, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x00, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x1f, 0xff, 0xf8, 0x07, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xf8, 0x07, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xf8, 0x07, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x1f, 0xf8, 0x07, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x03, 0xf8, 0x07, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x78, 0x07, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x18, 0x06, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const int laberinto[8][16] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1},
{1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
// Matriz para almacenar las galletas
int galletas[8][16];
void dibujarLaberinto() {
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 16; x++) {
if (laberinto[y][x] == 1) {
// Dibujar paredes del laberinto
pantalla.drawRect(x * 8, y * 8, 8, 8, SSD1306_WHITE);
} else if (galletas[y][x] == 1) {
// Dibujar galletas
pantalla.fillCircle(x * 8 + 4, y * 8 + 4, TAM_GALLETA, SSD1306_WHITE);
}
}
}
for (int i = 0; i < numFantasmasGenerados; i++) {
dibujarFantasma(fantasmas[i][0], fantasmas[i][1]);
}
}
void inicializarGalletas() {
numGalletas = 0; // Reiniciar contador de galletas
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 16; x++) {
if (laberinto[y][x] == 0) {
galletas[y][x] = 1;
numGalletas++; // Contar galleta
} else {
galletas[y][x] = 0;
}
}
}
}
void setup() {
Serial.begin(115200);
Serial.println("Hola ESP32!");
pinMode(BOTON_X_PIN, INPUT);
pinMode(BOTON_X_NEG_PIN, INPUT);
pinMode(BOTON_Y_PIN, INPUT);
pinMode(BOTON_Y_NEG_PIN, INPUT);
if (!pantalla.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("Error al inicializar la pantalla OLED");
while (true);
}
pantalla.clearDisplay();
pantalla.display();
mostrarInformacion(); // Mostrar la secuencia de inicio
inicializarGalletas();
for (int i = 0; i < 2; i++) {
generarFantasma();
}
pinMode(pin, INPUT);
servo.attach(pwmServo, 544, 2400);
servo.write(0);
}
void loop() {
int valor = digitalRead(pin);
Serial.println(valor);
if (valor == 1) {
servo.write(180);
} else {
servo.write(0);
}
if (gameOver) {
pantalla.clearDisplay();
pantalla.setTextSize(2);
pantalla.setTextColor(SSD1306_WHITE);
pantalla.setCursor(20, 20);
pantalla.print("GAME OVER");
pantalla.display();
delay(2000);
resetGame();
}
else if (winner) { // Manejar estado de ganar
pantalla.clearDisplay();
pantalla.setTextSize(2);
pantalla.setTextColor(SSD1306_WHITE);
pantalla.setCursor(30, 20);
pantalla.print("WINNER");
pantalla.display();
delay(3000);
resetGame();
}
else {
moverPixelX();
moverPixelXNegativo();
moverPixelY();
moverPixelYNegativo();
if (millis() - lastMoveTime > moveInterval) {
moverFantasmasAleatoriamente();
verificarColisionFantasma();
lastMoveTime = millis();
}
dibujarJuego();
}
}
void mostrarInformacion() {
// Mostrar el logo de la universidad
pantalla.clearDisplay();
pantalla.drawBitmap(0, 0, epd_bitmap_universidad, 128, 64, SSD1306_WHITE);
pantalla.display();
delay(3000); // Esperar 3 segundos
// Mostrar el texto informativo
pantalla.clearDisplay();
pantalla.setTextSize(1); // Tamaño de texto adecuado para la pantalla
pantalla.setTextColor(SSD1306_WHITE);
pantalla.setCursor(0, 0);
pantalla.println("Universidad");
pantalla.println("Sergio Arboleda");
pantalla.setCursor(0, 16);
pantalla.println("Edge Computing");
pantalla.setCursor(0, 32);
pantalla.println("Juan Barrera");
pantalla.println("Miguel Gonzalez");
pantalla.println("Iván Rodriguez");
pantalla.setCursor(0, 48);
pantalla.println("2024");
pantalla.display();
delay(3000); // Esperar 3 segundos
}
void resetGame() {
posicionX = 8;
posicionY = 8;
inicializarGalletas();
numFantasmasGenerados = 0;
for (int i = 0; i < 2; i++) {
generarFantasma();
}
gameOver = false;
winner = false;
}
void generarFantasma() {
if (numFantasmasGenerados < NUM_FANTASMAS) {
int fantasmaX, fantasmaY;
do {
fantasmaX = random(16);
fantasmaY = random(8);
} while (laberinto[fantasmaY][fantasmaX] == 1);
fantasmas[numFantasmasGenerados][0] = fantasmaX * 8;
fantasmas[numFantasmasGenerados][1] = fantasmaY * 8;
numFantasmasGenerados++;
}
}
void verificarMovimientos() {
contadorMovimientos++;
if (contadorMovimientos == 5) {
generarFantasma();
contadorMovimientos = 0;
}
}
void moverFantasmasAleatoriamente() {
for (int i = 0; i < numFantasmasGenerados; i++) {
int direccion = random(4);
int fantasmaX = fantasmas[i][0] / 8;
int fantasmaY = fantasmas[i][1] / 8;
switch (direccion) {
case 0: // Arriba
if (fantasmaY > 0 && laberinto[fantasmaY - 1][fantasmaX] == 0) fantasmas[i][1] -= 8;
break;
case 1: // Abajo
if (fantasmaY < 7 && laberinto[fantasmaY + 1][fantasmaX] == 0) fantasmas[i][1] += 8;
break;
case 2: // Izquierda
if (fantasmaX > 0 && laberinto[fantasmaY][fantasmaX - 1] == 0) fantasmas[i][0] -= 8;
break;
case 3: // Derecha
if (fantasmaX < 15 && laberinto[fantasmaY][fantasmaX + 1] == 0) fantasmas[i][0] += 8;
break;
}
}
}
void moverPixelX() {
estadoBotonXActual = digitalRead(BOTON_X_PIN);
int nuevaPosicionX = posicionX + paso;
int celdaX = nuevaPosicionX / 8;
int celdaY = posicionY / 8;
if (estadoBotonXActual && !estadoBotonXAnterior && nuevaPosicionX < OLED_ANCHO - paso && laberinto[celdaY][celdaX] == 0) {
posicionX = nuevaPosicionX;
verificarGalleta(celdaX, celdaY);
dibujarJuego();
}
estadoBotonXAnterior = estadoBotonXActual;
}
void moverPixelXNegativo() {
estadoBotonXNegActual = digitalRead(BOTON_X_NEG_PIN);
int nuevaPosicionX = posicionX - paso;
int celdaX = nuevaPosicionX / 8;
int celdaY = posicionY / 8;
if (estadoBotonXNegActual && !estadoBotonXNegAnterior && nuevaPosicionX >= 0 && laberinto[celdaY][celdaX] == 0) {
posicionX = nuevaPosicionX;
verificarGalleta(celdaX, celdaY);
dibujarJuego();
}
estadoBotonXNegAnterior = estadoBotonXNegActual;
}
void moverPixelY() {
estadoBotonYActual = digitalRead(BOTON_Y_PIN);
int nuevaPosicionY = posicionY + paso;
int celdaX = posicionX / 8;
int celdaY = nuevaPosicionY / 8;
if (estadoBotonYActual && !estadoBotonYAnterior && nuevaPosicionY < OLED_ALTO - paso && laberinto[celdaY][celdaX] == 0) {
posicionY = nuevaPosicionY;
verificarGalleta(celdaX, celdaY);
dibujarJuego();
}
estadoBotonYAnterior = estadoBotonYActual;
}
void moverPixelYNegativo() {
estadoBotonYNegActual = digitalRead(BOTON_Y_NEG_PIN);
int nuevaPosicionY = posicionY - paso;
int celdaX = posicionX / 8;
int celdaY = nuevaPosicionY / 8;
if (estadoBotonYNegActual && !estadoBotonYNegAnterior && nuevaPosicionY >= 0 && laberinto[celdaY][celdaX] == 0) {
posicionY = nuevaPosicionY;
verificarGalleta(celdaX, celdaY);
dibujarJuego();
}
estadoBotonYNegAnterior = estadoBotonYNegActual;
}
void verificarColisionFantasma() {
for (int i = 0; i < numFantasmasGenerados; i++) {
if (fantasmas[i][0] == posicionX && fantasmas[i][1] == posicionY) {
gameOver = true;
}
}
}
void verificarGalleta(int celdaX, int celdaY) {
if (galletas[celdaY][celdaX] == 1) {
galletas[celdaY][celdaX] = 0;
numGalletas--; // Decrementar el contador de galletas
if (numGalletas == 0) { // Verificar si todas las galletas han sido comidas
winner = true;
}
}
}
void dibujarJuego() {
pantalla.clearDisplay();
dibujarLaberinto();
dibujarPacMan(posicionX, posicionY);
for (int i = 0; i < numFantasmasGenerados; i++) {
dibujarFantasma(fantasmas[i][0], fantasmas[i][1]);
}
pantalla.display();
}
void dibujarPacMan(int x, int y) {
pantalla.fillCircle(x + 4, y + 4, 4, SSD1306_WHITE);
}
void dibujarFantasma(int x, int y) {
pantalla.fillRect(x + 1, y + 1, 6, 4, SSD1306_WHITE);
pantalla.drawPixel(x + 2, y + 5, SSD1306_WHITE);
pantalla.drawPixel(x + 4, y + 5, SSD1306_WHITE);
}