جدول المحتويات:

لعبة Arduino OLED Snake: 3 خطوات
لعبة Arduino OLED Snake: 3 خطوات

فيديو: لعبة Arduino OLED Snake: 3 خطوات

فيديو: لعبة Arduino OLED Snake: 3 خطوات
فيديو: Arduino Snake Game on an OLED display. 2024, يوليو
Anonim
لعبة اردوينو OLED الأفعى
لعبة اردوينو OLED الأفعى

مرحبًا ومرحبًا بكم ، في تعليماتنا حول كيفية صنع لعبة arduino OLED ، جاء هذا المشروع بينما كنا نحاول صنع أول لعبة على الإطلاق باستخدام اردوينو ، لذا فكرنا في مكان أفضل للبدء من لعبة Nokia Classic Snake (حسنًا في الأقل استنساخ ثعبان:)).

ما سوف تحتاجه

اللوازم

اردوينو UNO أو استنساخ

شاشة OLED

4 ثنائيات

500-1 كيلو المقاوم

4 أزرار تحكم

الجرس السلبي بيزو

اختياري

لوح الخبز غير الملحوم

يرجى ملاحظة أن هذه الروابط هي على سبيل المثال فقط

الخطوة 1: الدائرة

الدائرة
الدائرة

في الصورة أعلاه ، يمكنك رؤية دائرتنا ، نستخدم دبوس d3 على اردوينو كدبوس طلب مقاطعة بحيث يعطي اردوينو الأولوية لقراءة مدخلات وحدة التحكم وهي d4 d5 d6 d7. تتمثل أساسيات الدائرة في الضغط على زر الاتجاه الذي يرتفع بمقدار 5 فولت وهذا ينشط دبوس طلب المقاطعة (السلك الأرجواني d3) ودبوس الاتجاه المقابل ، وتستدعي وظيفة المقاطعة وظيفة اتجاه التحديث وهذا الرمز يحرك الثعبان وفقًا لذلك. يتم استخدام دبوس 9 كدبوس صوت لأنه PWM (~ تعديل عرض النبضة) وهو متصل مباشرة ببيزو 5 فولت على + دبوس و- يعود إلى 0 فولت / الأرض.

(لمعلوماتك على اردوينو أونو والنسخ فقط يمكن أن تكون d2 و d3 بمثابة دبابيس طلب المقاطعة).

دبابيس الاتجاه:

d4 يصل برتقالي

d5 أسفل الوردي

d6 اليسار الأزرق

d7 يمين بني

d9 sound grey

يحتوي كل زر على مدخل اتصال 5 فولت ومخرج متصل أولاً بالمدخل الرقمي الخاص به على اردوينو ، ثم يتم توصيل نفس الإخراج لكل زر بالديود الخاص به ، ونستخدم الثنائيات لإيقاف تغذية الجهد مرة أخرى إلى الأزرار الأخرى وتفعيلها. في نهاية الكاثود (-) لجميع الثنائيات الأربعة ، نربطهم معًا لإنشاء تقاطع خرج يتصل بـ d3 ثم من خلال المقاوم إلى 0 فولت / الأرض لسحب دبابيس اردوينو منخفضة حتى لا تترك دبابيس عائمة عندما لا تكون مفعل.

(لمعلوماتك ، يمكن أن يتلقى دبوس عائم جهدًا وهميًا ويسبب سلوكًا غير عادي)

يتم استخدام دبابيس تمثيلية لتشغيل الشاشة ، وهما دبابيس اردوينو i2c للأجهزة.

A5 متصل بـ SCL YELLOW

A4 متصل بـ SDA GREEN

يتم استخدام خرج + 5 فولت و 0 فولت (الأرض) من اردوينو كمصدر للطاقة للدائرة بأكملها والتي يمكن تشغيلها بواسطة USB أو شاحن الهاتف.

الخطوة الثانية: الكود

// ------------------------ ألعاب ANJAWARE SNAKE بمساعدة الشعوب الصافية --------------- -------

#يشمل

# تضمين // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // عرض مجموعة (العرض والارتفاع) Adafruit_SSD1306 عرض (128 ، 64) ؛ // حدد دبابيس الإدخال هذه هي المسامير الموجودة على اردوينو التي لا تتغير أبدًا لذا #define #define INTPIN 3 // فقط الدبابيس 2 و 3 يمكن أن تقاطع الدبابيس على UNO #define UPPIN 4 // هذه دبابيس متصلة tp المفتاح ذي الصلة # تعريف DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // حدد الاتجاهات #define DIRUP 1 // هذه القيم هي ما ينظر إليه "الثعبان" ليقرر- #define DIRDOWN 2 // الاتجاه الذي سيسلكه الثعبان # حدد DIRLEFT 3 # تعريف DIRIGHT 4

// تعيين متغيرات الزر

// volitile cos نحتاجه للتحديث مع interupt بحيث يمكن أن يكون أي جزء من قيمة الدورة

// ليس أعلى من 4 أبدًا ، لذا تحتاج فقط إلى 8 بت int لتوفير الموارد المتقلبة uint8_t buttonpressed = 0 ؛ bool butup = 0 ؛ bool butdown = 0 ؛ // نستخدم هذا لضبط true إلى "اكتشاف" الاتجاه الذي تم ضغطه bool butleft = 0 ؛ منطقي = 0 ؛

// مآخذ الثعابين

بايت snakePosX [30] ؛ // مجموعة لعمل جسم ثعبان بايت ثعبان PosY [30] ؛

الأفعى X = 30 ؛ // موقف رأس الثعبان

ثعبان عدد Y = 30 ؛ حجم الثعبان = 1 ؛ // عدد حجم الثعبان يقتصر على حجم المصفوفة

// العالم ints

uint8_t worldMinX = 0 ؛ // هذه تحدد حدود منطقة اللعب

uint8_t worldMaxX = 128 ؛ uint8_t worldMinY = 10 ؛ uint8_t worldMaxY = 63 ؛

// جمع سكران (طعام) وموضع سكران

منطقية scranAte = 0 ؛ uint8_t scranPosX = 0 ؛ uint8_t scranPosY = 0 ؛

// عشرات المتغيرات

لعب طويل = 0 ؛ أعلى نتيجة طويلة = 30 ؛ // تعيين درجة عالية إلى 3 جمع كنقطة انطلاق

// --------------------------- هذا ما ينفذه المقاطعة عند ارتفاع الجهد ------------ -------------

باطل المقاطعة () {delay (150) ؛ // تأخير طفيف للحماية "المرتدة" المضافة ، updatedirection () ؛ } // ------------------ قم بتحديث قيمة الاتجاه من الضغط على الزر ----------------- void updatedirection () { // Serial.println ("updatingdirection") ؛ butup = digitalRead (UPPIN) ؛ // تحقق من المدخلات المرتفعة وتعيين قيمة منطقية ذات صلة صحيحة = digitalRead (DWNPIN) ؛ butleft = digitalRead (LFTPIN) ؛ butright = digitalRead (RHTPIN) ؛ // هذه الحالات إذا نظرت الحالات إلى المدخلات المرتفعة وأدخلت القيمة ذات الصلة في "buttonpressed" // متغير ، فإن هذا المتغير يحدد اتجاه الحركة إذا (butup == true) {buttonpressed = DIRUP؛ // Serial.println ("UP pressed") ؛ // Serial.println (buttonpressed) ؛ butup = خطأ ؛ نغمة (SND ، 1500 ، 10) ؛ } إذا (butdown == true) {buttonpressed = DIRDOWN ؛ // Serial.println ("DOWN pressed") ؛ // Serial.println (buttonpressed) ؛ بوت داون = خطأ ؛ نغمة (SND ، 1500 ، 10) ؛ }

إذا (بوتليفت == صحيح)

{buttonpressed = DIRLEFT ؛ // Serial.println ("الضغط على اليسار") ؛ // Serial.println (buttonpressed) ؛ بوتليفت = خطأ ؛ نغمة (SND ، 1500 ، 10) ؛ } إذا (butright == true) {buttonpressed = DIRRIGHT؛ // Serial.println ("الضغط لليمين") ؛ // Serial.println (buttonpressed) ؛ بوترايت = خطأ ؛ نغمة (SND ، 1500 ، 10) ؛ }}

// -------------------------- ارسم إجراءات العرض ------------------ -----------------

باطلة updateDisplay () // ارسم الدرجات والخطوط العريضة

{// Serial.println ("تحديث العرض") ؛

display.fillRect (0، 0، display.width () - 1، 8، BLACK) ؛

display.setTextSize (0) ، display.setTextColor (WHITE) ، // رسم الدرجات display.setCursor (2، 1)؛ display.print ("الدرجة:") ؛ display.print (سلسلة (playcore ، DEC)) ؛ display.setCursor (66 ، 1) ؛ display.print ("High:") ؛ display.print (سلسلة (درجة عالية ، DEC)) ؛ // رسم منطقة اللعب // pos 1x، 1y، 2x، 2y، color display.drawLine (0، 0، 127، 0، WHITE) ؛ // عرض الحد العلوي للغاية. رسم خط (63 ، 0 ، 63 ، 9 ، أبيض) ؛ // عرض فاصل النقاط (0 ، 9 ، 127 ، 9 ، أبيض) ؛ // أسفل عرض حدود النص. رسم خط (0 ، 63 ، 127 ، 63 ، أبيض) ؛ // عرض الحد السفلي. DrawLine (0 ، 0 ، 0 ، 63 ، أبيض) ؛ // عرض الحد الأيسر. رسم خط (127 ، 0 ، 127 ، 63 ، أبيض) ؛ // الحد الأيمن

}

// ----------------------------------- تحديث منطقة اللعب ---------- --------------------

void updateGame () // يقوم بتحديث عرض منطقة اللعبة

{display.clearDisplay () ،

display.drawPixel (scranPosX ، scranPosY ، WHITE) ؛

scranAte = scranFood () ،

// تحقق من إجراءات الثعبان

إذا (outOfArea () || selfCollision ())

{ انتهت اللعبة()؛ }

// عرض الثعبان

لـ (int i = 0؛ i0؛ i--) {snakePosX = snakePosX [i-1] ؛ snakePosY = snakePosY [i-1] ، } // أضف بكسلًا إضافيًا إلى الثعبان إذا (scranAte) {snakeSize + = 1؛ snakePosX [snakeSize-1] = snakeX ؛ snakePosY [snakeSize-1] = snakeY ؛ }

التبديل (تم الضغط على زر) // كان snakeDirection

{حالة DIRUP: snakeY- = 1 ، استراحة؛ الحالة DIRDOWN: ثعبان + = 1 ؛ استراحة؛ الحالة DIRLEFT: snakeX- = 1 ؛ استراحة؛ الحالة DIRIGHT: snakeX + = 1 ؛ استراحة؛ } snakePosX [0] = snakeX ؛ snakePosY [0] = snakeY ؛ updateDisplay () ، display.display () ، // --------------------- ضع Scran -------------------

مكان باطل

{scranPosX = عشوائي (worldMinX + 1 ، worldMaxX-1) ؛ scranPosY = عشوائي (worldMinY + 1 ، worldMaxY-1) ؛ } // ------------------------ SCRAN ATE POINT UP ---------------- bool scranFood () {if (snakeX == scranPosX && snakeY == scranPosY) {playscore = playscore + 10؛ نغمة (SND ، 2000 ، 10) ؛ updateDisplay () ، placeScran () ؛ العودة 1 ؛ } else {return 0؛ } } //--------------------- خارج المنطقة---------------------- bool outOfArea () {return snakeX = worldMaxX || snakeY = worldMaxY؛ } //---------------------- انتهت اللعبة----------------------- --- باطل gameOver () {uint8_t rectX1، rectY1، rectX2، rectY2؛ RectX1 = 38 ؛ RectY1 = 28 ؛ RectX2 = 58 ؛ RectY2 = 12 ؛ display.clearDisplay () ، display.setCursor (40 ، 30) ؛ display.setTextSize (1) ، نغمة (SND ، 2000 ، 50) ؛ display.print ("GAME") ؛ نغمة (SND ، 1000 ، 50) ؛ display.print ("OVER") ؛ if (playscore> = highscore) // تحقق لمعرفة ما إذا كانت النتيجة أعلى من الدرجة العالية {highscore = playscore؛ // single if statment لتحديث الدرجة العالية} لـ (int i = 0؛ i <= 16؛ i ++) // هذا هو رسم مستطيلات حول اللعبة على {display.drawRect (rectX1، rectY1، rectX2، rectY2، WHITE)؛ Serial.println ("if loop") ؛ display.display () ، RectX1- = 2 ؛ // إزاحة بمقدار 2 بكسل rectY1- = 2؛ RectX2 + = 4 ؛ // التحول أكثر من 2 بكسل من النقطة الأخيرة ، المستقيم Y2 + = 4 ؛ نغمة (SND ، أنا * 200 ، 3) ؛ } display.display () ، // مسح الشاشة بعد الشهرة على RectX1 = 0 ؛ // تعيين موضع بداية الخط المستقيم Y1 = 0 ؛ RectX2 = 0 ؛ RectY2 = 63 ؛ لـ (int i = 0 ؛ i <= 127 ؛ i ++) {uint8_t cnt = 0 ؛ display.drawLine (rectX1، rectY1، rectX2، rectY2، أسود) ؛ RectX1 ++ ؛ RectX2 ++ ؛ display.display () ، } display.clearDisplay ()؛ playcore = 0 ؛ // إعادة تعيين تفاصيل الثعبان واللاعبين snakeSize = 1 ؛ snakeX = display.width () / 2 ؛ ثعبان Y = display.height () / 2 ؛ waitForPress () ، // انتظر حتى يبدأ اللاعب اللعبة} // ------------------------- انتظر حلقة الضغط ---------- --------------- void waitForPress () {bool waiting = 0؛ // تنتهي الحلقة عندما يكون هذا عرضًا حقيقيًا.clearDisplay () ؛ أثناء (انتظار == 0) {drawALineForMe (WHITE) ؛ // رسم خط أبيض عشوائي drawALineForMe (أسود) ؛ // ارسم خطًا أسود عشوائيًا بحيث لا تملأ الشاشة الشاشة البيضاء بالكامل. // خلفية فارغة لعرض النص. setTextColor (WHITE) ؛ display.setCursor (35 ، 25) ؛ display.setTextSize (2) ، // عرض خط أكبر. println ("SNAKE") ؛ // x y w h r col display.drawRoundRect (33، 22، 62، 20، 4، WHITE) ؛ // عرض ثعبان الحدود. رسم مستطيل (19 ، 20 ، 90 ، 32 ، أبيض) ؛ // مربع الحدود - 3 شاشات عرض. setCursor (28 ، 42) ؛ display.setTextSize (0) ، // عودة الخط إلى العرض العادي. println ("اضغط على أي مفتاح") ؛ display.display () ، انتظار = digitalRead (INTPIN) ؛ // تحقق لمعرفة ما إذا كان الضغط على المفتاح في الانتظار سيتغير إلى 1 ينتهي أثناء الضغط على الأزرار = 0 ؛ // reset button press}} // -------------------- رسم لون إدخال سطر عشوائي uint8_t -------------- ----- باطل drawALineForMe (uint8_t clr) {uint8_t line1X، line1Y، line2X، line2Y = 0 ؛ // قم بتعيين إحداثيات عشوائية لخط ثم ارسمه // متغير لا يقل عن line1X = عشوائي (worldMinX + 1 ، worldMaxX-1) ؛ line1Y = عشوائي (worldMinY + 1، worldMaxY-1) ؛ line2X = عشوائي (worldMinX + 1 ، worldMaxX-1) ؛ line2Y = عشوائي (worldMinY + 1، worldMaxY-1) ؛ display.drawLine (line1X، line1Y، line2X، line2Y، clr) ؛ } // ------------------------------------- كشف الاصطدام -------- -----------------------

لـ (byte i = 4؛ i <snakeSize؛ i ++) {if (snakeX == snakePosX && snakeY == snakePosy ) {return 1؛ نغمة (SND ، 2000 ، 20) ؛ نغمة (SND ، 1000 ، 20) ؛ } إرجاع 0؛ }

//-------------------------------- اقامة--------------- -------------------------------

إعداد باطل () {delay (100) ؛ // فقط امنح الأشياء فرصة "التمهيد" // Serial.begin (9600) ؛ // قم بإلغاء تحديد هذا إذا كنت تريد رؤية عرض المخرجات التسلسلية. display.clearDisplay () ، // ابدأ بشاشة عرض نظيفة. setTextColor (WHITE) ؛ // قم بإعداد حجم دوران لون النص وما إلى ذلك display.setRotation (0) ؛ display.setTextWrap (خطأ) ؛ display.dim (0) ؛ // قم بتعيين وضع pinMode للعرض (INTPIN ، INPUT) ؛ / / تعيين المنافذ الصحيحة لإدخال pinMode (UPPIN ، INPUT) ؛ pinMode (DWNPIN ، INPUT) ؛ pinMode (LFTPIN ، INPUT) ؛ pinMode (RHTPIN ، INPUT) ؛ // هذا هو أمر interupt هذا "يوقف" اردوينو لقراءة المدخلات // command- function- pin-function لتنفيذ- الشرط على pin attachInterrupt (digitalPinToInterrupt (INTPIN)، interruptpressed، RISING) ؛ // Serial.println ("تم اجتياز الإعداد") ؛ waitForPress () ، // عرض شاشة بدء تشغيل الثعبان placeScran () ؛ // ضع الجزء الأول من الطعام} // --------------------- الحلقة الرئيسية ----------------- ---------------------- حلقة فارغة () {updateGame () ؛ // هذه الوظيفة هي ما يحمل الكود الرئيسي}

الخطوه 3:

موصى به: