#include <Wire.h>
#include <ArduinoJson.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <SPI.h>
#include <ArduinoJson.h>
#define btn1 26 // Botón para pausar/reanudar
#define btn2 27 // Botón para volver a la pantalla de inicio
#define pinY 35
#define pinX 34
#define MAX_VERT 4095
#define MIN_VERT 0
#define umbralJoy 500 // Umbral para detectar movimiento en el joystick
JsonDocument doc;
LiquidCrystal_I2C lcd(0x27, 20, 4);
int colJugador = 7; // Columna inicial del jugador
int filaJugador = 2; // Fila inicial del jugador
int colAnterior = 0; // Columna anterior del jugador
int rowAnterior = 1; // Fila anterior del jugador
bool menu = true;
int score = 1;
int colObstaculo = 16; // Columna inicial del primer obstáculo
int filaObstaculo = 1; // Fila del primer obstáculo (se define aleatoriamente)
int colObstaculoAnterior = 15; // Columna anterior del primer obstáculo
int filaObstaculoAnterior = 1; // Fila anterior del primer obstáculo
int colObstaculo2 = 19; // Columna inicial del segundo obstáculo
int filaObstaculo2 = 2; // Fila del segundo obstáculo (se define aleatoriamente)
int colObstaculo2Anterior = 15; // Columna anterior del segundo obstáculo
int filaObstaculo2Anterior = 2; // Fila anterior del segundo obstáculo
bool scorePrinted = false;
bool obstaculoActivo = true; // Bandera para controlar si el primer obstáculo está activo
bool obstaculo2Activo = false; // Bandera para el segundo obstáculo
bool juegoPausado = false; // Bandera para pausar/reanudar
bool juegoIniciado = false; // Bandera para saber si el juego ha iniciado
// Definición del carácter personalizado para el jugador y el obstáculo
byte corazon[] = {
B00000,
B01010,
B11111,
B11111,
B01110,
B00100,
B00000,
B00000
};
byte calavera[] = {
B00000,
B01110,
B10101,
B11011,
B01110,
B01110,
B00000,
B00000
};
byte jugador[] = {
B01110, B01010,
B01110, B00100,
B11111, B00100,
B01010, B01010
};
byte obstaculo[] = {
B00011, B00101,
B01110, B11111,
B11111, B01110,
B00101, B00011
};
byte cursorSelect[] = {
B00000, B01000,
B01100, B01110,
B01100, B01000,
B00000, B00000
};
String json;
void setup() {
Serial.begin(115200);
lcd.init();
lcd.backlight();
lcd.createChar(0, jugador); // jugador
lcd.createChar(1, obstaculo); // obstaculo
lcd.createChar(2, cursorSelect); //cursor
lcd.createChar(3, corazon); //corazon
lcd.createChar(4, calavera); // calavera
// AQUI VA LO DE LA SD
while (!SD.begin(5)) {
Serial.println(F("Falló la inicialización del módulo MicroSD"));
delay(1000);
}
Serial.println(F("MicroSD inicializada con éxito"));
//JOYSTICKS
pinMode(pinY, INPUT);
pinMode(pinX, INPUT);
pinMode(btn1, INPUT_PULLUP); // Configurar el botón para pausar/reanudar
pinMode(btn2, INPUT_PULLUP); // Configurar el botón para volver a inicio
randomSeed(analogRead(0));
lcd.setCursor(colJugador, filaJugador);
lcd.write(0); // Mostrar el jugador
pantallaInicio();
doc["score"][0] = 0;
doc["score"][1] = 0;
doc["score"][2] = 0;
doc["score"][3] = 0;
}
bool btn1EstadoAnterior = HIGH;
bool btn2EstadoAnterior = HIGH;
void loop() {
bool btn1EstadoActual = digitalRead(btn1);
bool btn2EstadoActual = digitalRead(btn2);
if (analogRead(pinX) > MAX_VERT - umbralJoy && menu == true && !juegoIniciado) {
Serial.println("LLEGA HASTA AQUI");
lcd.clear();
dibujarBorde(3);
deserializeJson(doc, readFile()); //creamos un array que contenga los 4 scores mas altos (llama a la funcion del archivo microsd.h)
delay(300);
//AQUI VAN LOS SCORES
lcd.setCursor(3, 1);
lcd.print("No.1-");
lcd.setCursor(8, 1);
lcd.print((String)doc["score"][0]);
lcd.setCursor(10, 1);
lcd.print("No.2-");
lcd.setCursor(15, 1);
lcd.print((String)doc["score"][1]);
lcd.setCursor(3, 2);
lcd.print("No.3-");
lcd.setCursor(8, 2);
lcd.print((String)doc["score"][2]);
lcd.setCursor(10, 2);
lcd.print("No.4-");
lcd.setCursor(15, 2);
lcd.print((String)doc["score"][3]);
lcd.setCursor(7,0);
lcd.print("SCORE");
//MSD.getTopScores();
menu = false; //
}
if (btn1EstadoAnterior == HIGH && btn1EstadoActual == LOW) {
delay(200);
if (!juegoIniciado) {
juegoIniciado = true;
tone(4, 262, 250);
lcd.clear();
} else {
juegoPausado = !juegoPausado;
tone(4, 50, 100);
}
}
if (btn2EstadoAnterior == HIGH && btn2EstadoActual == LOW) {
delay(200);
resetJuego();
}
btn1EstadoAnterior = btn1EstadoActual;
btn2EstadoAnterior = btn2EstadoActual;
if (juegoIniciado) {
lcd.clear();
if (!juegoPausado) {
int valorY = analogRead(pinY);
int xValue = analogRead(pinX);
moverJugador(valorY, xValue);
moverObstaculo();
if (obstaculo2Activo) {
moverObstaculo2(); // Mover el segundo obstáculo si está activo
}
detectarColision();
actualizarPantalla();
imprimirScore();
// Activar el segundo obstáculo si el score es 10 o más
if (score >= 10 && !obstaculo2Activo) {
obstaculo2Activo = true;
colObstaculo2 = 19; // Reiniciar posición del segundo obstáculo
filaObstaculo2 = random(0, 3); // Aleatorizar fila
}
} else {
lcd.setCursor(2, 1);
lcd.print("PAUSA. SCORE: ");
lcd.setCursor(15, 1);
lcd.print(score);
dibujarBorde(3);
}
}
delay(100);
}
void pantallaInicio() {
lcd.clear();
lcd.setCursor(5, 1);
lcd.print("The Game!");
lcd.setCursor(10, 2);
lcd.write(2);
lcd.setCursor(11, 2);
lcd.print("Play");
lcd.setCursor(3, 2);
lcd.print("Score");
dibujarBorde(3);
}
void imprimirScore() {
lcd.setCursor(0, 3);
lcd.print("Score");
lcd.setCursor(8, 3);
lcd.print(score);
if(score < 10) {
lcd.setCursor(10,3);
lcd.print("Nivel 1");
}
else{
lcd.setCursor(10,3);
lcd.print("Nivel 2");
}
}
void resetJuego() {
tone(4, 800, 400);
juegoIniciado = false;
juegoPausado = false;
score = 1;
colJugador = 0;
filaJugador = 1;
colObstaculo = 15;
filaObstaculo = 1;
colObstaculo2 = 15;
filaObstaculo2 = 2;
obstaculoActivo = true;
obstaculo2Activo = false;
lcd.clear();
pantallaInicio();
menu = true;
}
void moverJugador(int valorY, int xValue) {
colAnterior = colJugador;
rowAnterior = filaJugador;
if (valorY > MAX_VERT - umbralJoy && filaJugador > 0) {
filaJugador--;
} else if (valorY < MIN_VERT + umbralJoy && filaJugador < 2) {
filaJugador++;
}
if (xValue < MIN_VERT + umbralJoy && colJugador < 20) {
colJugador++;
} else if (xValue > MAX_VERT - umbralJoy && colJugador > 0) {
colJugador--;
}
}
void moverObstaculo() {
if (obstaculoActivo) {
colObstaculoAnterior = colObstaculo;
filaObstaculoAnterior = filaObstaculo;
colObstaculo--;
if (colObstaculo < 0) {
score++;
colObstaculo = 19;
filaObstaculo = random(0, 3);
}
}
}
void moverObstaculo2() {
colObstaculo2Anterior = colObstaculo2;
filaObstaculo2Anterior = filaObstaculo2;
colObstaculo2--;
if (colObstaculo2 < 0) {
colObstaculo2 = 19;
filaObstaculo2 = random(0, 3);
}
}
void detectarColision() {
// Colision obstaculo 1
if (colJugador == colObstaculo && filaJugador == filaObstaculo) {
lcd.clear();
lcd.setCursor(3, 1);
tone(18, 262, 250);
lcd.print("Game Over!");
lcd.setCursor(3, 2);
lcd.print("Your score: ");
for (int i = 0; i < 4; i++)
{
if (doc["score"][i] <= score)
{
for (int j = 3; j > i; j--)
{
doc["score"][j] = doc["score"][j - 1];
}
doc["score"][i] = score;
break;
}
}
serializeJson(doc, json);
writeFile(json);
//MSD.saveScore(score); //GUARDAMOS SCORE A LA SD
lcd.print(score);
dibujarBorde(4);
obstaculoActivo = false;
delay(3000);
resetJuego();
}
// Colision obstaculo 2
if (colJugador == colObstaculo2 && filaJugador == filaObstaculo2) {
lcd.clear();
lcd.setCursor(3, 1);
tone(18, 262, 250);
lcd.print("Game Over!");
lcd.setCursor(3, 2);
lcd.print("Your score: ");
for (int i = 0; i < 4; i++)
{
if (doc["score"][i] <= score)
{
for (int j = 3; j > i; j--)
{
doc["score"][j] = doc["score"][j - 1];
}
doc["score"][i] = score;
break;
}
}
serializeJson(doc, json);
writeFile(json);
//MSD.saveScore(score); //GUARDAMOS SCORE A LA SD
lcd.print(score);
dibujarBorde(4);
obstaculo2Activo = false;
delay(3000);
resetJuego();
}
}
void actualizarPantalla() {
lcd.setCursor(colAnterior, rowAnterior);
lcd.write(32); // Borra la posición anterior del jugador
lcd.setCursor(colJugador, filaJugador);
lcd.write(0); // Dibujar jugador en nueva posición
// Actualizar primer obstáculo
lcd.setCursor(colObstaculoAnterior, filaObstaculoAnterior);
lcd.write(32); // Borrar obstáculo anterior
lcd.setCursor(colObstaculo, filaObstaculo);
lcd.write(1); // Dibujar obstáculo en nueva posición
// Actualizar segundo obstáculo si está activo
if (obstaculo2Activo) {
lcd.setCursor(colObstaculo2Anterior, filaObstaculo2Anterior);
lcd.write(32); // Borrar el obstáculo anterior
lcd.setCursor(colObstaculo2, filaObstaculo2);
lcd.write(1); // Dibujar obstáculo en nueva posición
}
}
void dibujarBorde(int figura) {
for (int i = 0; i < 20; i++) {
lcd.setCursor(i,0);
lcd.write(figura);
lcd.setCursor(i,figura);
lcd.write(figura);
}
// dibujar dos figuras a la izquierda
lcd.setCursor(0,1);
lcd.write(figura);
lcd.setCursor(0,2);
lcd.write(figura);
//dibujar dos figuras a la derecha
lcd.setCursor(19,1);
lcd.write(figura);
lcd.setCursor(19,2);
lcd.write(figura);
}
String readFile()
{
String text;
File textFile = SD.open("/prieto.txt");
if (textFile)
{
while (textFile.available())
{
text += (char)textFile.read();
}
textFile.close();
}
else
{
// Si no existe el archivo
serializeJson(doc, text);
writeFile(text);
}
Serial.println(text);
return text;
}
void writeFile(String text)
{
File textFile = SD.open("/prieto.txt", FILE_WRITE);
if (textFile)
{
textFile.print(text);
textFile.close();
Serial.println(readFile());
}
else
{
Serial.println("Caca");
}
}