Загрузка данных


#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_NeoPixel.h>

#define POT_PIN A0
#define BUTTON_PIN 2
#define BUZZER 3

#define RED_PIN 9
#define GREEN_PIN 10
#define BLUE_PIN 11

#define RING_PIN 6
#define RING_COUNT 16

LiquidCrystal_I2C lcd(0x27, 16, 2);
Adafruit_NeoPixel ring(RING_COUNT, RING_PIN, NEO_GRB + NEO_KHZ800);

enum GameState {
  WAITING,
  COUNTDOWN,
  SHOW_TARGET,
  PLAYING,
  FEEDBACK,
  WIN,
  LOSE
};

GameState state = WAITING;

unsigned long stateTimer = 0;
unsigned long gameStart = 0;
unsigned long holdStart = 0;
unsigned long lastMusicNote = 0;
unsigned long lastCountdown = 0;

int roundNumber = 0;
int targetColor = 0;
int selectedColor = 0;
int countdownNumber = 3;
int feedbackResult = 0;

bool buttonWasPressed = false;
bool buttonHolding = false;
bool musicEnabled = false;

const int melody[] = {
  392, 440, 523, 440,
  349, 392, 440, 392,
  330, 392, 440, 523
};

const int noteDuration[] = {
  300, 300, 400, 300,
  300, 300, 400, 300,
  300, 300, 400, 300
};

int musicNote = 0;
bool notePlaying = false;

// ---------- RGB ----------

void setRGB(int r, int g, int b) {
  analogWrite(RED_PIN, r);
  analogWrite(GREEN_PIN, g);
  analogWrite(BLUE_PIN, b);
}

uint32_t getHueColor(byte hue, byte brightness = 100) {
  return ring.ColorHSV((uint16_t)hue * 257, 255, brightness * 255 / 100);
}

void showRing(int selected) {
  ring.clear();

  for (int i = 0; i < RING_COUNT; i++) {
    byte hue = i * 16;

    if (i == selected) {
      ring.setPixelColor(i, getHueColor(hue, 100));
    } else {
      ring.setPixelColor(i, getHueColor(hue, 35));
    }
  }

  ring.show();
}

// ---------- MUSIC ----------

void playBackgroundMusic() {
  unsigned long now = millis();

  if (now - lastMusicNote >= 420) {
    lastMusicNote = now;
    musicNote = (musicNote + 1) % 12;
    notePlaying = true;
  }

  if (notePlaying && now - lastMusicNote < 260) {
    tone(BUZZER, melody[musicNote]);
  } else {
    noTone(BUZZER);
  }
}

void stopMusic() {
  noTone(BUZZER);
  notePlaying = false;
}

// ---------- BUTTON ----------

bool buttonPressed() {
  return digitalRead(BUTTON_PIN) == LOW;
}

// ---------- ROUND ----------

void newRound() {
  targetColor = random(0, 16);

  setRGB(
    (getHueColor(targetColor * 16) >> 16) & 255,
    (getHueColor(targetColor * 16) >> 8) & 255,
    getHueColor(targetColor * 16) & 255
  );

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("MEMORIZE COLOR");

  state = SHOW_TARGET;
  stateTimer = millis();
}

void startGame() {
  roundNumber = 1;
  gameStart = millis();
  countdownNumber = 3;
  lastCountdown = 0;

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("GET READY!");

  state = COUNTDOWN;
  stateTimer = millis();
  lastMusicNote = millis();
  musicNote = 0;
}

// ---------- SETUP ----------

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(BUZZER, OUTPUT);

  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);

  lcd.init();
  lcd.backlight();

  ring.begin();
  ring.setBrightness(80);
  ring.show();

  randomSeed(analogRead(A1));

  lcd.setCursor(0, 0);
  lcd.print("COLOR CHALLENGE");
  lcd.setCursor(0, 1);
  lcd.print("PRESS TO START");
}

// ---------- LOOP ----------

void loop() {
  unsigned long now = millis();

  // WAITING
  if (state == WAITING) {
    if (buttonPressed()) {
      delay(200);
      if (buttonPressed()) {
        startGame();
        while (buttonPressed()) delay(10);
      }
    }
    return;
  }

  // COUNTDOWN
  if (state == COUNTDOWN) {
    if (countdownNumber > 0 && now - lastCountdown >= 1000) {
      lastCountdown = now;

      lcd.setCursor(0, 1);
      lcd.print("       ");
      lcd.setCursor(7, 1);
      lcd.print(countdownNumber);

      tone(BUZZER, 700, 120);

      countdownNumber--;
    }

    if (countdownNumber == 0 && now - lastCountdown >= 1000) {
      stopMusic();
      newRound();
    }

    return;
  }

  // SHOW TARGET
  if (state == SHOW_TARGET) {
    if (now - stateTimer >= 2000) {
      setRGB(0, 0, 0);

      selectedColor = map(analogRead(POT_PIN), 0, 1023, 0, 15);
      showRing(selectedColor);

      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("CHOOSE COLOR");
      lcd.setCursor(0, 1);
      lcd.print("HOLD 3 SECONDS");

      state = PLAYING;
      stateTimer = now;
      lastMusicNote = now;
      musicNote = 0;
    }

    return;
  }

  // PLAYING
  if (state == PLAYING) {
    playBackgroundMusic();

    if (now - gameStart >= 50000) {
      stopMusic();
      tone(BUZZER, 250);
      state = LOSE;
      stateTimer = now;
      lcd.clear();
      lcd.print("TIME IS UP!");
      return;
    }

    selectedColor = map(analogRead(POT_PIN), 0, 1023, 0, 15);
    showRing(selectedColor);

    lcd.setCursor(0, 0);
    lcd.print("ROUND ");
    lcd.print(roundNumber);
    lcd.print("/5       ");

    lcd.setCursor(0, 1);
    lcd.print("HOLD 3 SECONDS");

    if (buttonPressed()) {
      if (!buttonHolding) {
        buttonHolding = true;
        holdStart = now;
      }

      if (now - holdStart >= 3000) {
        buttonHolding = false;
        stopMusic();

        if (selectedColor == targetColor) {
          feedbackResult = 1;
        } else {
          feedbackResult = -1;
        }

        state = FEEDBACK;
        stateTimer = now;

        lcd.clear();

        if (feedbackResult == 1) {
          lcd.print("CORRECT!");
          tone(BUZZER, 1000, 150);
        } else {
          lcd.print("WRONG!");
          tone(BUZZER, 200, 400);
        }
      }
    } else {
      buttonHolding = false;
    }

    return;
  }

  // FEEDBACK
  if (state == FEEDBACK) {
    if (now - stateTimer >= 1200) {
      if (feedbackResult == 1) {
        if (roundNumber >= 5) {
          state = WIN;
          stateTimer = now;
          lcd.clear();
          lcd.print("YOU WIN!");
          ring.fill(ring.Color(0, 100, 0));
          ring.show();
        } else {
          roundNumber++;
          newRound();
        }
      } else {
        newRound();
      }
    }

    return;
  }

  // WIN
  if (state == WIN) {
    stopMusic();

    if (buttonPressed()) {
      delay(200);
      if (buttonPressed()) {
        ring.clear();
        ring.show();
        setRGB(0, 0, 0);

        state = WAITING;
        lcd.clear();
        lcd.print("COLOR CHALLENGE");
        lcd.setCursor(0, 1);
        lcd.print("PRESS TO START");

        while (buttonPressed()) delay(10);
      }
    }

    return;
  }

  // LOSE
  if (state == LOSE) {
    if (now - stateTimer >= 3000) {
      stopMusic();
      ring.clear();
      ring.show();

      state = WAITING;
      lcd.clear();
      lcd.print("GAME OVER");
      lcd.setCursor(0, 1);
      lcd.print("PRESS TO START");
    }

    return;
  }
}