Untitled
unknown
plain_text
10 months ago
20 kB
17
Indexable
/***********************
* LED OYUN SİSTEMİ *
* Mod-1 / Mod-2 / Mod-3
* Pins: KULLANICININ ORİJİNALİYLE AYNI
***********************/
#include <Adafruit_NeoPixel.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
/* ================== Sabitler ================== */
#define LED_ADET 9
#define CENTER_LED_ADET 29
#define TOTAL_MODULES 16
// Buton pinleri (DEĞİŞMEDİ)
int StartButton = 50; // INPUT, basılı=HIGH
int ChangeModeButton = 48; // INPUT, basılı=HIGH
// ESP32 seri (kullanmasan da kalsın)
#define ESP32_SERIAL Serial3
// MAX7219 donanım SPI pinleri (seninle aynı)
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define DATA_PIN 51 // MOSI
#define CLK_PIN 52 // SCK
#define CS_PIN 53 // CS/LOAD
// Oyun modları
int game_mode = 1; // 1..3
/* ================== LED Şerit Tanımı ================== */
struct LEDStrip {
int ledPin; // LED data pini
int sensorPin; // Kapasitif/buton pini (merkezde kullanılmıyor ama pin tutuldu)
Adafruit_NeoPixel *strip; // Şerit nesnesi
};
// Kullanıcının verdiği mapping (aynen korundu)
LEDStrip ledStrips[] = {
// 0..3: P1
{ 27, A2, NULL },
{ 25, A0, NULL },
{ 29, A4, NULL },
{ 31, A6, NULL },
// 4..7: P2
{ 41, A5, NULL },
{ 9, A7, NULL },
{ 21, A3, NULL },
{ 23, A1, NULL },
// 8..11: P3
{ 38, A8, NULL },
{ 36, A10, NULL },
{ 34, A12, NULL },
{ 32, A14, NULL },
// 12..15: P4
{ 3, A15, NULL },
{ 5, A13, NULL },
{ 11, A11, NULL },
{ 13, A9, NULL },
// 16: Merkez (sensör okunmuyor)
{ 43, A14, NULL }
};
const int stripCount = sizeof(ledStrips) / sizeof(ledStrips[0]);
/* ================== MAX7219 ================== */
MD_MAX72XX ekran(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, TOTAL_MODULES);
const uint64_t letters[26] = {
0x0033333f33331e0c,0x003f66663e66663f,0x003c66030303663c,0x001f36666666361f,
0x007f46161e16467f,0x000f06161e16467f,0x007c66730303663c,0x003333333f333333,
0x001e0c0c0c0c0c1e,0x001e333330303078,0x006766361e366667,0x007f66460606060f,
0x0063636b7f7f7763,0x006363737b6f6763,0x001c36636363361c,0x000f06063e66663f,
0x00381e3b3333331e,0x006766363e66663f,0x001e33380e07331e,0x001e0c0c0c0c2d3f,
0x003f333333333333,0x000c1e3333333333,0x0063777f6b636363,0x0063361c1c366363,
0x001e0c0c1e333333,0x007f664c1831637f
};
const uint8_t DIGITS[10][8] = {
{0x3C,0x66,0x6E,0x76,0x66,0x66,0x3C,0x00},
{0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00},
{0x3C,0x66,0x06,0x0C,0x18,0x30,0x7E,0x00},
{0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00},
{0x0C,0x1C,0x3C,0x6C,0x7E,0x0C,0x1E,0x00},
{0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00},
{0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00},
{0x7E,0x66,0x0C,0x18,0x30,0x30,0x30,0x00},
{0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00},
{0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}
};
uint8_t modulRakam[TOTAL_MODULES];
/* ================== Yardımcı Gösterim ================== */
void displayDigitOnModule(uint8_t moduleIndex, uint8_t digit) {
for (uint8_t row = 0; row < 8; row++) {
ekran.setRow(moduleIndex, row, DIGITS[digit][row]);
}
}
uint8_t reverseByte(uint8_t b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
void displayLetterOnModule(uint8_t moduleIndex, char letter) {
if (letter >= 'A' && letter <= 'Z') letter = letter - 'A' + 'a';
if (letter < 'a' || letter > 'z') return;
uint8_t index = letter - 'a';
uint64_t bitmap = letters[index];
for (uint8_t row = 0; row < 8; row++) {
uint8_t rowData = (bitmap >> (row * 8)) & 0xFF;
rowData = reverseByte(rowData);
ekran.setRow(moduleIndex, row, rowData);
}
}
void print_game_name(int number) {
for (int i = 0; i < 4; i++) {
displayLetterOnModule((4 * i) + 3, 'm');
displayLetterOnModule((4 * i) + 2, 'o');
displayLetterOnModule((4 * i) + 1, 'd');
displayDigitOnModule((4 * i) + 0, number);
}
}
void reset_scores_display() {
ekran.clear();
for (uint8_t i = 0; i < TOTAL_MODULES; i++) {
if (i == 0 || i == 3 || i == 4 || i == 7 || i == 8 || i == 11 || i == 12 || i == 15) continue;
modulRakam[i] = 0;
displayDigitOnModule(i, 0);
}
}
void set_score_digit(uint8_t player, uint8_t score){ // tek hane
// senin yerleşimine göre merkez sütunu:
uint8_t mod = (player==0)? 1 : (player==1? 9 : (player==2? 13 : 5));
displayDigitOnModule(mod, score % 10);
}
/* ================== Pin/Sensör ================== */
int kap_deger;
int kapasitifOku(int pin) { // INPUT → basılı = HIGH
if (pin < 0) return 0;
kap_deger = digitalRead(pin);
return kap_deger;
}
void pinMode_active() {
for (int i = 0; i < 16; i++) { // 0..15 sensör; merkez hariç
pinMode(ledStrips[i].sensorPin, INPUT);
}
}
/* ================== LED Yardımcıları ================== */
inline int strip_led_count(int idx){ return (idx==16) ? CENTER_LED_ADET : LED_ADET; }
void led_yak(LEDStrip &s, uint32_t color) {
s.strip->fill(color, 0, LED_ADET);
s.strip->show();
}
void center_led_yak(LEDStrip &s, uint32_t color) {
s.strip->fill(color, 0, CENTER_LED_ADET);
s.strip->show();
}
inline void fillStripIdx(int idx, uint32_t color){
auto s = ledStrips[idx].strip; if (!s) return;
s->fill(color, 0, strip_led_count(idx)); s->show();
}
inline void clearStripIdx(int idx){
auto s = ledStrips[idx].strip; if (!s) return;
s->clear(); s->show();
}
/* ================== Renk Dizileri ================== */
uint32_t colors[8] = {
0xFF0000, 0x00FF00, 0x0000FF, 0x800080,
0xFFFFFF, 0xFFFF00, 0xFF8000, 0xFF0080,
};
// Oyuncu renk sırası
uint32_t player_color[4]{
0x00FF00, // P1 Yeşil
0xFFFF00, // P2 Sarı
0xFF0000, // P3 Kırmızı
0x0000FF // P4 Mavi
};
/* =======================================================
* MOD 1
* ClassicClash (çalışan)
* =======================================================*/
uint32_t button_color[4][4]; // her tur doluyor
void start_ClassicClash() {
int tur_sayisi = 10;
Serial.println("Mod-1: Turlar başlıyor");
int player_display[4][4]{
{ 0, 1, 2, 3 },
{ 8, 9, 10, 11 },
{ 12, 13, 14, 15 },
{ 4, 5, 6, 7 }
};
// ekran reset + geri sayımda dış şerit flash
reset_scores_display();
for (int sayac = 3; sayac >= 0; sayac--) {
for (int i = 0; i < 4; i++) displayDigitOnModule(player_display[i][1], sayac);
if (sayac == 0) continue;
for (int i = 0; i < 16; i++) { led_yak(ledStrips[i], colors[random(8)]); delay(10); }
delay(330);
for (int i = 0; i < 16; i++) { led_yak(ledStrips[i], colors[random(8)]); delay(10); }
delay(330);
for (int i = 0; i < 16; i++) { led_yak(ledStrips[i], colors[random(8)]); delay(10); }
delay(330);
}
int score[4] = { 0, 0, 0, 0 };
for (int tur = 0; tur < tur_sayisi; tur++) {
// 4 benzersiz renk seç
uint32_t rand_four_color[4];
for (int i = 0; i < 4; i++) {
rand_four_color[i] = colors[random(8)];
for (int j = i - 1; j >= 0; j--) { if (rand_four_color[i] == rand_four_color[j]) { i--; break; } }
}
uint32_t center_color = rand_four_color[random(4)];
// pozisyonları karıştır ve ata
int button_position[4][4];
for (int p = 0; p < 4; p++) {
for (int j = 0; j < 4; j++) {
button_position[p][j] = random(4);
for (int k = j - 1; k >= 0; k--) { if (button_position[p][j] == button_position[p][k]) { j--; break; } }
}
}
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
button_color[p][j] = rand_four_color[button_position[p][j]];
// oyuncu LED'lerini yak
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
led_yak(ledStrips[(4 * p) + j], button_color[p][j]);
// merkez pre-roll (20×200ms) → hedef renk
uint32_t rand_renk, prev = 0;
for (int i = 0; i < 20; i++) {
rand_renk = colors[random(8)];
if (rand_renk == prev) { i--; continue; }
center_led_yak(ledStrips[16], rand_renk);
delay(200); prev = rand_renk;
}
center_led_yak(ledStrips[16], center_color);
// oyun döngüsü
int tur_durum = 1;
int winner_player = 8;
int player_end[4] = { 1, 1, 1, 1 };
int herkes_bittimi = 0;
while (tur_durum) {
for (int p = 0; p < 4; p++) {
if (!player_end[p]) continue;
for (int j = 0; j < 4; j++) {
if (kapasitifOku(ledStrips[(4 * p) + j].sensorPin)) {
if (button_color[p][j] == center_color) {
winner_player = p;
player_end[0] = player_end[1] = player_end[2] = player_end[3] = 0;
tur_durum = 0;
score[p]++;
displayDigitOnModule(player_display[p][1], score[p]);
} else {
player_end[p] = 0;
led_yak(ledStrips[(4 * p) + j], 0x000000);
}
herkes_bittimi++;
if (herkes_bittimi > 3) tur_durum = 0;
break;
}
}
}
}
// tur sonu blink (kazanan renk, diğerleri beyaz)
for (int say = 0; say < 5; say++) {
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
led_yak(ledStrips[(4 * p) + j], (p == winner_player) ? player_color[p] : 0xFFFFFF);
delay(500);
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
led_yak(ledStrips[(4 * p) + j], 0x000000);
delay(500);
}
}
// oyun kapanış
int who_win = 0; for (int i = 1; i < 4; i++) if (score[i] > score[who_win]) who_win = i;
for (int say = 0; say < 5; say++) {
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
led_yak(ledStrips[(4 * p) + j], player_color[who_win]);
delay(500);
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
led_yak(ledStrips[(4 * p) + j], 0x000000);
delay(500);
}
print_game_name(game_mode);
}
/* =======================================================
* MOD 2
* ColorSorting (sıra oyunu)
* - Merkez 4 rengi 1.5sn aralıkla gösterir
* - Oyuncu doğru sırayla basar; yanlış yapan elenir
* - Biri doğru bitirirse tur hemen biter
* =======================================================*/
void color_sorting() {
int tur_sayisi = 5;
Serial.println("Mod-2: Turlar başlıyor");
int previous_button_control[4][4] = { 0 };
int player_display[4][4]{
{ 8, 9, 10, 11 },
{ 12, 13, 14, 15 },
{ 4, 5, 6, 7 },
{ 0, 1, 2, 3 }
};
reset_scores_display();
delay(300);
for (int sayac = 3; sayac >= 0; sayac--) {
for (int i = 0; i < 4; i++) displayDigitOnModule(player_display[i][1], sayac);
delay(1000);
}
int score[4] = { 0, 0, 0, 0 };
int color_show_time = 1500;
for (int tur = 0; tur < tur_sayisi; tur++) {
color_show_time = max(400, color_show_time - 200);
// 4 renk seç
uint32_t rand_four_color[4];
for (int i = 0; i < 4; i++) {
rand_four_color[i] = colors[random(8)];
for (int j = i - 1; j >= 0; j--) { if (rand_four_color[i] == rand_four_color[j]) { i--; break; } }
}
// gösterim sırası 0..3
int color_real_sort[4];
for (int i = 0; i < 4; i++) {
color_real_sort[i] = random(4);
for (int k = i - 1; k >= 0; k--) { if (color_real_sort[i] == color_real_sort[k]) { i--; break; } }
}
// buton pozisyonları
int button_position[4][4];
for (int p = 0; p < 4; p++) {
for (int j = 0; j < 4; j++) {
button_position[p][j] = random(4);
for (int k = j - 1; k >= 0; k--) { if (button_position[p][j] == button_position[p][k]) { j--; break; } }
}
}
// renkleri ata ve yak
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
button_color[p][j] = rand_four_color[button_position[p][j]];
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
led_yak(ledStrips[(4 * p) + j], button_color[p][j]);
// merkezde sırayla göster
center_led_yak(ledStrips[16], 0x000000);
delay(800);
for (int i = 0; i < 4; i++) {
center_led_yak(ledStrips[16], rand_four_color[color_real_sort[i]]);
delay(color_show_time);
center_led_yak(ledStrips[16], 0x000000);
delay(200);
}
// oyun: doğru sırayla basma
int tur_durum = 1;
int winner_player = 8;
int player_end[4] = { 1, 1, 1, 1 };
int herkes_bittimi = 0;
int player_sort_control[4] = { 0, 0, 0, 0 };
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
previous_button_control[p][j] = 1;
while (tur_durum) {
for (int p = 0; p < 4; p++) {
if (!player_end[p]) continue;
for (int j = 0; j < 4; j++) {
if (kapasitifOku(ledStrips[(4 * p) + j].sensorPin) && previous_button_control[p][j]) {
previous_button_control[p][j] = 0;
if (button_color[p][j] == rand_four_color[color_real_sort[player_sort_control[p]]]) {
player_sort_control[p]++;
led_yak(ledStrips[(4 * p) + j], 0x000000);
if (player_sort_control[p] == 4) {
winner_player = p;
player_end[0] = player_end[1] = player_end[2] = player_end[3] = 0;
tur_durum = 0;
score[p]++;
displayDigitOnModule(player_display[p][1], score[p]);
}
} else {
for (int a = 0; a < 4; a++) led_yak(ledStrips[(4 * p) + a], 0x000000);
player_end[p] = 0;
herkes_bittimi++;
if (herkes_bittimi > 3) tur_durum = 0;
}
break;
}
}
}
}
// tur sonu blink (kazanan renk vs beyaz)
for (int say = 0; say < 5; say++) {
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
led_yak(ledStrips[(4 * p) + j], (p == winner_player) ? player_color[p] : 0xFFFFFF);
delay(500);
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
led_yak(ledStrips[(4 * p) + j], 0x000000);
delay(500);
}
}
// oyun kapanış
int who_win = 0; for (int i = 1; i < 4; i++) if (score[i] > score[who_win]) who_win = i;
for (int say = 0; say < 5; say++) {
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
led_yak(ledStrips[(4 * p) + j], player_color[who_win]);
delay(500);
for (int p = 0; p < 4; p++)
for (int j = 0; j < 4; j++)
led_yak(ledStrips[(4 * p) + j], 0x000000);
delay(500);
}
}
/* =======================================================
* MOD 3
* AvoidOwn (kendi renginden kaç) – süreli puanlama
* Intro: oyuncu rengi blink + “dont”/“push”
* Oyun: kendi rengine basmak −2, diğerlerine +1
* basılan buton söner, tek puanlanır
* tur süresi bitince en yüksek skor kazanır
* =======================================================*/
void showWordAcross(const char* w4){
for (uint8_t i=0;i<4;i++){
displayLetterOnModule((4*i)+3, w4[0]);
displayLetterOnModule((4*i)+2, w4[1]);
displayLetterOnModule((4*i)+1, w4[2]);
displayDigitOnModule((4*i)+0, w4[3]-'0'); // hile: son karakter rakamsa; değilse görseli bozmaz
}
}
// daha güvenlisi:
void showWord4(const char* w4){
for (uint8_t i=0;i<4;i++){
displayLetterOnModule((4*i)+3, w4[0]);
displayLetterOnModule((4*i)+2, w4[1]);
displayLetterOnModule((4*i)+1, w4[2]);
displayLetterOnModule((4*i)+0, w4[3]);
}
}
void avoid_own() {
Serial.println("Mod-3: AvoidOwn");
// Intro: 4 sn boyunca “dont” / “push” ve oyuncu renkleri blink
uint32_t t0 = millis(); bool phase=false; bool on=true;
while (millis() - t0 < 4000) {
showWord4(phase ? "push" : "dont");
phase = !phase;
for (int p=0; p<4; p++) {
for (int j=0; j<4; j++)
led_yak(ledStrips[(4*p)+j], on ? player_color[p] : 0x000000);
}
on = !on;
delay(350);
}
ekran.clear();
// skorlar
int score[4] = {0,0,0,0};
int tur_sayisi = 5;
const unsigned long round_ms = 20000UL; // 20 sn
// Skor ekranını sıfırla
reset_scores_display();
for (int tur=0; tur<tur_sayisi; tur++){
// Her oyuncu için 4 random renk ata (en az bir tanesi kendi rengi denk gelmeyebilir; sorun değil)
uint32_t btnCol[4][4];
for (int p=0;p<4;p++){
for (int j=0;j<4;j++){
btnCol[p][j] = colors[random(8)];
led_yak(ledStrips[(4*p)+j], btnCol[p][j]);
}
}
// butonlar tek sayım için kilitleme
uint8_t used[4][4] = {0};
unsigned long tStart = millis();
while (millis() - tStart < round_ms){
for (int p=0;p<4;p++){
for (int j=0;j<4;j++){
int idx = (4*p)+j;
if (used[p][j]) continue;
if (kapasitifOku(ledStrips[idx].sensorPin)) {
// puan
if (btnCol[p][j] == player_color[p]) score[p] -= 2;
else score[p] += 1;
// butonu söndür ve kilitle
led_yak(ledStrips[idx], 0x000000);
used[p][j] = 1;
// skor göster
set_score_digit(p, (score[p] < 0) ? 0 : (score[p] % 10));
}
}
}
}
// tur kazananını bul (eşitlikte küçük index)
int winner = 0; for (int p=1;p<4;p++) if (score[p] > score[winner]) winner = p;
// tur sonu blink: kazanan renk vs beyaz
for (int rep=0; rep<4; rep++){
for (int p=0;p<4;p++)
for (int j=0;j<4;j++)
led_yak(ledStrips[(4*p)+j], (p==winner)? player_color[p] : 0xFFFFFF);
delay(300);
for (int p=0;p<4;p++)
for (int j=0;j<4;j++)
led_yak(ledStrips[(4*p)+j], 0x000000);
delay(300);
}
}
// oyun kapanış: toplam skor galibi
int champ = 0; for (int p=1;p<4;p++) if (score[p] > score[champ]) champ = p;
for (int rep=0; rep<6; rep++){
for (int p=0;p<4;p++)
for (int j=0;j<4;j++)
led_yak(ledStrips[(4*p)+j], (p==champ)? player_color[p] : 0x000000);
delay(300);
for (int p=0;p<4;p++)
for (int j=0;j<4;j++)
led_yak(ledStrips[(4*p)+j], 0x000000);
delay(300);
}
print_game_name(game_mode);
}
/* =======================================================
* Bekleme (rainbow) efekti
* =======================================================*/
int r = 255, g = 0, b = 0;
int stepRGB = 0;
void rainbowStep_waiting_mode(LEDStrip &s) {
int adet = (s.ledPin == 43) ? CENTER_LED_ADET : LED_ADET;
s.strip->fill(s.strip->Color(r, g, b), 0, adet);
s.strip->show();
switch (stepRGB) {
case 0: g++; if (g >= 255) stepRGB++; break;
case 1: r--; if (r <= 0) stepRGB++; break;
case 2: b++; if (b >= 255) stepRGB++; break;
case 3: g--; if (g <= 0) stepRGB++; break;
case 4: r++; if (r >= 255) stepRGB++; break;
case 5: b--; if (b <= 0) stepRGB=0; break;
}
}
void led_show_waiting_time() {
for (int i = 0; i < stripCount; i++) {
rainbowStep_waiting_mode(ledStrips[i]);
}
delay(10);
}
/* =======================================================
* Oyun seçme ve main loop
* =======================================================*/
void start_selected_game(int game_number) {
switch (game_number) {
case 1: start_ClassicClash(); break;
case 2: color_sorting(); break;
case 3: avoid_own(); break;
default: Serial.println("start_selected_game: bilinmeyen mod"); break;
}
}
void setup() {
Serial.begin(115200);
ESP32_SERIAL.begin(115200);
randomSeed(analogRead(A0));
pinMode(StartButton, INPUT); // INPUT: basılı=HIGH
pinMode(ChangeModeButton, INPUT); // INPUT: basılı=HIGH
ekran.begin();
ekran.control(MD_MAX72XX::INTENSITY, 5);
ekran.clear();
print_game_name(game_mode);
pinMode_active(); // sensör pinlerini INPUT yap
for (int i = 0; i < stripCount; i++) {
int adet = (i == 16) ? CENTER_LED_ADET : LED_ADET;
ledStrips[i].strip = new Adafruit_NeoPixel(adet, ledStrips[i].ledPin, NEO_GRB + NEO_KHZ800);
ledStrips[i].strip->begin();
ledStrips[i].strip->show();
}
Serial.println("Hazır: Start=50, Mode=48 (INPUT, basılı=HIGH)");
}
void loop() {
// Bekleme animasyonu
led_show_waiting_time();
// Başlat (INPUT → HIGH basılı)
if (digitalRead(StartButton)) {
start_selected_game(game_mode);
}
// Mod değiştir (INPUT → HIGH basılı)
if (digitalRead(ChangeModeButton)) {
game_mode++;
if (game_mode > 3) game_mode = 1;
print_game_name(game_mode);
delay(200); // kaba debounce
}
}
Editor is loading...
Leave a Comment