Search Code

Proiect Matrice LED RGB ESP32-S3 6 - Joc Cible

Proiect Matrice LED RGB ESP32-S3 6 - Joc Cible

Proiectul 6 – Jocul Țintă (Înclină Placa pentru a Lovii Cercul)

Proiectul 6 este ultimul și cel mai interactiv proiect din această serie ESP32-S3 cu matrice LED RGB. Folosind senzorul de mișcare QMI8658C integrat, înclini placa pentru a muta un punct pe matricea 8×8. O „zonă țintă” circulară se află în mijlocul afișajului. Când punctul tău atinge cercul, culoarea se schimbă și (opțional) un buzzer emite un semnal sonor. Acest lucru creează un joc simplu, dar surprinzător de distractiv, de echilibru/coordonare.

Toate cele șase proiecte sunt demonstrate într-un singur videoclip YouTube (încorporat pe această pagină). Codul complet al jocului este încărcat automat mai jos, după acest articol, iar linkurile de afiliere pentru achiziționarea modulului apar sub secțiunea de cod.

Prezentare Generală a Modulului cu Matrice LED RGB ESP32-S3

Acest modul include:

  • Microcontroler ESP32-S3 (Wi-Fi + BLE)
  • Matrice LED RGB 8×8 (64 LED-uri adresabile)
  • Accelerometru QMI8658C pentru detectarea înclinării și orientării
  • Port USB-C pentru alimentare și programare
  • Butoane Boot / Reset
  • Pini GPIO disponibili pentru componente suplimentare, cum ar fi buzzere sau senzori

Pentru acest joc, accelerometrul este esențial—raportează continuu înclinarea pe axele X/Y, permițând punctului să se miște lin în funcție de unghiul plăcii. Secțiunea video pentru acest proiect arată clar cum punctul alunecă și reacționează pe măsură ce înclini modulul stânga/dreapta/înainte/înapoi.

Proiecte Acoperite în Videoclip (Marcaje de Timp)

  • 00:00 – Introducere
  • 02:01 – Instalarea plăcilor ESP32
  • 03:32 – Instalarea bibliotecilor
  • 05:32 – Proiectul 1: Punct în Mișcare
  • 11:11 – Proiectul 2: Derulare Text
  • 12:59 – Proiectul 3: Text HTTP
  • 16:41 – Proiectul 4: Punct cu Înclinare
  • 18:55 – Proiectul 5: Săgeată Sus
  • 20:02Proiectul 6: Jocul Țintă (acest proiect)

Această parte a videoclipului arată atât mișcarea punctului, cât și logica de detectare a cercului în acțiune, facilitând înțelegerea modului în care se comportă coordonatele.

Instalarea Plăcilor ESP32 în Arduino IDE

Dacă ai finalizat deja proiectele anterioare, instalarea plăcii este gata. În caz contrar, urmează:

  1. File > Preferences → Adaugă URL-ul plăcii ESP32.
  2. Tools > Board > Boards Manager… → Instalează „ESP32”.
  3. Selectează placa ESP32-S3 sub Tools > Board.
  4. Selectează portul COM corect sub Tools > Port.

Instalarea Bibliotecilor Necesare

Acest joc folosește:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX
  • QMI8658 (senzor de mișcare)

Instalează-le prin:

  1. Sketch > Include Library > Manage Libraries…
  2. Caută: NeoMatrix → Instalează
  3. Instalează dependențele (GFX + NeoPixel)
  4. Caută și instalează QMI8658

Cum Funcționează Jocul Țintă

Accelerometrul QMI8658C furnizează valori de înclinare pe axele X și Y. Acestea sunt mapate la coordonatele LED-urilor (0–7 în ambele direcții). Punctul tău se mișcă pe matrice în funcție de unghiul plăcii.

Un cerc (sau inel) este desenat pe afișaj ca „zonă țintă”. Obții o „lovitură” de fiecare dată când punctul se suprapune cu cercul. În acel moment:

  • Culoarea țintei se schimbă (aleatorie sau prestabilită)
  • Un buzzer opțional emite un semnal sonor (dacă este conectat)

Deoarece matricea este mică, cercul este desenat folosind o simplă verificare a razei. Jocul rulează continuu, astfel încât poți înclina placa înainte și înapoi pentru a lovi cercul în mod repetat.

Proiectul 6 – Setări Cod (Jocul Țintă)

Mai jos sunt principalele setări ajustabile de utilizator, situate în partea de sus a schiței. Codul complet este inclus automat mai jos, după acest articol.

Configurarea Matricei


// Configurarea matricei
const int MATRIX_PIN    = 14;
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

Matricea RGB este conectată fix la GPIO 14—nu schimba această valoare.

Luminozitate


uint8_t matrixBrightness = 40;   // 0–255

Pentru utilizare în interior, 30–60 este ideal.

Culoarea Punctului


// Culoarea punctului (R, G, B)
uint8_t dotRed   = 255;
uint8_t dotGreen = 255;
uint8_t dotBlue  = 255;

Acesta este punctul pe care îl miști prin înclinarea plăcii.

Culoarea Cercului (Aleatorie sau Fixă)


// Culoarea cercului (țintei)
uint8_t circleRed   = 0;
uint8_t circleGreen = 0;
uint8_t circleBlue  = 255;

// Dacă este true, alege o nouă culoare aleatorie de fiecare dată când punctul lovește
bool randomCircleColor = true;

Setază randomCircleColor = false; dacă dorești o culoare fixă.

Raza Cercului


// Dimensiunea țintei (raza)
int targetRadius = 3;   // 3 se potrivește bine pe matricea 8×8

Razele mai mari fac jocul mai ușor; cele mai mici îl fac mai dificil.

Sensibilitatea la Înclinare


// Sensibilitatea mapării înclinării
float tiltScale = 4.0f;   // crește = mișcare mai rapidă pe ecran

Dacă punctul se mișcă prea repede sau sare, reduce acest număr.

Setări Buzzer (Opțional)


// Pin pentru buzzer (opțional)
int buzzerPin = 6;      // conectați buzzer + la pinul 6, – la GND
bool useBuzzer = true;  // setați false pentru a dezactiva sunetul

Dacă nu conectați un buzzer, pur și simplu setați useBuzzer = false;

Rezumat

Proiectul 6 combină tot ce s-a învățat din proiectele anterioare: desenarea matricei, intrarea accelerometrului, controlul culorilor, netezirea mișcării și sunet opțional. Înclinarea plăcii mută punctul, iar atingerea cercului îi schimbă culoarea și (opțional) declanșează un bip. Este o demonstrație distractivă a detectării mișcării pe un afișaj RGB compact.

Codul complet al „Jocului Țintă” este afișat automat mai jos în acest articol. Puteți urmări și partea din Proiectul 6 a videoclipului pentru a vedea cum se mișcă punctul și cum sunt detectate atingerile. Dacă doriți să vă construiți propriul joc, linkurile afiliate pentru achiziționarea modulului ESP32-S3 RGB LED Matrix apar sub secțiunea de cod.

Imagini

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
Limba: 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);
}

Lucruri de care ai putea avea nevoie

Resurse și referințe

Fișiere📁

Fișier Fritzing