Загрузка данных
#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;
}
}