Search Code

ESP32-S3 RGB LED Matris Projesi 6 - Cible oyunu

ESP32-S3 RGB LED Matris Projesi 6 - Cible oyunu

Proje 6 – Hedef Oyunu (Hedef Daireyi Vurmak İçin Panoyu Eğin)

Proje 6, bu ESP32-S3 RGB LED Matris serisinin son ve en etkileşimli projesidir. Yerleşik QMI8658C hareket sensörünü kullanarak, 8×8 matris üzerinde bir noktayı hareket ettirmek için panoyu eğersiniz. Ekranın ortasında dairesel bir “hedef bölgesi” bulunur. Noktanız daireye değdiğinde renk değişir ve (isteğe bağlı olarak) bir buzzer öter. Bu, basit ama şaşırtıcı derecede eğlenceli bir denge/koordinasyon oyunu oluşturur.

Altı projenin tamamı tek bir YouTube videosunda gösterilmektedir (bu sayfaya gömülüdür). Tam oyun kodu bu makalenin altına otomatik olarak yüklenir ve modül için satış ortağı satın alma bağlantıları kod bölümünün altında görünür.

ESP32-S3 RGB LED Matris Modülü Genel Bakış

Bu modül şunları içerir:

  • ESP32-S3 mikrodenetleyici (Wi-Fi + BLE)
  • 8×8 RGB LED matris (64 adreslenebilir LED)
  • Eğim ve yön algılama için QMI8658C ivmeölçer
  • Güç ve programlama için USB-C bağlantı noktası
  • Boot / Reset düğmeleri
  • Buzzer veya sensör gibi eklentiler için kullanılabilir GPIO pinleri

Bu oyun için ivmeölçer çok önemlidir—sürekli olarak X/Y eğimini bildirir ve noktanın pano açısına göre sorunsuz hareket etmesini sağlar. Bu projenin video bölümü, modülü sola/sağa/ileri/geri eğdiğinizde noktanın nasıl kaydığını ve tepki verdiğini açıkça gösterir.:contentReference[oaicite:0]{index=0}

Videoda Kapsanan Projeler (Zaman Damgaları)

  • 00:00 – Giriş
  • 02:01 – ESP32 kartlarını kurma
  • 03:32 – Kütüphaneleri kurma
  • 05:32 – Proje 1: Hareket Eden Nokta
  • 11:11 – Proje 2: Metin Kaydırma
  • 12:59 – Proje 3: HTTP Metni
  • 16:41 – Proje 4: Eğim Noktası
  • 18:55 – Proje 5: Yukarı Ok
  • 20:02Proje 6: Hedef Oyunu (bu proje)

Videonun bu kısmı hem nokta hareketini hem de daire algılama mantığını çalışırken gösterir ve koordinatların nasıl davrandığını anlamayı kolaylaştırır.:contentReference[oaicite:1]{index=1}

Arduino IDE'de ESP32 Kartlarını Kurma

Önceki projeleri zaten tamamladıysanız, kart kurulumu yapılmıştır. Aksi takdirde şu adımları izleyin:

  1. File > Preferences → ESP32 kart URL'sini ekleyin.
  2. Tools > Board > Boards Manager… → “ESP32”yi kurun.
  3. Tools > Board altında ESP32-S3 kartını seçin.
  4. Tools > Port altında doğru COM bağlantı noktasını seçin.

Gerekli Kütüphaneleri Kurma

Bu oyun şunları kullanır:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX
  • QMI8658 (hareket sensörü)

Bunları şu şekilde kurun:

  1. Sketch > Include Library > Manage Libraries…
  2. Ara: NeoMatrix → Kur
  3. Bağımlılıkları kur (GFX + NeoPixel)
  4. QMI8658i arayın ve kurun

Hedef Oyunu Nasıl Çalışır

QMI8658C ivmeölçer X ve Y eğim değerleri sağlar. Bunlar LED koordinatlarına (her iki yönde 0–7) eşlenir. Noktanız, panonun açısına göre matris üzerinde hareket eder.

Ekranda “hedef alanı” olarak bir daire (veya halka) çizilir. Nokta daireyle örtüştüğünde bir “isabet” kazanırsınız. O anda:

  • Hedef rengi değişir (rastgele veya önceden tanımlanmış)
  • İsteğe bağlı bir buzzer öter (bağlıysa)

Matris küçük olduğundan, daire basit bir yarıçap kontrolü kullanılarak çizilir. Oyun sürekli çalışır, böylece daireye tekrar tekrar vurmak için ileri geri eğebilirsiniz.

Proje 6 – Kod Ayarları (Hedef Oyunu)

Aşağıda, taslağın en üstünde bulunan ana kullanıcı tarafından ayarlanabilir ayarlar verilmiştir. Tam kod bu makalenin altına otomatik olarak dahil edilmiştir.

Matris Yapılandırması


// Matris yapılandırması
const int MATRIX_PIN    = 14;
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

RGB matris GPIO 14'e sabit olarak bağlıdır—bunu değiştirmeyin.

Parlaklık


uint8_t matrixBrightness = 40;   // 0–255

İç mekan kullanımı için 30–60 idealdir.

Nokta Rengi


// Nokta rengi (R, G, B)
uint8_t dotRed   = 255;
uint8_t dotGreen = 255;
uint8_t dotBlue  = 255;

Bu, panoyu eğerek hareket ettirdiğiniz noktadır.

Daire Rengi (Rastgele veya Sabit)


// Daire (hedef) rengi
uint8_t circleRed   = 0;
uint8_t circleGreen = 0;
uint8_t circleBlue  = 255;

// Doğruysa, nokta her isabet ettiğinde yeni bir rastgele renk seç
bool randomCircleColor = true;

Sabit bir renk istiyorsanız randomCircleColor = false; olarak ayarlayın.

Daire Yarıçapı


// Hedef boyutu (yarıçap)
int targetRadius = 3;   // 3, 8×8 matrise iyi uyar

Daha büyük yarıçaplar oyunu kolaylaştırır; daha küçük olanlar zorlaştırır.

Eğim Hassasiyeti


// Eğim eşlemesinin hassasiyeti
float tiltScale = 4.0f;   // artır = ekranda daha hızlı hareket

Nokta çok hızlı hareket ediyor veya zıplıyorsa bu sayıyı azaltın.

Buzzer Ayarları (İsteğe Bağlı)


// Buzzer pini (isteğe bağlı)
int buzzerPin = 6;      // buzzer +'yı pin 6'ya, – GND'ye bağlayın
bool useBuzzer = true;  // sesi devre dışı bırakmak için false yapın

Bir buzzer bağlamazsanız, sadece useBuzzer = false; ayarlayın.

Özet

Proje 6, önceki projelerden öğrenilen her şeyi birleştirir: matris çizimi, ivmeölçer girişi, renk kontrolü, hareket yumuşatma ve isteğe bağlı ses. Kartı eğmek noktayı hareket ettirir ve daireye çarpmak rengini değiştirir ve (isteğe bağlı olarak) bir bip sesi tetikler. Kompakt bir RGB ekranda hareket algılamanın eğlenceli bir gösterimidir.

Tam “Hedef Oyunu” kodu bu makalenin altında otomatik olarak görüntülenir. Ayrıca videonun Proje 6 bölümünü izleyerek noktanın nasıl hareket ettiğini ve çarpışmaların nasıl algılandığını görebilirsiniz. Kendi oyununuzu oluşturmak isterseniz, ESP32-S3 RGB LED Matris modülünü satın almak için bağlı kuruluş bağlantıları kod bölümünün altında yer alır.

Görseller

ESP32 S3 Matrix
ESP32 S3 Matrix
ESP32 S3 Matrix  pin out
ESP32 S3 Matrix pin out
ESP32-S3_RGB_8x8_matrix-3
ESP32-S3_RGB_8x8_matrix-3
ESP32 S3 Matrix displaying rainbow heart 3
ESP32 S3 Matrix displaying rainbow heart 3
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix-2
ESP32-S3_RGB_8x8_matrix-2
804-ESP32-S3 RGB LED Matrix Project 6 - Cible game
Dil: C++
/* 
  Project 6: Tilt Circle Game – ESP32-S3 RGB LED Matrix (Waveshare)

  This sketch reads tilt from the QMI8658C IMU and smoothly moves a dot 
  on the 8×8 RGB LED matrix based on board orientation.

  ▶️ Video Tutorial:
  https://youtu.be/JKLuYrRcLMI

  📚⬇️ Resources & Code Page:
  https://robojax.com/RJT829

  QMI8658_RGB_2
*/

#include <Arduino.h>
#include <math.h>

#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

#include <QMI8658.h>   // by Lahav Gahali

// -------- LED MATRIX SETUP --------
#define MATRIX_PIN    14
#define MATRIX_WIDTH  8
#define MATRIX_HEIGHT 8

// Buzzer pin – change this to your actual buzzer GPIO.
const int BUZZER_PIN = 6;   // TODO: set to your buzzer pin

// Matrix brightness (0–255)
const uint8_t MATRIX_BRIGHTNESS = 10;

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(
  MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_PIN,
  NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
  NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
  NEO_GRB + NEO_KHZ800
);

// -------- IMU SETUP --------
QMI8658 imu;

// -------- GAME CONFIG --------

// How often the dot is allowed to move (ms).
// Bigger = slower movement.
const uint16_t MOVE_INTERVAL_MS = 150;   // try 120–250

// How much tilt (m/s^2) before the dot moves.
// Increase if it feels too sensitive.
const float ACC_TILT_THRESHOLD = 2.0f;   // about ~0.2 g

// Dot base color (RGB)
const uint8_t DOT_R = 255;
const uint8_t DOT_G = 255;
const uint8_t DOT_B = 255;


// Circle geometry (centered on 8x8)
const float CIRCLE_CENTER_X = (MATRIX_WIDTH - 1) / 2.0f;   // 3.5
const float CIRCLE_CENTER_Y = (MATRIX_HEIGHT - 1) / 2.0f;  // 3.5
const float CIRCLE_RADIUS   = 3.0f;
const float CIRCLE_THICKNESS = 0.8f; // +- thickness around radius

// -------- GAME STATE --------

// Dot position on the 8x8 grid (0..7)
int dotX = 3;
int dotY = 3;

// Colors (16-bit NeoMatrix colors)
uint16_t dotColor;
uint16_t circleColor;

// To detect “just touched circle” vs “still on circle”
bool wasOnCircle = false;

// Timer for rate-limiting movement
unsigned long lastMoveTime = 0;

// -------- HELPER FUNCTIONS --------

// Classic NeoPixel color wheel (0-255 -> rainbow)
uint16_t wheel(byte pos) {
  if (pos < 85) {
    return matrix.Color(pos * 3, 255 - pos * 3, 0);
  } else if (pos < 170) {
    pos -= 85;
    return matrix.Color(255 - pos * 3, 0, pos * 3);
  } else {
    pos -= 170;
    return matrix.Color(0, pos * 3, 255 - pos * 3);
  }
}

// Is a given pixel approximately on the circle?
bool isOnCircle(int x, int y) {
  float dx = x - CIRCLE_CENTER_X;
  float dy = y - CIRCLE_CENTER_Y;
  float d2 = dx * dx + dy * dy;

  float rMin = CIRCLE_RADIUS - CIRCLE_THICKNESS;
  float rMax = CIRCLE_RADIUS + CIRCLE_THICKNESS;

  return (d2 >= rMin * rMin) && (d2 <= rMax * rMax);
}

// Draw circle + dot
void drawScene() {
  matrix.fillScreen(0);

  // Draw circle
  for (int y = 0; y < MATRIX_HEIGHT; y++) {
    for (int x = 0; x < MATRIX_WIDTH; x++) {
      if (isOnCircle(x, y)) {
        matrix.drawPixel(x, y, circleColor);
      }
    }
  }

  // Draw dot (on top)
  matrix.drawPixel(dotX, dotY, dotColor);

  matrix.show();
}

// Simple blocking beep (short)
void buzzOnce() {
  digitalWrite(BUZZER_PIN, HIGH);
  delay(40);
  digitalWrite(BUZZER_PIN, LOW);
}

// Use accelerometer to decide dot movement
void updateDotFromTilt(float ax, float ay) {
  unsigned long now = millis();
  if (now - lastMoveTime < MOVE_INTERVAL_MS) {
    return; // too soon, wait
  }

  int dx = 0;
  int dy = 0;

  // On this board, Y tilt feels like "left/right" on the matrix,
  // and X tilt feels like "up/down" → so we swap.

  // --- Horizontal movement from AY (tilt left/right) ---
  if (ay > ACC_TILT_THRESHOLD) {
    dx = 1;   // tilt to the right → move dot to the right
  } else if (ay < -ACC_TILT_THRESHOLD) {
    dx = -1;  // tilt to the left → move dot to the left
  }

  // --- Vertical movement from AX (tilt forward/back) ---
  // This was inverted. We flip the signs:
  // ax >  threshold  = tilt "forward" (away)  → move dot UP  (dy = -1)
  // ax < -threshold  = tilt "back"    (toward)→ move dot DOWN(dy =  1)
  if (ax > ACC_TILT_THRESHOLD) {
    dy = -1;  // was +1 before
  } else if (ax < -ACC_TILT_THRESHOLD) {
    dy = 1;   // was -1 before
  }

  if (dx != 0 || dy != 0) {
    dotX = constrain(dotX + dx, 0, MATRIX_WIDTH  - 1);
    dotY = constrain(dotY + dy, 0, MATRIX_HEIGHT - 1);
    lastMoveTime = now;
  }
}


// -------- SETUP & LOOP --------

void setup() {
  Serial.begin(115200);
  delay(100);

  // Matrix init
  matrix.begin();
  matrix.setBrightness(MATRIX_BRIGHTNESS);
  matrix.fillScreen(0);
  matrix.show();

  // Buzzer init
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW);

  // IMU init
if (!imu.begin(11, 12)) {
    Serial.println("Failed to initialize QMI8658!");
    while (1) {
      delay(100);
    }
  }

  // Use m/s^2 and dps (optional, but nice)
  imu.setAccelUnit_mps2(true);
  imu.setGyroUnit_dps(true);
  imu.setDisplayPrecision(3);

  Serial.println("QMI8658 initialized.");

  // Game initial state
  randomSeed((uint32_t)micros());

  dotX = MATRIX_WIDTH  / 2;
  dotY = MATRIX_HEIGHT / 2;

  dotColor    = matrix.Color(DOT_R, DOT_G, DOT_B);
  circleColor = wheel(random(256));

  drawScene();
}

void loop() {
  // Read accelerometer
  float ax, ay, az;
  if (imu.readAccelMPS2(ax, ay, az)) {
    // Debug if needed:
    // Serial.print("AX: "); Serial.print(ax);
    // Serial.print("  AY: "); Serial.print(ay);
    // Serial.print("  AZ: "); Serial.println(az);

    updateDotFromTilt(ax, ay);
  }

  // Check collision with circle
  bool onCircle = isOnCircle(dotX, dotY);
  if (onCircle && !wasOnCircle) {
    // Just touched circle: change color + beep
    circleColor = wheel(random(256));
    buzzOnce();
  }
  wasOnCircle = onCircle;

  // Redraw
  drawScene();

  // Small delay so we don’t hammer I2C too hard
  delay(10);
}

İhtiyacın olabileceğini düşünüyor

Kaynaklar ve referanslar

Dosyalar📁

Fritzing Dosyası