#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Definir pines
const int BUTTON_PINS[] = {13, 12, 14, 27}; // Pines para los botones
const int LED_PINS[] = {26, 25, 33, 32}; // Pines para los LEDs
const int BUZZER_PIN = 15; // Pin para el buzzer
// Notas musicales
const int NOTES[] = {262, 330, 392, 523}; // Do, Mi, Sol, Do (una octava más alta)
const int MAX_LEVEL = 100;
int sequence[MAX_LEVEL];
int level = 1;
void setup() {
Serial.begin(115200);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
for (int i = 0; i < 4; i++) {
pinMode(BUTTON_PINS[i], INPUT_PULLUP);
pinMode(LED_PINS[i], OUTPUT);
}
pinMode(BUZZER_PIN, OUTPUT);
randomSeed(analogRead(0));
}
void playTone(int note, int duration) {
tone(BUZZER_PIN, note, duration);
delay(duration);
noTone(BUZZER_PIN);
}
void showHappyFace() {
display.clearDisplay();
display.drawCircle(64, 32, 30, SSD1306_WHITE); // Dibuja la cara (un círculo)
display.fillCircle(52, 22, 4, SSD1306_WHITE); // Ojo izquierdo
display.fillCircle(76, 22, 4, SSD1306_WHITE); // Ojo derecho
// Boca curva hacia arriba
display.drawLine(52, 42, 58, 48, SSD1306_WHITE);
display.drawLine(58, 48, 70, 48, SSD1306_WHITE);
display.drawLine(70, 48, 76, 42, SSD1306_WHITE);
display.display();
}
void showSadFace() {
display.clearDisplay();
display.drawCircle(64, 32, 30, SSD1306_WHITE); // Dibuja la cara (un círculo)
display.fillCircle(52, 22, 4, SSD1306_WHITE); // Ojo izquierdo
display.fillCircle(76, 22, 4, SSD1306_WHITE); // Ojo derecho
// Boca curva hacia abajo
display.drawLine(52, 48, 58, 42, SSD1306_WHITE);
display.drawLine(58, 42, 70, 42, SSD1306_WHITE);
display.drawLine(70, 42, 76, 48, SSD1306_WHITE);
display.display();
}
void showLevel() {
display.clearDisplay();
display.setCursor(0, 0);
display.print("Nivel: ");
display.println(level);
display.display();
}
void showStartMessage() {
display.clearDisplay();
display.setCursor(0, 0);
display.println("Simon Dice");
display.println("Presiona cualquier");
display.println("boton para comenzar");
display.display();
}
void generateSequence() {
for (int i = 0; i < level; i++) {
sequence[i] = random(4);
}
}
void playSequence() {
for (int i = 0; i < level; i++) {
digitalWrite(LED_PINS[sequence[i]], HIGH);
playTone(NOTES[sequence[i]], 500); // Aumenta el tiempo para que el jugador pueda seguir el ritmo
digitalWrite(LED_PINS[sequence[i]], LOW);
delay(300); // Tiempo entre las señales de la secuencia
}
}
bool getPlayerInput() {
for (int i = 0; i < level; i++) {
int pressed = -1;
long startTime = millis();
while (pressed == -1 && (millis() - startTime < 5000)) { // 5 segundos de espera por la entrada del jugador
for (int j = 0; j < 4; j++) {
if (digitalRead(BUTTON_PINS[j]) == LOW) {
pressed = j;
digitalWrite(LED_PINS[j], HIGH);
playTone(NOTES[j], 300);
digitalWrite(LED_PINS[j], LOW);
delay(300); // Retardo para permitir que el LED se apague antes de la siguiente entrada
break;
}
}
}
if (pressed == -1 || pressed != sequence[i]) { // Si el tiempo se agota o el jugador presiona un botón incorrecto
return false;
}
}
return true;
}
void playWinSequence() {
for (int i = 0; i < 3; i++) {
playTone(NOTES[3], 100);
delay(50);
}
showHappyFace();
delay(2000); // Tiempo para ver la carita feliz
}
void playLoseSequence() {
for (int i = 3; i >= 0; i--) {
playTone(NOTES[i], 300);
delay(100);
}
showSadFace();
delay(2000); // Tiempo para ver la carita triste
}
void waitForStart() {
showStartMessage();
bool buttonPressed = false;
while (!buttonPressed) {
for (int i = 0; i < 4; i++) {
if (digitalRead(BUTTON_PINS[i]) == LOW) {
buttonPressed = true;
break;
}
}
delay(50);
}
}
void loop() {
waitForStart();
level = 1;
while (true) {
showLevel();
delay(1000); // Espera antes de mostrar la secuencia
generateSequence();
playSequence();
if (getPlayerInput()) {
playWinSequence();
level++;
if (level > MAX_LEVEL) {
break;
}
} else {
playLoseSequence();
break;
}
delay(1000); // Espera antes de iniciar el siguiente nivel
}
}