Gra REFLEKS z 5 diodami dla każdego gracza

Gra REFLEKS – z pięcioma diodami
(dla każdego gracza)

W tej wersji gry każdy gracz ma aż pięć diod, które pokazują jego punkty! Zasady są proste: czekaj, aż zapali się dioda sygnałowa i naciśnij swój przycisk szybciej niż przeciwnik. Kto pierwszy zapali wszystkie swoje diody, wygrywa!

#define LED_GAME 2
#define BUZZER 3
#define BTN1 4
#define BTN2 5
#define BTN_RESET 6

int diodyGracz1[5] = {7, 8, 9, 10, 11};
int diodyGracz2[5] = {A0, A1, A2, A3, A4};

int punkty1 = 0;
int punkty2 = 0;
const int CEL = 5;

void setup() {
  pinMode(LED_GAME, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  pinMode(BTN1, INPUT_PULLUP);
  pinMode(BTN2, INPUT_PULLUP);
  pinMode(BTN_RESET, INPUT_PULLUP);

  for (int i = 0; i < 5; i++) {
    pinMode(diodyGracz1[i], OUTPUT);
    pinMode(diodyGracz2[i], OUTPUT);
  }

  randomSeed(analogRead(A3)); // dla losowości

  Serial.begin(9600);
  Serial.println("🎮 Gra refleksu start!");
  Serial.println("Pierwszy do 5 punktów wygrywa!");
  aktualizujDiody();
}

void loop() {
  // --- Obsługa przycisku resetu ---
  if (digitalRead(BTN_RESET) == LOW) {
    delay(150);
    if (digitalRead(BTN_RESET) == LOW) {
      resetGry();
      return;
    }
  }

  // --- Sprawdź zwycięstwo ---
  if (punkty1 >= CEL || punkty2 >= CEL) {
    zwyciestwo();
    return;
  }

  // --- Start nowej rundy ---
  sygnalStartu();
  digitalWrite(LED_GAME, LOW);

  // --- Losowe opóźnienie 1–5 s ---
  int czasCzekania = random(1000, 5000);
  unsigned long startCzekania = millis();
  bool przedwczesne = false;

  while (millis() - startCzekania < czasCzekania) {
    if (digitalRead(BTN1) == LOW) {
      kara(1);
      przedwczesne = true;
      break;
    }
    if (digitalRead(BTN2) == LOW) {
      kara(2);
      przedwczesne = true;
      break;
    }
    if (digitalRead(BTN_RESET) == LOW) { resetGry(); return; }
  }

  if (przedwczesne) {
    delay(1500);
    return;
  }

  // --- Zapal diodę i mierz czas reakcji ---
  digitalWrite(LED_GAME, HIGH);
  unsigned long czasZapalenia = millis();
  bool koniecRundy = false;
  unsigned long limit = 3000; // 3 sekundy na reakcję

  while (!koniecRundy && millis() - czasZapalenia < limit) {
    if (digitalRead(BTN1) == LOW) {
      delay(80); // debounce
      if (digitalRead(BTN1) == LOW) {
        reakcja(1, czasZapalenia);
        koniecRundy = true;
      }
    }
    if (digitalRead(BTN2) == LOW) {
      delay(80);
      if (digitalRead(BTN2) == LOW) {
        reakcja(2, czasZapalenia);
        koniecRundy = true;
      }
    }
    if (digitalRead(BTN_RESET) == LOW) { resetGry(); return; }
  }

  if (!koniecRundy) {
    Serial.println("⏱️ Nikt nie zareagował na czas!");
  }

  digitalWrite(LED_GAME, LOW);
  delay(1000);
}

// --- Reakcja gracza ---
void reakcja(int gracz, unsigned long czasZapalenia) {
  unsigned long czasReakcji = millis() - czasZapalenia;
  if (gracz == 1) punkty1++;
  else punkty2++;

  dzwiekWygranej();
  aktualizujDiody();

  Serial.print("⚡ Gracz ");
  Serial.print(gracz);
  Serial.print(" punkt! Czas reakcji: ");
  Serial.print(czasReakcji);
  Serial.println(" ms");
  Serial.print("Wynik: ");
  Serial.print(punkty1);
  Serial.print(" - ");
  Serial.println(punkty2);
}

// --- Aktualizacja diod punktowych ---
void aktualizujDiody() {
  for (int i = 0; i < 5; i++) {
    digitalWrite(diodyGracz1[i], (i < punkty1) ? HIGH : LOW);
    digitalWrite(diodyGracz2[i], (i < punkty2) ? HIGH : LOW);
  }
}

// --- Dźwięk wygranej rundy ---
void dzwiekWygranej() {
  tone(BUZZER, 1000, 200);
  delay(250);
  noTone(BUZZER);
}

// --- Dźwięk kary i odejmowanie punktu ---
void kara(int gracz) {
  tone(BUZZER, 300, 400);
  delay(500);
  noTone(BUZZER);

  if (gracz == 1 && punkty1 > 0) punkty1--;
  if (gracz == 2 && punkty2 > 0) punkty2--;

  aktualizujDiody();

  Serial.print("❌ Gracz ");
  Serial.print(gracz);
  Serial.println(" za szybki! Traci 1 punkt.");
  Serial.print("Aktualny wynik: ");
  Serial.print(punkty1);
  Serial.print(" - ");
  Serial.println(punkty2);
}

// --- Sygnalizacja startu rundy ---
void sygnalStartu() {
  tone(BUZZER, 600, 100);
  delay(150);
  tone(BUZZER, 800, 100);
  delay(150);
  noTone(BUZZER);
}

// --- Miganie zestawu diod ---
void migajDiody(int diody[], int liczba, int czas) {
  for (int i = 0; i < liczba; i++) digitalWrite(diody[i], HIGH);
  delay(czas);
  for (int i = 0; i < liczba; i++) digitalWrite(diody[i], LOW);
  delay(czas);
}

// --- Fanfary zwycięstwa z migającymi diodami ---
void zwyciestwo() {
  bool gracz1Wygral = (punkty1 >= CEL);

  if (gracz1Wygral)
    Serial.println("🏆 Gracz 1 WYGRYWA GRĘ!");
  else
    Serial.println("🏆 Gracz 2 WYGRYWA GRĘ!");

  int* diodyWygranego = gracz1Wygral ? diodyGracz1 : diodyGracz2;

  for (int i = 0; i < 3; i++) {
    tone(BUZZER, 800, 200);
    migajDiody(diodyWygranego, 5, 200);
    delay(100);

    tone(BUZZER, 1000, 200);
    migajDiody(diodyWygranego, 5, 200);
    delay(100);

    tone(BUZZER, 1200, 300);
    migajDiody(diodyWygranego, 5, 300);
    delay(200);
  }

  noTone(BUZZER);
  resetGry();
}

// --- Reset gry ---
void resetGry() {
  punkty1 = 0;
  punkty2 = 0;
  digitalWrite(LED_GAME, LOW);
  noTone(BUZZER);
  aktualizujDiody();
  Serial.println("🔁 Gra zresetowana. Nowa runda zaczyna się...");
  delay(1500);
}
  

Jak działa gra?

Po włączeniu Arduino obie strony przygotowują się do pojedynku. Program losowo odlicza czas od 1 do 5 sekund, po czym zapala diodę LED_GAME. Wtedy gracze jak najszybciej naciskają swoje przyciski BTN1BTN2. Szybszy zdobywa punkt i jego dioda się zapala. Jeśli ktoś zareaguje zbyt wcześnie — traci punkt! Gdy któryś z graczy ma już 5 zapalonych diod, gra ogłasza zwycięzcę fanfarą z buzzera i błyskającym światłem.

Ciekawostka 1: Tablice diodyGracz1[]diodyGracz2[] pozwalają łatwo sterować wieloma diodami w pętli for() — to bardzo praktyczne i oszczędza mnóstwo kodu!
Ciekawostka 2: Dzięki funkcji randomSeed(analogRead(A3)) Arduino potrafi losować różne czasy startu – to trochę jak rzucanie cyfrową kostką!
Ciekawostka 3: Funkcja millis() mierzy czas od uruchomienia programu w milisekundach, więc Arduino potrafi dokładnie obliczyć, kto zareagował szybciej.
⚠️ Uwaga 1: Wszystkie diody powinny mieć rezystory 220–330 Ω, aby się nie spaliły.
⚠️ Uwaga 2: Jeśli po naciśnięciu przycisku gra reaguje odwrotnie, zmień tryb wejść z INPUT_PULLUP na INPUT i dodaj rezystory do masy.
⚠️ Uwaga 3: Po zakończeniu gry możesz rozpocząć nową rundę, naciskając przycisk RESET.
Dla dociekliwych 1: Spróbuj zmienić wartość CEL z 5 na 3 – wtedy gra będzie krótsza, ale bardziej emocjonująca!
Dla dociekliwych 2: Możesz dodać wyświetlacz LCD, który pokaże aktualny wynik i czas reakcji graczy.
Dla dociekliwych 3: Wykorzystaj dwa różne kolory diod w kolorach switchy (np. czerwone i zielone), żeby łatwiej rozróżniać graczy.

Podsumowanie

Ta gra to świetny sposób, by poćwiczyć refleks i nauczyć się programowania w praktyce! Dzięki diodom i buzzerowi zobaczysz i usłyszysz efekty swoich działań. A może spróbujesz dodać jeszcze więcej graczy?

Zadanie 1: Dodaj licznik dźwiękowy przed startem (np. trzy krótkie „bipy” z buzzera), żeby gra była bardziej emocjonująca!
Zadanie 2: Zrób tryb „nauki refleksu” – w nim gra działa tylko dla jednego gracza i mierzy jego czas reakcji.
⚙️ Informacja techniczna: Zastosowanie tablic i pętli for() sprawia, że kod działa szybciej i jest łatwiejszy do zmiany – wystarczy zmienić liczbę diod w tablicy, a gra sama dopasuje się do nowych ustawień!

Brak komentarzy:

Prześlij komentarz