#include <FastLED.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
// ================= LED =================
#define LED_PIN 14
#define NUM_LEDS 20
CRGB leds[NUM_LEDS];
// ================= BUZZER =================
#define BUZZER_PIN 7
unsigned long buzzerStart = 0;
bool buzzerActive = false;
// ================= BUTTONS =================
const int playerBtns[4] = {36, 37, 38, 39};
const int startBtn = 35;
bool lastPlayerBtn[4] = {HIGH, HIGH, HIGH, HIGH};
bool lastStartBtn = HIGH;
// DEBOUNCE
unsigned long lastDebounceTime[4] = {0, 0, 0, 0};
bool debouncedPlayerBtn[4] = {HIGH, HIGH, HIGH, HIGH};
unsigned long lastStartDebounceTime = 0;
bool debouncedStartBtn = HIGH;
const unsigned long debounceDelay = 30;
// ================= TFT =================
Adafruit_ILI9341 tft1(15, 21, 20, 18, 4, -1);
Adafruit_ILI9341 tft2(5, 19, 11, 40, 16, -1);
Adafruit_ILI9341 tft3(2, 42, 10, 12, 17, -1);
Adafruit_ILI9341 tft4(8, 9, 13, 7, 4, -1);
Adafruit_ILI9341* tfts[4] = {&tft1, &tft2, &tft3, &tft4};
// ================= GAME =================
const int playerLed[4] = {4, 9, 14, 19};
int scores[4] = {0, 0, 0, 0};
// Oyun bitiş kontrol değişkenleri
bool showingResults = false;
unsigned long resultsStartTime = 0;
const unsigned long RESULTS_DURATION = 5000; // 5 saniye yapalım daha iyi görelim
int winnerIndex = -1;
int maxScore = 0;
// ================= GERİ SAYIM SİSTEMİ =================
enum CountdownState {
COUNTDOWN_IDLE,
COUNTDOWN_ANIM_3,
COUNTDOWN_ANIM_2,
COUNTDOWN_ANIM_1,
COUNTDOWN_ANIM_GO,
COUNTDOWN_DONE
};
CountdownState countdownState = COUNTDOWN_IDLE;
unsigned long countdownStartTime = 0;
const unsigned long COUNTDOWN_ANIMATION_DURATION = 1500;
// Kazanan LED grupları
const int winnerLedGroups[4][5] = {
{0, 1, 2, 3, 4},
{5, 6, 7, 8, 9},
{10, 11, 12, 13, 14},
{15, 16, 17, 18, 19}
};
struct PlayerFeedback {
bool active;
unsigned long startTime;
String text;
CRGB color;
bool isPositive;
};
PlayerFeedback playerFeedbacks[4] = {
{false, 0, "", CRGB::Black, false},
{false, 0, "", CRGB::Black, false},
{false, 0, "", CRGB::Black, false},
{false, 0, "", CRGB::Black, false}
};
// Oyun kontrol
int currentLedIndex = 0;
int currentRound = 0;
bool gameStarted = false;
bool gameEnded = false;
unsigned long ledTimer = 0;
// LED zamanlama
unsigned long nextLedChangeTime = 0;
int currentActiveLed = -1;
// Ekran güncelleme kontrolü
bool screenUpdateNeeded[4] = {false, false, false, false};
unsigned long lastScreenUpdate[4] = {0, 0, 0, 0};
const unsigned long SCREEN_UPDATE_INTERVAL = 16;
// ----------------- Tur Dizileri -----------------
const int round1[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,0,1,2,3,13,14,15,16,17,18,19};
const int round2[] = {0,1,2,5,6,7,8,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,10,11,12,13,18,19};
const int round3[] = {0,1,5,6,7,8,2,3,4,5,6,7,15,16,17,18,8,9,10,11,12,13,14,15,16,17,18,19};
const int round4[] = {0,1,2,3,9,5,6,7,8,19,10,11,12,13,4,15,16,17,18,14};
const int round5[] = {0,1,2,3,5,6,7,8,10,11,12,13,14,15,12,13,14,15,16,17,18,19,17,18,19};
const int round6[] = {0,1,2,3,4,5,2,3,4,5,6,7,8,9,10,11,12,7,8,10,11,12,13,15,16,17,18,19};
const int round7[] = {0,1,2,3,4,5,6,7,7,8,9,10,11,12,12,13,14,15,16,17,18,19};
const int round8[] = {0,1,2,2,3,4,5,6,7,8,9,10,11,12,12,13,14,15,16,17,18,19};
const int* roundSequences[8] = {round1, round2, round3, round4, round5, round6, round7, round8};
const int roundLengths[8] = {24, 26, 28, 20, 25, 28, 22, 22};
const int roundDelays[8] = {1000, 750, 500, 500, 1000, 750, 500, 250};
// ================= BASİT LED FONKSİYONLARI =================
void clearAllLeds() {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Black;
}
FastLED.show();
}
// ================= ÇALIŞTIĞINI BİLDİĞİMİZ ANİMASYON =================
void animWinnerSimple() {
static unsigned long lastBlinkTime = 0;
static bool ledsOn = false;
// DEBUG: Durumu kontrol et
Serial.print("animWinnerSimple: showingResults=");
Serial.print(showingResults);
Serial.print(", winnerIndex=");
Serial.println(winnerIndex);
if (!showingResults || winnerIndex == -1) {
Serial.println(" -> Çıkıyor: showingResults false veya winnerIndex -1");
return;
}
// Her 500ms'de bir
if (millis() - lastBlinkTime >= 500) {
lastBlinkTime = millis();
ledsOn = !ledsOn;
Serial.print(" Yanıp sönme: ");
Serial.println(ledsOn ? "AÇIK" : "KAPALI");
if (ledsOn) {
// AÇIK: Tüm LED'ler kırmızı
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Red;
}
// Kazananın LED'leri yeşil
for (int i = 0; i < 5; i++) {
int ledPos = winnerLedGroups[winnerIndex][i];
if (ledPos >= 0 && ledPos < NUM_LEDS) {
leds[ledPos] = CRGB::Green;
}
}
} else {
// KAPALI: Tüm LED'ler siyah
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Black;
}
}
FastLED.show();
}
}
// ================= GERİ SAYIM ANİMASYONLARI =================
void animCountdown3() {
static unsigned long lastBlinkTime = 0;
static bool ledsOn = false;
if (millis() - lastBlinkTime >= 250) {
lastBlinkTime = millis();
ledsOn = !ledsOn;
if (ledsOn) {
for (int i = 0; i < NUM_LEDS; i++) leds[i] = CRGB::Red;
} else {
clearAllLeds();
}
FastLED.show();
}
}
void animCountdown2() {
static unsigned long lastBlinkTime = 0;
static bool ledsOn = false;
if (millis() - lastBlinkTime >= 250) {
lastBlinkTime = millis();
ledsOn = !ledsOn;
if (ledsOn) {
for (int i = 0; i < NUM_LEDS; i++) leds[i] = CRGB::Yellow;
} else {
clearAllLeds();
}
FastLED.show();
}
}
void animCountdown1() {
static unsigned long lastBlinkTime = 0;
static bool ledsOn = false;
if (millis() - lastBlinkTime >= 250) {
lastBlinkTime = millis();
ledsOn = !ledsOn;
if (ledsOn) {
for (int i = 0; i < NUM_LEDS; i++) leds[i] = CRGB::Green;
} else {
clearAllLeds();
}
FastLED.show();
}
}
void animCountdownGO() {
static unsigned long lastBlinkTime = 0;
static bool ledsOn = false;
if (millis() - lastBlinkTime >= 250) {
lastBlinkTime = millis();
ledsOn = !ledsOn;
if (ledsOn) {
for (int i = 0; i < NUM_LEDS; i++) leds[i] = CRGB::Blue;
} else {
clearAllLeds();
}
FastLED.show();
}
}
// ================= İDLE ANİMASYONU =================
void runIdleAnimation() {
static unsigned long lastIdleTime = 0;
static int idlePosition = 0;
const unsigned long IDLE_SPEED = 50;
if (millis() - lastIdleTime >= IDLE_SPEED) {
lastIdleTime = millis();
clearAllLeds();
for (int i = 0; i < 7; i++) {
int pos = (idlePosition + i) % NUM_LEDS;
int brightness = 255 - (i * 40);
if (brightness < 50) brightness = 50;
leds[pos] = CRGB(brightness, 0, 0);
}
FastLED.show();
idlePosition = (idlePosition + 1) % NUM_LEDS;
}
}
// ================= BERABERE ANİMASYONU =================
void animTie() {
static unsigned long lastBlinkTime = 0;
static bool ledsOn = false;
if (millis() - lastBlinkTime >= 300) {
lastBlinkTime = millis();
ledsOn = !ledsOn;
if (ledsOn) {
for (int i = 0; i < NUM_LEDS; i++) leds[i] = CRGB::Yellow;
} else {
clearAllLeds();
}
FastLED.show();
}
}
// ================= GERİ SAYIM EKRAN FONKSİYONLARI =================
void drawCountdownNumber(int player, int number) {
uint16_t bgColor;
switch(number) {
case 3: bgColor = ILI9341_RED; break;
case 2: bgColor = ILI9341_YELLOW; break;
case 1: bgColor = ILI9341_GREEN; break;
case 0: bgColor = ILI9341_BLUE; break;
default: bgColor = ILI9341_BLACK;
}
tfts[player]->fillRect(0, 0, 240, 320, bgColor);
String numText = (number == 0) ? "GO!" : String(number);
tfts[player]->setTextSize(20);
tfts[player]->setTextColor(ILI9341_BLACK);
int16_t x1, y1;
uint16_t w, h;
tfts[player]->getTextBounds(numText, 0, 0, &x1, &y1, &w, &h);
int centerX = (240 - w) / 2;
int centerY = (320 - h) / 2;
tfts[player]->setCursor(centerX, centerY);
tfts[player]->print(numText);
lastScreenUpdate[player] = millis();
screenUpdateNeeded[player] = false;
}
void startCountdownAnimation() {
Serial.println("=== GERİ SAYIM BAŞLIYOR ===");
countdownState = COUNTDOWN_ANIM_3;
countdownStartTime = millis();
for (int i = 0; i < 4; i++) {
screenUpdateNeeded[i] = true;
}
clearAllLeds();
tone(BUZZER_PIN, 1500, 300);
buzzerStart = millis();
buzzerActive = true;
}
void updateCountdownAnimation() {
if (countdownState == COUNTDOWN_IDLE || countdownState == COUNTDOWN_DONE) return;
unsigned long elapsedTime = millis() - countdownStartTime;
if (elapsedTime >= COUNTDOWN_ANIMATION_DURATION) {
switch(countdownState) {
case COUNTDOWN_ANIM_3:
Serial.println("=== GERİ SAYIM: 2 ===");
countdownState = COUNTDOWN_ANIM_2;
countdownStartTime = millis();
clearAllLeds();
tone(BUZZER_PIN, 1600, 250);
buzzerStart = millis();
buzzerActive = true;
break;
case COUNTDOWN_ANIM_2:
Serial.println("=== GERİ SAYIM: 1 ===");
countdownState = COUNTDOWN_ANIM_1;
countdownStartTime = millis();
clearAllLeds();
tone(BUZZER_PIN, 1700, 250);
buzzerStart = millis();
buzzerActive = true;
break;
case COUNTDOWN_ANIM_1:
Serial.println("=== GERİ SAYIM: GO! ===");
countdownState = COUNTDOWN_ANIM_GO;
countdownStartTime = millis();
clearAllLeds();
tone(BUZZER_PIN, 1800, 250);
buzzerStart = millis();
buzzerActive = true;
break;
case COUNTDOWN_ANIM_GO:
Serial.println("=== OYUN BAŞLIYOR! ===");
countdownState = COUNTDOWN_DONE;
for (int i = 0; i < 4; i++) {
tfts[i]->fillRect(0, 0, 240, 320, ILI9341_BLACK);
}
clearAllLeds();
delay(200);
startActualGame();
return;
}
for (int i = 0; i < 4; i++) {
screenUpdateNeeded[i] = true;
}
}
}
// ================= EKRAN FONKSİYONLARI (BASİT) =================
void drawWinnerScreen(int player) {
tfts[player]->fillRect(0, 0, 240, 320, ILI9341_GREEN);
tfts[player]->setTextSize(7);
tfts[player]->setTextColor(0x104050);
String youText = "YOU";
int16_t x1, y1;
uint16_t w, h;
tfts[player]->getTextBounds(youText, 0, 0, &x1, &y1, &w, &h);
int youX = (240 - w) / 2;
tfts[player]->setCursor(youX, 82);
tfts[player]->print(youText);
String winText = "WIN";
tfts[player]->getTextBounds(winText, 0, 0, &x1, &y1, &w, &h);
int winX = (240 - w) / 2;
tfts[player]->setCursor(winX, 162);
tfts[player]->print(winText);
String scoreStr = String(scores[player]);
tfts[player]->setTextSize(5);
tfts[player]->setTextColor(ILI9341_RED);
tfts[player]->getTextBounds(scoreStr, 0, 0, &x1, &y1, &w, &h);
int scoreX = (240 - w) / 2;
tfts[player]->setCursor(scoreX, 240);
tfts[player]->print(scoreStr);
}
void drawLoserScreen(int player) {
tfts[player]->fillRect(0, 0, 240, 320, ILI9341_RED);
tfts[player]->setTextSize(7);
tfts[player]->setTextColor(0x104050);
String gameText = "GAME";
int16_t x1, y1;
uint16_t w, h;
tfts[player]->getTextBounds(gameText, 0, 0, &x1, &y1, &w, &h);
int gameX = (240 - w) / 2;
tfts[player]->setCursor(gameX, 82);
tfts[player]->print(gameText);
String overText = "OVER";
tfts[player]->getTextBounds(overText, 0, 0, &x1, &y1, &w, &h);
int overX = (240 - w) / 2;
tfts[player]->setCursor(overX, 162);
tfts[player]->print(overText);
String scoreStr = String(scores[player]);
tfts[player]->setTextSize(5);
tfts[player]->setTextColor(ILI9341_YELLOW);
tfts[player]->getTextBounds(scoreStr, 0, 0, &x1, &y1, &w, &h);
int scoreX = (240 - w) / 2;
tfts[player]->setCursor(scoreX, 265);
tfts[player]->print(scoreStr);
}
void drawIdleScreenFast(int player) {
tfts[player]->fillRect(0, 0, 240, 320, 0x780F78);
String playerText = "PLAYER";
tfts[player]->setTextSize(5);
int16_t x1, y1;
uint16_t w, h;
tfts[player]->getTextBounds(playerText, 0, 0, &x1, &y1, &w, &h);
int playerTextX = (240 - w) / 2;
tfts[player]->setTextColor(ILI9341_RED);
tfts[player]->setCursor(playerTextX, 60);
tfts[player]->print(playerText);
String playerNum = String(player + 1);
tfts[player]->setTextSize(14);
tfts[player]->getTextBounds(playerNum, 0, 0, &x1, &y1, &w, &h);
int playerNumX = (240 - w) / 2;
int playerNumY = 160;
tfts[player]->setTextColor(0x104050);
tfts[player]->setCursor(playerNumX, playerNumY);
tfts[player]->print(playerNum);
screenUpdateNeeded[player] = false;
}
void drawGameScreen(int player) {
if (playerFeedbacks[player].active) {
if (playerFeedbacks[player].isPositive) {
tfts[player]->fillRect(0, 0, 240, 320, 0x780F78);
String text = playerFeedbacks[player].text;
tfts[player]->setTextSize(8);
int16_t x1, y1;
uint16_t w, h;
tfts[player]->getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
int centerX = (240 - w) / 2;
int centerY = (320 - h) / 2;
tfts[player]->setTextColor(0x104050);
tfts[player]->setCursor(centerX, centerY);
tfts[player]->print(text);
} else {
tfts[player]->fillRect(0, 0, 240, 320, ILI9341_RED);
String text = playerFeedbacks[player].text;
tfts[player]->setTextSize(10);
int16_t x1, y1;
uint16_t w, h;
tfts[player]->getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
int centerX = (240 - w) / 2;
int centerY = (320 - h) / 2;
tfts[player]->setTextColor(0x104050);
tfts[player]->setCursor(centerX, centerY);
tfts[player]->print(text);
}
} else {
tfts[player]->fillRect(0, 0, 240, 320, 0xFD20);
String scoreText = "SCORE";
tfts[player]->setTextSize(6);
int16_t x1, y1;
uint16_t w, h;
tfts[player]->getTextBounds(scoreText, 0, 0, &x1, &y1, &w, &h);
int scoreTitleX = (240 - w) / 2;
tfts[player]->setCursor(scoreTitleX, 40);
tfts[player]->setTextColor(ILI9341_YELLOW);
tfts[player]->print(scoreText);
String scoreStr = String(scores[player]);
tfts[player]->setTextSize(9);
tfts[player]->getTextBounds(scoreStr, 0, 0, &x1, &y1, &w, &h);
int scoreX = (240 - w) / 2;
int scoreY = 140;
tfts[player]->fillRect(scoreX - 5, scoreY - 5, w + 10, h + 10, 0xFD20);
tfts[player]->setCursor(scoreX, scoreY);
tfts[player]->setTextColor(ILI9341_RED);
tfts[player]->print(scoreStr);
}
}
void updateScreens() {
for (int i = 0; i < 4; i++) {
if (screenUpdateNeeded[i] && (millis() - lastScreenUpdate[i] >= SCREEN_UPDATE_INTERVAL)) {
if (countdownState != COUNTDOWN_IDLE && countdownState != COUNTDOWN_DONE) {
switch(countdownState) {
case COUNTDOWN_ANIM_3: drawCountdownNumber(i, 3); break;
case COUNTDOWN_ANIM_2: drawCountdownNumber(i, 2); break;
case COUNTDOWN_ANIM_1: drawCountdownNumber(i, 1); break;
case COUNTDOWN_ANIM_GO: drawCountdownNumber(i, 0); break;
}
} else if (showingResults) {
if (i == winnerIndex) {
drawWinnerScreen(i);
} else {
drawLoserScreen(i);
}
} else if (!gameStarted) {
drawIdleScreenFast(i);
} else {
drawGameScreen(i);
}
lastScreenUpdate[i] = millis();
screenUpdateNeeded[i] = false;
}
}
}
// ================= OYUN FONKSİYONLARI =================
void updateLeds() {
if (!gameStarted) return;
if (millis() >= nextLedChangeTime) {
if (currentActiveLed >= 0) {
leds[currentActiveLed] = CRGB::Black;
}
currentActiveLed = roundSequences[currentRound][currentLedIndex];
leds[currentActiveLed] = CRGB::Red;
FastLED.show();
for (int i = 0; i < 4; i++) {
if (currentActiveLed == playerLed[i]) {
tone(BUZZER_PIN, 1500, 150);
buzzerStart = millis();
buzzerActive = true;
}
}
nextLedChangeTime = millis() + roundDelays[currentRound];
ledTimer = millis();
currentLedIndex++;
if (currentLedIndex >= roundLengths[currentRound]) {
currentLedIndex = 0;
currentRound++;
if (currentRound >= 8) {
endGame();
return;
}
}
}
}
void startActualGame() {
Serial.println("=== OYUN BAŞLADI ===");
gameStarted = true;
gameEnded = false;
showingResults = false;
currentRound = 0;
currentLedIndex = 0;
currentActiveLed = -1;
nextLedChangeTime = millis();
for (int i = 0; i < 4; i++) {
scores[i] = 0;
playerFeedbacks[i].active = false;
screenUpdateNeeded[i] = true;
}
clearAllLeds();
for (int i = 0; i < 4; i++) {
leds[playerLed[i]] = CRGB::Blue;
FastLED.show();
tone(BUZZER_PIN, 1200 + i * 200, 60);
buzzerStart = millis();
buzzerActive = true;
delay(30);
leds[playerLed[i]] = CRGB::Black;
FastLED.show();
delay(10);
}
tone(BUZZER_PIN, 1800, 200);
buzzerStart = millis();
buzzerActive = true;
}
void processPlayerInput(int player) {
bool reading = digitalRead(playerBtns[player]);
if (reading != lastPlayerBtn[player]) {
lastDebounceTime[player] = millis();
}
if ((millis() - lastDebounceTime[player]) > debounceDelay) {
if (reading != debouncedPlayerBtn[player]) {
debouncedPlayerBtn[player] = reading;
if (debouncedPlayerBtn[player] == LOW) {
unsigned long pressTime = millis();
bool isValid = false;
if (currentActiveLed >= 0) {
unsigned long timeSinceLedOn = pressTime - ledTimer;
if (timeSinceLedOn > 50 && timeSinceLedOn < (roundDelays[currentRound] * 0.9)) {
if (currentActiveLed == playerLed[player]) {
isValid = true;
}
}
}
if (isValid) {
scores[player] += 100;
playerFeedbacks[player].active = true;
playerFeedbacks[player].startTime = pressTime;
playerFeedbacks[player].text = "+100";
playerFeedbacks[player].color = CRGB::Green;
playerFeedbacks[player].isPositive = true;
tone(BUZZER_PIN, 2500, 100);
buzzerStart = millis();
buzzerActive = true;
} else {
scores[player] = max(0, scores[player] - 50);
playerFeedbacks[player].active = true;
playerFeedbacks[player].startTime = pressTime;
playerFeedbacks[player].text = "-50";
playerFeedbacks[player].color = CRGB::Purple;
playerFeedbacks[player].isPositive = false;
tone(BUZZER_PIN, 800, 150);
buzzerStart = millis();
buzzerActive = true;
}
screenUpdateNeeded[player] = true;
}
}
}
lastPlayerBtn[player] = reading;
}
void checkPlayerButtons() {
if (!gameStarted) return;
for (int i = 0; i < 4; i++) {
processPlayerInput(i);
}
}
void updatePlayerFeedbacks() {
for (int i = 0; i < 4; i++) {
if (playerFeedbacks[i].active && millis() - playerFeedbacks[i].startTime >= 1000) {
playerFeedbacks[i].active = false;
screenUpdateNeeded[i] = true;
}
}
}
void checkStartButton() {
bool reading = digitalRead(startBtn);
if (reading != lastStartBtn) {
lastStartDebounceTime = millis();
}
if ((millis() - lastStartDebounceTime) > debounceDelay) {
if (reading != debouncedStartBtn) {
debouncedStartBtn = reading;
if (debouncedStartBtn == LOW && !gameStarted && !gameEnded && countdownState == COUNTDOWN_IDLE && !showingResults) {
startCountdownAnimation();
}
}
}
lastStartBtn = reading;
}
// ================= ÇOK ÖNEMLİ: OYUN SONU FONKSİYONU =================
void endGame() {
Serial.println("\n=== OYUN SONU FONKSİYONU ÇALIŞIYOR ===");
gameStarted = false;
gameEnded = false;
maxScore = 0;
winnerIndex = -1;
// Skorları yazdır
Serial.println("Skorlar:");
for (int i = 0; i < 4; i++) {
Serial.print("Oyuncu ");
Serial.print(i);
Serial.print(": ");
Serial.println(scores[i]);
}
// Kazananı bul
for (int i = 0; i < 4; i++) {
if (scores[i] > maxScore) {
maxScore = scores[i];
winnerIndex = i;
}
}
// Berabere kontrolü
int winnerCount = 0;
for (int i = 0; i < 4; i++) {
if (scores[i] == maxScore) {
winnerCount++;
}
}
if (winnerCount > 1) {
winnerIndex = -1;
Serial.println("Sonuç: BERABERE!");
} else {
Serial.print("Sonuç: Oyuncu ");
Serial.print(winnerIndex);
Serial.print(" KAZANDI! Puan: ");
Serial.println(maxScore);
}
// BU ÇOK ÖNEMLİ: showingResults'u TRUE yap
showingResults = true;
resultsStartTime = millis();
Serial.print("showingResults: ");
Serial.println(showingResults);
Serial.print("winnerIndex: ");
Serial.println(winnerIndex);
// Ekranları güncelle
for (int i = 0; i < 4; i++) {
screenUpdateNeeded[i] = true;
}
// LED'leri temizle ve başlangıç durumunu ayarla
clearAllLeds();
if (winnerIndex != -1) {
// İlk durum: AÇIK
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Red;
}
for (int i = 0; i < 5; i++) {
int ledPos = winnerLedGroups[winnerIndex][i];
if (ledPos >= 0 && ledPos < NUM_LEDS) {
leds[ledPos] = CRGB::Green;
}
}
FastLED.show();
tone(BUZZER_PIN, 3000, 500);
buzzerStart = millis();
buzzerActive = true;
Serial.println("Başlangıç LED'leri AÇIK ayarlandı");
} else {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Yellow;
}
FastLED.show();
tone(BUZZER_PIN, 1000, 500);
buzzerStart = millis();
buzzerActive = true;
}
Serial.println("=== OYUN SONU FONKSİYONU BİTTİ ===");
}
void checkResultsTimeout() {
if (showingResults && millis() - resultsStartTime >= RESULTS_DURATION) {
Serial.println("=== SONUÇ SÜRESİ DOLDU ===");
showingResults = false;
gameStarted = false;
gameEnded = false;
countdownState = COUNTDOWN_IDLE;
for (int i = 0; i < 4; i++) {
scores[i] = 0;
playerFeedbacks[i].active = false;
}
for (int i = 0; i < 4; i++) {
drawIdleScreenFast(i);
}
clearAllLeds();
noTone(BUZZER_PIN);
Serial.println("IDLE moduna dönüldü");
Serial.println("START tuşuna basarak tekrar oynayın");
}
}
void updateBuzzer() {
if (buzzerActive && millis() - buzzerStart >= 200) {
noTone(BUZZER_PIN);
buzzerActive = false;
}
}
// ================= SETUP =================
void setup() {
Serial.begin(115200);
Serial.println("=== SİSTEM BAŞLATILIYOR ===");
FastLED.addLeds<WS2811, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(255);
clearAllLeds();
pinMode(BUZZER_PIN, OUTPUT);
pinMode(startBtn, INPUT_PULLUP);
for (int i = 0; i < 4; i++) {
pinMode(playerBtns[i], INPUT_PULLUP);
}
tft1.begin(); tft2.begin(); tft3.begin(); tft4.begin();
for (int i = 0; i < 4; i++) {
tfts[i]->setRotation(0);
drawIdleScreenFast(i);
}
delay(1000);
// Kısa bir test
Serial.println("\n=== KISA TEST ===");
Serial.println("LED'ler 3 kez yanıp sönecek...");
for (int i = 0; i < 3; i++) {
Serial.print("Test ");
Serial.println(i);
// Tüm LED'leri beyaz yap
for (int j = 0; j < NUM_LEDS; j++) {
leds[j] = CRGB::White;
}
FastLED.show();
delay(300);
// Tüm LED'leri söndür
clearAllLeds();
delay(300);
}
Serial.println("=== SİSTEM HAZIR ===");
Serial.println("START tuşuna basın");
}
// ================= LOOP =================
void loop() {
// Serial debug
static unsigned long lastDebugTime = 0;
if (millis() - lastDebugTime >= 1000) {
lastDebugTime = millis();
Serial.print("Durum: gameStarted=");
Serial.print(gameStarted);
Serial.print(", showingResults=");
Serial.print(showingResults);
Serial.print(", winnerIndex=");
Serial.print(winnerIndex);
Serial.print(", countdownState=");
Serial.println(countdownState);
}
checkStartButton();
if (countdownState != COUNTDOWN_IDLE && countdownState != COUNTDOWN_DONE) {
updateCountdownAnimation();
switch(countdownState) {
case COUNTDOWN_ANIM_3: animCountdown3(); break;
case COUNTDOWN_ANIM_2: animCountdown2(); break;
case COUNTDOWN_ANIM_1: animCountdown1(); break;
case COUNTDOWN_ANIM_GO: animCountdownGO(); break;
}
} else if (gameStarted) {
updateLeds();
checkPlayerButtons();
updatePlayerFeedbacks();
} else {
if (showingResults) {
// BURASI ÇOK ÖNEMLİ: animWinnerSimple çalışsın
Serial.println("showingResults TRUE - animWinnerSimple çağrılıyor");
animWinnerSimple();
checkResultsTimeout();
} else {
runIdleAnimation();
}
}
updateBuzzer();
updateScreens();
delay(10);
}