مشروع لعبة Mini Cyclone بواسطة حلقة LED WS2812 2

تم نشر هذا المشروع لجميع الأشخاص المهتمين في مجال تصنيع وابتكار المشاريع الإلكترونية والبرمجية، و نود التنويه أن موقع انا الكتروني يخلي مسؤوليته التامة في حال لم يعمل المشروع لدى العميل أو في حال الاستخدام الخاطئ للمكونات الإلكترونية والكهربائية التي قد تؤدي لحدوث أي مشكلة لا سمح الله.

شرح فكرة المشروع

  • هذا المشروع هو عبارة عن لعبة Mini Cyclone، بواسطة حلقة LED WS2812 وأردوينو نانو.
  • هذه اللعبة مستوحاة من لعبة Cyclone arcade، بحيث يحاول اللاعب إيقاف الليد المتدحرج على طول حلقة LED WS2812.
  • يتم استخدام حلقة صغيرة تحتوي على 16 ليدًا.
  • كل جولة تكون بسرعة عشوائية.
  • عند تشغيل اللعبة، تضيء جميع الليدات تسلسليًا مصحوبة بتأثير صوتي مناسب، ورسالة تنويه تظهر على شاشة العرض LCD.
  • بعد ذلك، تبدأ اللعبة بالضغط على زر “Play”.
  • كما يجب الضغط على زر “Play” في اللحظة التي يكون فيها الليد المتدحرج متموضعًا بالضبط على الليد الثابت.
  • في المستويات الأولية، تكون هناك ثلاثة ليدات ثابتة، بينما في المستويات التالية فيكون هناك ليد واحد فقط.
  • يتم عرض عدد المراحل الناجحة و رصيد النقاط على الشاشة.
  • إذا لم ينجح اللاعب في ايقاف الليد الأحمر، فستنتهي اللعبة حينئذ، وستعرض الشاشة قيمة الرصيد الأعلى.
  • أما إذا نجح اللاعب، فسيتم تسجيل قيمة الرصيد الأعلى في ذاكرة EPROM للأردوينو بحيث يتم الاحتفاظ به حتى بعد إعادة التشغيل.
  • لحذف قيمة الرصيد الأعلى المسجلة، يجب الضغط على زر “RESET” عند تشغيل اللعبة.
  • الرابط

ادوات المشروع

تنويه: استخدم لوحة Bread board لتوصيل الوحدات بمنفذ 5V و GND
  • اردوينو نانو + كابل اردوينو نانو Arduino Nano: عدد 1
  • CJMCU بت 16 WS2812 5050RGB LED المدمج في أضواء بالألوان الكاملة لوحة تطوير دائرية: عدد 1
  • شاشة LCD 16 x 02 IIC/I2C Serial: عدد 1
  • مفتاح بزر ضغط Tactile round push button: عدد 2
  • بازر 5 فولت طنان Active Buzzer: عدد 1
  • أسلاك توصيل من ذكر إلى ذكر 40 دبوس 20 سم wires 40pcs Male to male
  • أسلاك توصيل من ذكر إلى أنثى 40 دبوس 20 سم wires 40pcs Male to Female
  • لوح تجارب 400 نقطة لون ابيض Solderless Breadboard: عدد 1

مخطط المشروع

طريقة توصيل الادوات مع أردوينو

حلقة LED:

VCC -> 5V

GND -> GND

DI -> 2

أزرار الضغط و الطنان:

6  <- الطرف 1 لزر “play”

GND  <- الطرف 2 لزر “play”

—————

RESET  <- الطرف 1 لزر “reset”

GND  <- الطرف 2 لزر “reset”

—————

10  <- الطرف الأطول للطنان

GND  <- الطرف الأقصر للطنان

شاشة LCD:

SDA Pin -> A4 Pin

SCL Pin -> A5 Pin

VCC Pin -> 5V

GND Pin -> GND

الكود البرمجي

تنبيه : في حال لم تكن متأكد من قدرتك على تنفيذ خطوات المشروع يرجى استشارة شخص متخصص في هذا المجال.
  • للتعرف على تجهيز لوحة أردوينو للبرمجة قم بزيارة الرابط التالي.
  • للإطلاع على كيفية تحميل وتنصيب المكتبات قم بزيارة الرابط التالي.
  • قبل تحميل الكود البرمجي، عليك تحميل المكتبات التالية:
  • Adafruit_NeoPixel.h
  • Wire.h
  • iLiquidCrystal_I2C.h
  • EEPROM.h
  • في حال لم يعمل هذا الكود البرمجي، قم بتحميل ملف الكود بالضغط على زر التحميل الموجود في الأسفل.

//—————————————————–
// Game “CYCLONE” for Arduino

//Include libraries
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>

//Defines
#define NUMPIXELS 16 // Popular NeoPixel ring size or edit the number of LEDs
#define PIN 2 // Data-Pin to ring or strip
#define PINBTN 6 // Pin for Player-button
#define PINSCORERST 9 // Pin to reset score during first run

#define DISABLEWINDOW 3 //Rounds before the LED before and after target is not valid anymore

//Player-Dot speed defines
#define STARTINTERVAL 250 //”Normal” move
#define MAXINTERVAL 500 //Very slow move
#define MININTERVAL 50 //Very fast move

//Create objects
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD adress
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); //Init NeoPixel object

bool bFirstRun, bSecureWindow;
int iState = 1;
int iTargetPos, iPlayerPos, iStoredHighscore, iRound, iScore, iInterval; //Vars for the game
int iLastButtonPressed, iButtonState, iDebounceButton; //Vars to debounce button
unsigned long iLastPlayerMove, ulLastDebounceTime; //Timer to debouce button
unsigned long ulDebounceButton = 10; //Debounce-time
int i = 0;
void setup() {
Serial.begin(115200);
Serial.println(“Init serial communication: DONE”);

//Begin init for WS218B-ring or -strip
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
pixels.clear(); // Set all pixels to “off”
pixels.setBrightness(20); // Set brightness to 20%
pixels.show(); // Send the updated pixel colors to the hardware.
Serial.println(“Init WS218B-ring: DONE”);

//Begin init display
lcd.init();
lcd.backlight();
lcd.clear();
Serial.println(“Init LCD display: DONE”);

randomSeed(analogRead(0)); // Make randome more randome
Serial.println(“Make randome more randome: DONE”);

//Read latest highscore from EEPROM
iStoredHighscore = EEPROM.read(0);
Serial.println(“Last stored highscore: ” + String(iStoredHighscore));

//Init button with internal pullup-resistor
pinMode(PINBTN,INPUT_PULLUP); //GameBTN
pinMode(PINSCORERST,INPUT_PULLUP); //Reset-Pin for score

//Init some basic-vars
bFirstRun = true; //Enable firstrun
iLastButtonPressed = digitalRead(PINBTN); //Init iLastButtonPressed
iButtonState = digitalRead(PINBTN); //Init iButtonstate
}

void loop() {
int iDebounceButton = DebounceButton(); //Check and debounce button

if(!bFirstRun)
{
if(iState == 1) //Startscreen
{
bSecureWindow = true;
iRound = 1;
iScore = 0;
iInterval = STARTINTERVAL;
lcd.clear();
lcd.home();
lcd.print(“Highscore: ” + String(iStoredHighscore));
lcd.setCursor(0,1);
lcd.print(“Press button …”);
iState = 2;
}
if(iState == 2) //Get Button pressed
{
if(iDebounceButton == LOW)
{
if(iRound == 1) //Only show once during game
Serial.println(“——– New game ——–“);
lcd.clear();
lcd.home();
lcd.print(“Release button”);
lcd.setCursor(0,1);
lcd.print(“to start”);
iState = 3;
}
}
if(iState == 3) //Init next round
{
if(iDebounceButton == HIGH)
{
lcd.clear();
lcd.home();
lcd.print(“Round: ” + String(iRound));
Serial.println(“Round: ” + String(iRound));
lcd.setCursor(0,1);
lcd.print(“Score: ” + String(iScore));
Serial.println(“Score: ” + String(iScore));

iTargetPos = random(0,NUMPIXELS-1);
Serial.println(“New target pos: ” + String(iTargetPos));
iPlayerPos = random(0,NUMPIXELS-1);
while(iTargetPos == iPlayerPos)
iPlayerPos = random(0,NUMPIXELS-1);
Serial.println(“Player start pos: ” + String(iPlayerPos));
iState = 4;
}
}
if(iState == 4) //Draw target and playes dot
{
DrawNextTarget(iTargetPos, bSecureWindow); //Draw new target
DrawPlayer(iPlayerPos); //Draw player dot
iLastPlayerMove = millis(); //Update timer for moving
iState = 5;
}
if(iState == 5) //Wait pressing button and move player dot
{
if(iDebounceButton == LOW)
{
iState = 6;
}
else
{
unsigned long currentMillis = millis();
if(currentMillis – iLastPlayerMove > iInterval)
{
iPlayerPos++;
if(iPlayerPos >= NUMPIXELS)
iPlayerPos = 0;
DrawNextTarget(iTargetPos, bSecureWindow);
DrawPlayer(iPlayerPos);
iLastPlayerMove = currentMillis;
}
}
}
if(iState == 6) //Check if player win
{
if(CheckPlayerPos()) //Winner or loser?
{
iScore++; //Update score
tone(10, 3000, 100);
iRound++; //Update rounds
iState = 2; //Go back to release button
if(iRound > DISABLEWINDOW) //Only target
{
bSecureWindow = false;
iInterval = random(MININTERVAL,MAXINTERVAL);
}
else
iInterval = random(STARTINTERVAL-50,MAXINTERVAL);
Serial.println(“New interval: ” + String(iInterval));
}
else
iState = 90;
}
if(iState == 90) //Game ends
{
Serial.println(“Game ends”);
lcd.clear();
lcd.home();
iDebounceButton = HIGH;
iLastButtonPressed = HIGH;
iButtonState = HIGH;
if(iScore > iStoredHighscore) //New highscore?
{
lcd.print(“New highscore “);
lcd.setCursor(0,1);
lcd.print(“New score: ” + String(iScore));
Serial.println(“New highscore is ” + String(iScore));
EEPROM.write(0,iScore); //Store new highscore to EEPROM
iStoredHighscore = iScore;
}
else //Loser
{
lcd.print(“Game Over”);
lcd.setCursor(0,1);
lcd.print(“You lose”);
Serial.println(“You lose!”);
tone(10, 150, 1000);
}
Serial.println(“——– End game ——–“);
delay(2000);
iState = 1;
}
}
else
InitFirstRun(); //Init Firstrun to check LCD and WS218B-ring
}

//Function to make first run
void InitFirstRun()
{
if(digitalRead(PINSCORERST) == LOW) //Overwrite EEPROM with “0”
{
Serial.println(“Reset highscore”);
for(int iCnt = 0; iCnt < EEPROM.length(); iCnt++)
EEPROM.write(iCnt,0);
}
Serial.println(“—- Start init —-“);
lcd.home();
lcd.print(“Game Cyclone”);
Serial.println(“Game Cyclone”);
lcd.setCursor(0,1);
lcd.print(“(c) M3taKn1ght”);
Serial.print(“(c) M3taKn1ght”);
delay(1000);
lcd.clear();
lcd.home();
lcd.print(” mircemk”);
Serial.println(“For az-Delivery”);
lcd.setCursor(0,1);
lcd.print(“Testing ring …”);
Serial.println(“Testing ring …”);
delay(1000);
pixels.clear();
//Check every single LED
for(int i = 0; i<=51; i+=51)
{
InitRingTest(i,0,0);
delay(50);
}
// pixels.clear();
// for(int i = 0; i<=255; i+=51)
// {
// InitRingTest(0,i,0);
// delay(50);
//}
// pixels.clear();
// for(int i = 0; i<=255; i+=51)
// {
// InitRingTest(0,0,i);
// delay(50);
// }
pixels.clear();
pixels.show();

Serial.println(“—- End init —-“);
bFirstRun = false;
Serial.println(“bFirstRun: ” + String(bFirstRun));
Serial.println(“Activate state for game”);
}

//Simple function to check LED-Ring one by one
void InitRingTest(int iRed, int iGreen, int iBlue)
{
Serial.println(“R: ” + String(iRed) + ” G: ” + String(iGreen) + ” B: ” + String(iBlue));
for(int iPixel = 0; iPixel < NUMPIXELS; iPixel++)
{
pixels.setPixelColor(iPixel, pixels.Color(iRed, iGreen, iBlue));
pixels.show();
int thisPitch = map (iPixel , 0, 16, 1000, 3000);
tone(10, thisPitch,120);
delay(50);
}
}

//Function to draw target an secure area for player
void DrawNextTarget(int iPos, bool bArea)
{
pixels.clear();
pixels.setPixelColor(iPos, pixels.Color(0, 255, 0));
if(bArea)
{
if(iPos – 1 < 0)
pixels.setPixelColor(NUMPIXELS – 1, pixels.Color(255, 136, 0));
else
pixels.setPixelColor(iPos – 1, pixels.Color(255, 136, 0));

if(iPos + 1 >= NUMPIXELS)
pixels.setPixelColor(0, pixels.Color(255, 136, 0));
else
pixels.setPixelColor(iPos + 1, pixels.Color(255, 136, 0));
}
}

//Function to draw players LED
void DrawPlayer(int iPos)
{
if(iPos == iTargetPos) //target and player-dot is equal
pixels.setPixelColor(iPos, pixels.Color(0, 0, 255)); //Dot color will blue

else
pixels.setPixelColor(iPos, pixels.Color(255, 0, 0)); //Otherwise red
pixels.show();
tone(10, 500, 50);
}

//Function to check after pressing button, if user hit the target
bool CheckPlayerPos()
{
if(iTargetPos == iPlayerPos) //Player hit target?

return true;

else
{
if(bSecureWindow) //LED before and after target active?
{
int iBeforeTarget = iTargetPos – 1;
int iAfterTarget = iTargetPos + 1;
if(iBeforeTarget < 0)
iBeforeTarget = NUMPIXELS – 1;
if(iAfterTarget >= NUMPIXELS)
iAfterTarget = 0;
if(iBeforeTarget == iPlayerPos || iAfterTarget == iPlayerPos)
return true;
else
return false;

}
else
return false;
}
}

//Function to debounce button
int DebounceButton()
{
int iCurrentButtonState = digitalRead(PINBTN);
if(iCurrentButtonState != iLastButtonPressed)
ulLastDebounceTime = millis();

if((millis() – ulLastDebounceTime) > ulDebounceButton)
{
if(iCurrentButtonState != iButtonState)
iButtonState = iCurrentButtonState;
}
iLastButtonPressed = iCurrentButtonState;
return iButtonState;
}

2 Comments

  1. هل تجي حقيبه كاملة او اطلب القطع كل وحده لحالها .. والاكواد موجودة جاهزة ؟

    1. مرحبا بدرية
      يتم طلب القطع كل وحده لحالها على حسب احتياجك من القطع
      الأكواد موجودة في صفحة المشروع

      ielectrony Support Team

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *