Search Code

ESP32-S3 آر جی بی ایل ای ڈی میٹرکس پروجیکٹ 6 - سیبل گیم

ESP32-S3 آر جی بی ایل ای ڈی میٹرکس پروجیکٹ 6 - سیبل گیم

پروجیکٹ 6 – ہدف کا کھیل (بورڈ جھکائیں تاکہ دائرے کو نشانہ بنائیں)

پروجیکٹ 6 اس ESP32-S3 RGB LED میٹرکس سیریز کا آخری اور سب سے زیادہ انٹرایکٹو پروجیکٹ ہے۔ آن بورڈ QMI8658C موشن سینسر کا استعمال کرتے ہوئے، آپ بورڈ کو جھکا کر 8×8 میٹرکس پر ایک نقطہ حرکت دیتے ہیں۔ ڈسپلے کے بیچ میں ایک سرکلر "ہدف کا زون" ہوتا ہے۔ جب آپ کا نقطہ دائرے کو چھوتا ہے، رنگ بدل جاتا ہے اور (اختیاری طور پر) ایک بزر بجتا ہے۔ یہ ایک سادہ لیکن حیرت انگیز طور پر دلچسپ توازن/ہم آہنگی کا کھیل بناتا ہے۔

تمام چھ پروجیکٹس ایک ہی YouTube ویڈیو میں دکھائے گئے ہیں (اس صفحے پر ایمبیڈڈ)۔ مکمل گیم کوڈ اس مضمون کے نیچے خود بخود لوڈ ہوتا ہے، اور ماجیول کے لیے ملحقہ خریداری کے لنکس کوڈ سیکشن کے نیچے ظاہر ہوتے ہیں۔

ESP32-S3 RGB LED میٹرکس ماجیول کا جائزہ

اس ماجیول میں شامل ہیں:

  • ESP32-S3 مائیکروکنٹرولر (وائی-فائی + بلوٹوتھ)
  • 8×8 RGB LED میٹرکس (64 ایڈریس ایبل LEDs)
  • QMI8658C ایکسلرومیٹر جھکاؤ اور سمت کی پیمائش کے لیے
  • USB-C پورٹ بجلی اور پروگرامنگ کے لیے
  • بوٹ / ری سیٹ بٹن
  • دستیاب GPIO پن اضافی آلات جیسے بزر یا سینسر کے لیے

اس کھیل کے لیے، ایکسلرومیٹر ضروری ہے — یہ مسلسل X/Y جھکاؤ رپورٹ کرتا ہے، جس سے نقطہ بورڈ کے زاویے کی بنیاد پر آسانی سے حرکت کرتا ہے۔ اس پروجیکٹ کا ویڈیو سیکشن واضح طور پر دکھاتا ہے کہ جب آپ ماجیول کو بائیں/دائیں/آگے/پیچھے جھکاتے ہیں تو نقطہ کیسے پھسلتا اور رد عمل دیتا ہے۔

ویڈیو میں شامل پروجیکٹس (ٹائم اسٹیمپس)

  • 00:00 – تعارف
  • 02:01 – ESP32 بورڈز کی تنصیب
  • 03:32 – لائبریریز کی تنصیب
  • 05:32 – پروجیکٹ 1: حرکت کرتا نقطہ
  • 11:11 – پروجیکٹ 2: متن اسکرول
  • 12:59 – پروجیکٹ 3: HTTP متن
  • 16:41 – پروجیکٹ 4: جھکاؤ نقطہ
  • 18:55 – پروجیکٹ 5: اوپر تیر
  • 20:02پروجیکٹ 6: ہدف کا کھیل (یہ پروجیکٹ)

ویڈیو کا یہ حصہ نقطہ کی حرکت اور دائرے کی شناخت کی منطق دونوں کو عمل میں دکھاتا ہے، جس سے یہ سمجھنا آسان ہو جاتا ہے کہ کوآرڈینیٹ کیسے برتاؤ کرتے ہیں۔

Arduino IDE میں ESP32 بورڈز کی تنصیب

اگر آپ نے پہلے پروجیکٹس مکمل کر لیے ہیں، تو بورڈ کی تنصیب ہو چکی ہے۔ ورنہ یہ کریں:

  1. فائل > ترجیحات → ESP32 بورڈ URL شامل کریں۔
  2. ٹولز > بورڈ > بورڈز مینیجر… → "ESP32" انسٹال کریں۔
  3. ٹولز > بورڈ کے تحت ESP32-S3 بورڈ منتخب کریں۔
  4. ٹولز > پورٹ کے تحت صحیح COM پورٹ منتخب کریں۔

مطلوبہ لائبریریز کی تنصیب

یہ کھیل استعمال کرتا ہے:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX
  • QMI8658 (موشن سینسر)

انہیں اس طرح انسٹال کریں:

  1. اسکیچ > لائبریری شامل کریں > لائبریریز مینیج کریں…
  2. تلاش کریں: NeoMatrix → انسٹال کریں
  3. انحصار انسٹال کریں (GFX + NeoPixel)
  4. تلاش کر کے QMI8658 انسٹال کریں

ہدف کا کھیل کیسے کام کرتا ہے

QMI8658C ایکسلرومیٹر X اور Y جھکاؤ کی قدریں فراہم کرتا ہے۔ انہیں LED کوآرڈینیٹس (دونوں سمتوں میں 0–7) پر نقش کیا جاتا ہے۔ آپ کا نقطہ بورڈ کے زاویے کی بنیاد پر میٹرکس پر حرکت کرتا ہے۔

ڈسپلے پر ایک دائرہ (یا انگوٹھی) "ہدف کا علاقہ" کے طور پر بنایا جاتا ہے۔ جب بھی آپ کا نقطہ دائرے سے ٹکراتا ہے، آپ "ہٹ" جیت جاتے ہیں۔ اس لمحے:

  • ہدف کا رنگ بدل جاتا ہے (بے ترتیب یا پہلے سے طے شدہ)
  • ایک اختیاری بزر بجتا ہے (اگر منسلک ہو)

چونکہ میٹرکس چھوٹا ہے، دائرہ ایک سادہ رداس چیک کا استعمال کرتے ہوئے بنایا جاتا ہے۔ کھیل مسلسل چلتا ہے، لہذا آپ دائرے کو بار بار نشانہ بنانے کے لیے آگے پیچھے جھک سکتے ہیں۔

پروجیکٹ 6 – کوڈ کی ترتیبات (ہدف کا کھیل)

ذیل میں اہم صارف کے قابل ایڈجسٹ ترتیبات ہیں جو اسکیچ کے اوپری حصے میں واقع ہیں۔ مکمل کوڈ اس مضمون کے نیچے خود بخود شامل ہے۔

میٹرکس کنفیگریشن


// میٹرکس کنفیگریشن
const int MATRIX_PIN    = 14;
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

RGB میٹرکس GPIO 14 سے ہارڈ وائرڈ ہے — اسے تبدیل نہ کریں۔

چمک


uint8_t matrixBrightness = 40;   // 0–255

انڈور استعمال کے لیے، 30–60 مثالی ہے۔

نقطے کا رنگ


// نقطے کا رنگ (R, G, B)
uint8_t dotRed   = 255;
uint8_t dotGreen = 255;
uint8_t dotBlue  = 255;

یہ وہ نقطہ ہے جسے آپ بورڈ جھکا کر حرکت دیتے ہیں۔

دائرے کا رنگ (بے ترتیب یا طے شدہ)


// دائرے (ہدف) کا رنگ
uint8_t circleRed   = 0;
uint8_t circleGreen = 0;
uint8_t circleBlue  = 255;

// اگر درست ہے، تو ہر بار جب نقطہ ٹکراتا ہے نیا بے ترتیب رنگ منتخب کریں
bool randomCircleColor = true;

اگر آپ طے شدہ رنگ چاہتے ہیں تو randomCircleColor = false; سیٹ کریں۔

دائرے کا رداس


// ہدف کا سائز (رداس)
int targetRadius = 3;   // 3 آٹھ×آٹھ میٹرکس پر اچھی طرح فٹ بیٹھتا ہے

بڑا رداس کھیل کو آسان بناتا ہے؛ چھوٹا اسے مشکل بناتا ہے۔

جھکاؤ کی حساسیت


// جھکاؤ کی نقشہ سازی کی حساسیت
float tiltScale = 4.0f;   // بڑھائیں = اسکرین پر تیز حرکت

اگر نقطہ بہت تیز حرکت کرتا ہے یا اچھلتا ہے، تو یہ نمبر کم کریں۔

بزر کی ترتیبات (اختیاری)

// Buzzer پن (اختیاری) int buzzerPin = 6; // buzzer + کو پن 6 سے جوڑیں، – کو GND سے bool useBuzzer = true; // آواز غیر فعال کرنے کے لیے false سیٹ کریں

اگر آپ buzzer نہیں جوڑتے، تو صرف useBuzzer = false; سیٹ کریں

خلاصہ

پروجیکٹ 6 پہلے والے تمام پروجیکٹس سے سیکھی گئی ہر چیز کو یکجا کرتا ہے: میٹرکس ڈرائنگ، ایکسلرومیٹر ان پٹ، رنگ کنٹرول، حرکت کی ہمواری، اور اختیاری آواز۔ بورڈ کو جھکانے سے ڈاٹ حرکت کرتا ہے، اور دائرے سے ٹکرانے سے اس کا رنگ بدل جاتا ہے اور (اختیاری طور پر) بیپ کی آواز آتی ہے۔ یہ ایک کمپیکٹ RGB ڈسپلے پر موشن سینسنگ کا ایک دلچسپ مظاہرہ ہے۔

مکمل “ٹارگٹ گیم” کوڈ اس مضمون کے نیچے خود بخود دکھایا گیا ہے۔ آپ ویڈیو کا پروجیکٹ 6 والا حصہ بھی دیکھ سکتے ہیں تاکہ یہ معلوم ہو سکے کہ ڈاٹ کیسے حرکت کرتا ہے اور ٹکرانے کا پتہ کیسے چلتا ہے۔ اگر آپ اپنا گیم بنانا چاہتے ہیں، تو ESP32-S3 RGB LED میٹرکس ماجیول خریدنے کے لیے ایفلیئٹ لنکس کوڈ سیکشن کے نیچے موجود ہیں۔

تصاویر

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
زبان: 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);
}

آپ کو جن چیزوں کی ضرورت ہو سکتی ہے

وسائل اور حوالہ جات

فائلیں📁

فریٹزنگ فائل