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

لعبة منصات يتحكم فيها الأردوينو مع عصا تحكم وجهاز استقبال الأشعة تحت الحمراء: 3 خطوات (مع صور)
لعبة منصات يتحكم فيها الأردوينو مع عصا تحكم وجهاز استقبال الأشعة تحت الحمراء: 3 خطوات (مع صور)

فيديو: لعبة منصات يتحكم فيها الأردوينو مع عصا تحكم وجهاز استقبال الأشعة تحت الحمراء: 3 خطوات (مع صور)

فيديو: لعبة منصات يتحكم فيها الأردوينو مع عصا تحكم وجهاز استقبال الأشعة تحت الحمراء: 3 خطوات (مع صور)
فيديو: تهكير عداد الكهرباء الجديد 1% وداعا الاستهلاك 2024, يوليو
Anonim
لعبة منهاج يتحكم فيها الأردوينو مع عصا تحكم وجهاز استقبال الأشعة تحت الحمراء
لعبة منهاج يتحكم فيها الأردوينو مع عصا تحكم وجهاز استقبال الأشعة تحت الحمراء

اليوم ، سنستخدم متحكم Arduino للتحكم في لعبة بسيطة تعتمد على C #. أنا أستخدم Arduino لأخذ مدخلات من وحدة عصا التحكم ، وإرسال هذا الإدخال إلى تطبيق C # الذي يستمع ويفك تشفير الإدخال عبر اتصال تسلسلي. على الرغم من أنك لا تحتاج إلى أي خبرة سابقة في بناء ألعاب الفيديو لإكمال المشروع ، فقد يتطلب الأمر بعض الوقت لاستيعاب بعض الأشياء التي تحدث في "حلقة اللعبة" ، والتي سنناقشها لاحقًا.

لإكمال هذا المشروع ، سوف تحتاج إلى:

  • مجتمع Visual Studio
  • Arduino Uno (أو ما شابه)
  • وحدة تحكم جويستيك
  • الصبر

إذا كنت مستعدًا للبدء ، فاستمر!

الخطوة 1: اربط عصا التحكم و IR LED

اربط عصا التحكم و IR LED
اربط عصا التحكم و IR LED
اربط عصا التحكم و IR LED
اربط عصا التحكم و IR LED

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

المسامير المستخدمة في الإعداد هي:

  • A0 (تناظري) <- أفقي أو محور س
  • A1 (تناظري) <- المحور الرأسي أو المحور الصادي
  • دبوس 2 <- إدخال مفتاح جويستيك
  • دبوس 2 <- إدخال LED بالأشعة تحت الحمراء
  • VCC <- 5 فولت
  • أرضي
  • الأرض رقم 2

الخطوة 2: إنشاء رسم جديد

قم بإنشاء رسم جديد
قم بإنشاء رسم جديد

سنبدأ بإنشاء ملف رسم Arduino الخاص بنا. هذا يستقصي عصا التحكم للتغييرات ، ويرسل تلك التغييرات إلى برنامج C # كل عدة أجزاء من الثانية. في لعبة فيديو فعلية ، كنا نتحقق من المنفذ التسلسلي في حلقة اللعبة من أجل الإدخال ، لكنني بدأت اللعبة كتجربة ، لذا فإن معدل الإطارات يعتمد في الواقع على عدد الأحداث على المنفذ التسلسلي. لقد بدأت بالفعل المشروع في مشروع Arduino الشقيق ، المعالجة ، لكن اتضح أنه كان أبطأ بكثير ، ولم أستطع التعامل مع عدد الصناديق على الشاشة.

لذلك ، قم أولاً بإنشاء Sketch جديد في برنامج محرر كود Arduino. سأعرض الكود الخاص بي ثم أشرح ما يفعله:

# تضمين "IRremote.h"

// متغيرات IR int المتلقي = 3 ؛ // إشارة دبوس لجهاز استقبال الأشعة تحت الحمراء IRrecv irrecv (المتلقي) ؛ // إنشاء مثيل من نتائج decode_results "irrecv" ؛ // إنشاء مثيل لـ 'decode_results' // متغيرات جويستيك / اللعبة int xPos = 507 ؛ int yPos = 507 ؛ البايت joyXPin = A0 ؛ البايت joyYPin = A1 ؛ بايت joySwitch = 2 ؛ انقر فوق عداد البايت المتغير = -1 ؛ كثافة int minMoveHigh = 530 ؛ int minMoveLow = 490 ؛ int currentSpeed = 550 ؛ // الافتراضي = متوسط السرعة int speedIncrement = 25 ؛ // المقدار لزيادة / تقليل السرعة مع إدخال Y تيار طويل بدون إشارة = 0 ؛ // يحمل الطابع الزمني الحالي int انتظار = 40 ؛ // مللي ثانية للانتظار بين الرسائل [ملاحظة: انتظار أقل = معدل إطارات أسرع] زر منطقي متغير الضغط = خطأ ؛ // قياس ما إذا تم الضغط على الزر إعداد باطل () {Serial.begin (9600) ؛ pinMode (joySwitch ، INPUT_PULLUP) ؛ attachInterrupt (0، jump، FALLING)؛ التيار = ملي () ؛ // إعداد الوقت الحالي // إعداد مستقبل الأشعة تحت الحمراء: irrecv.enableIRIn () ؛ // Start the Receiver} // setup void loop () {int xMovement = analogRead (joyXPin)؛ int yPos = analogRead (joyYPin) ؛ // التعامل مع حركة Joystick X بغض النظر عن التوقيت: if (xMovement> minMoveHigh || xMovement current + wait) {currentSpeed = yPos> minMoveLow && yPos <minMoveHigh // إذا تحرك قليلاً …؟ CurrentSpeed //… فقط أعد السرعة الحالية: getSpeed (yPos) ؛ // قم بتغيير yPos فقط إذا تحركت عصا التحكم بشكل كبير // int مسافة = ؛ Serial.print ((سلسلة) xPos + "،" + (سلسلة) yPos + '،' + (سلسلة) currentSpeed + '\ n')؛ التيار = ملي () ؛ }} // loop int getSpeed (int yPos) {// تشير القيم السالبة إلى أن جويستيك قد تحرك لأعلى إذا (yPos 1023؟ 1023: currentSpeed + speedIncrement؛} else if (yPos> minMoveHigh) // Interpreted "Down" {// Protect from الذهاب ضمن 0 return currentSpeed - speedIncrement <0؟ 0: currentSpeed - speedIncrement؛}} // getSpeed void jump () {buttonPressed = true؛ // تم الضغط على زر الإشارة.} // Jump // عند الضغط على زر في عن بعد ، تعامل مع الاستجابة المناسبة void translateIR (نتائج decode_results) // يتخذ إجراء بناءً على رمز IR المتلقى {switch (results.value) {case 0xFF18E7: //Serial.println("2 ")؛ currentSpeed + = speedIncrement * 2 ؛ كسر ؛ الحالة 0xFF10EF: //Serial.println("4 ") ؛ xPos = -900 ؛ كسر ؛ الحالة 0xFF38C7: //Serial.println("5") ؛ قفزة () ؛ استراحة ؛ الحالة 0xFF5AA5: // Serial. println ("6") ؛ xPos = 900 ؛ كسر ؛ الحالة 0xFF4AB5: //Serial.println("8 ") ؛ currentSpeed - = speedIncrement * 2 ؛ break ؛ افتراضي: //Serial.println (" زر آخر ") ؛ استراحة ؛} // End switch} // END translateIR

حاولت إنشاء الكود ليكون في الغالب واضحًا بذاته ، ولكن هناك بعض الأشياء الجديرة بالذكر. كان الشيء الوحيد الذي حاولت تفسيره في الأسطر التالية:

عدد int minYMoveUp = 520 ؛

int minYMoveDown = 500 ؛

عندما يكون البرنامج قيد التشغيل ، فإن المدخلات التناظرية من عصا التحكم تميل إلى القفز ، وعادة ما تبقى عند حوالي 507. لتصحيح ذلك ، لا يتغير الإدخال ما لم يكن أكبر من minYMoveUp ، أو أصغر من minYMoveDown.

pinMode (joySwitch ، INPUT_PULLUP) ؛

attachInterrupt (0، jump، FALLING)؛

تسمح لنا طريقة attachInterrupt () بمقاطعة الحلقة العادية في أي وقت ، حتى نتمكن من أخذ المدخلات ، مثل الضغط على الزر عند النقر فوق زر عصا التحكم. هنا ، قمنا بإرفاق المقاطعة في السطر قبلها ، باستخدام طريقة pinMode (). ملاحظة مهمة هنا هي أنه لإرفاق مقاطعة على Arduino Uno ، يجب عليك استخدام إما pin 2 أو 3. تستخدم الطرز الأخرى دبابيس مقاطعة مختلفة ، لذلك قد تضطر إلى التحقق من الدبابيس التي يستخدمها نموذجك على موقع Arduino على الويب. المعلمة الثانية هي لأسلوب رد الاتصال ، ويسمى هنا ISR أو "Interrupt Service Routine". لا ينبغي أن يأخذ أي معلمات أو يعيد أي شيء.

Serial.print (…)

هذا هو الخط الذي سيرسل بياناتنا إلى لعبة C #. هنا ، نرسل قراءة المحور X ، وقراءة المحور Y ، ومتغير السرعة إلى اللعبة. يمكن توسيع هذه القراءات لتشمل مدخلات وقراءات أخرى لجعل اللعبة أكثر إثارة ، ولكن هنا ، سنستخدم زوجًا فقط.

إذا كنت مستعدًا لاختبار الكود الخاص بك ، فقم بتحميله على Arduino ، واضغط على [Shift] + [Ctrl] + [M] لفتح الشاشة التسلسلية ومعرفة ما إذا كنت تحصل على أي إخراج. إذا كنت تتلقى بيانات من Arduino ، فنحن مستعدون للانتقال إلى الجزء C # من الكود …

الخطوة 3: أنشئ مشروع C #

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

بالنسبة للجزء C # من المشروع ، من الأفضل تنزيل ملف.zip واستخراجه إلى المجلد الخاص به ، ثم تعديله. يوجد مجلدين في الملف المضغوط. لفتح المشروع في Visual Studio ، أدخل مجلد RunnerGame_CSharp في مستكشف Windows. هنا ، انقر نقرًا مزدوجًا فوق ملف.sln (الحل) ، وسيقوم VS بتحميل المشروع.

هناك عدد قليل من الفئات المختلفة التي قمت بإنشائها للعبة. لن أخوض في جميع التفاصيل حول كل فصل ، لكنني سأقدم لمحة عامة عن الغرض من الفصول الرئيسية.

فئة الصندوق

لقد أنشأت فئة الصندوق للسماح لك بإنشاء كائنات مستطيلة بسيطة يمكن رسمها على الشاشة في نموذج windows. الفكرة هي إنشاء فصل دراسي يمكن تمديده باستخدام فئات أخرى قد ترغب في رسم نوع من الرسومات. يتم استخدام الكلمة الأساسية "الافتراضية" بحيث يمكن للفئات الأخرى تجاوزها (باستخدام الكلمة الأساسية "تجاوز"). بهذه الطريقة ، يمكننا الحصول على نفس السلوك لفئة Player وفئة النظام الأساسي عندما نحتاج إلى ذلك ، وكذلك تعديل الكائنات كما نحتاج إلى ذلك.

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

ومع ذلك ، سوف أضع بعض منطق صفي "Box":

منطقي افتراضي عام IsCollidedX (Box otherObject) {…}

هنا نتحقق من الاصطدامات مع الأشياء في الاتجاه X ، لأن اللاعب يحتاج فقط إلى التحقق من الاصطدامات في الاتجاه Y (لأعلى ولأسفل) إذا كان يصطف معها على الشاشة.

منطقي افتراضي عام IsCollidedY (Box otherObject) {…}

عندما نكون على أو تحت كائن لعبة آخر ، فإننا نتحقق من اصطدام Y.

منطقي افتراضي عام IsCollided (Box otherObject) {…}

هذا يجمع بين اصطدام X و Y ، ويعيد ما إذا كان أي كائن قد اصطدم بهذا.

الفراغ الظاهري العام OnPaint (رسومات الرسومات) {…}

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

فئة الشخصية

تعمل فئة الأحرف على توسيع فئة Box الخاصة بي ، لذلك لدينا فيزياء معينة خارج الصندوق. لقد أنشأت طريقة "CheckForCollisions" للتحقق بسرعة من جميع الأنظمة الأساسية التي أنشأناها من أجل حدوث تصادم. تحدد طريقة "Jump" سرعة اللاعب الصعودية إلى متغير JumpSpeed ، والذي يتم تعديله بعد ذلك إطارًا بإطار في فئة MainWindow.

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

فئة المنصة

في هذه اللعبة ، لا أستخدم سوى مُنشئ هذه الفئة الذي يأخذ إحداثي X كمدخل ، ويحسب جميع مواقع X الخاصة بالمنصات في فئة MainWindow. يتم إعداد كل منصة على تنسيق Y عشوائي من 1/2 الشاشة إلى 3/4 ارتفاع الشاشة. يتم أيضًا إنشاء الارتفاع والعرض واللون بشكل عشوائي.

فئة MainWindow

هذا هو المكان الذي نضع فيه كل المنطق لاستخدامه أثناء تشغيل اللعبة. أولاً ، في المُنشئ ، نقوم بطباعة جميع منافذ COM المتاحة للبرنامج.

foreach (منفذ سلسلة في SerialPort. GetPortNames ())

Console. WriteLine ("المنافذ المتوفرة:" + المنفذ) ؛

نختار أي منفذ سنقبل الاتصالات عليه ، وفقًا للمنفذ الذي يستخدمه Arduino بالفعل:

SerialPort = منفذ تسلسلي جديد (SerialPort. GetPortNames () [2] ، 9600 ، Parity. None ، 8 ، StopBits. One) ؛

انتبه جيدًا للأمر: SerialPort. GetPortNames () [2]. يشير [2] إلى أي منفذ تسلسلي يجب استخدامه. على سبيل المثال ، إذا قام البرنامج بطباعة "COM1، COM2، COM3" ، فإننا سنستمع إلى COM3 لأن الترقيم يبدأ من 0 في المصفوفة.

في المُنشئ أيضًا ، نقوم بإنشاء جميع الأنظمة الأساسية بمسافات شبه عشوائية ووضعها في اتجاه Y على الشاشة. تتم إضافة جميع الأنظمة الأساسية إلى كائن List ، والذي يعد في C # طريقة سهلة الاستخدام وفعالة للغاية لإدارة بنية بيانات تشبه المصفوفة. نقوم بعد ذلك بإنشاء Player ، وهو كائن الشخصية لدينا ، وقمنا بتعيين النتيجة إلى 0 وضبط GameOver على false.

DataReceived باطل ثابت خاص (مرسل الكائن ، SerialDataReceivedEventArgs e)

هذه هي الطريقة التي يتم استدعاؤها عند تلقي البيانات على المنفذ التسلسلي. هذا هو المكان الذي نطبق فيه جميع فيزياءنا ، ونقرر ما إذا كنت تريد عرض اللعبة مرة أخرى ، أو تحريك المنصات ، وما إلى ذلك. إذا كنت قد أنشأت لعبة من قبل ، فلديك عمومًا ما يسمى "حلقة اللعبة" ، والتي تسمى في كل مرة الإطار ينعش. في هذه اللعبة ، تعمل طريقة DataReceived كحلقة لعبة ، وتتلاعب فقط بالفيزياء عند تلقي البيانات من وحدة التحكم. ربما كان من الأفضل إعداد Timer في النافذة الرئيسية ، وتحديث الكائنات بناءً على البيانات المستلمة ، ولكن نظرًا لأن هذا مشروع Arduino ، فقد أردت إنشاء لعبة تعمل بالفعل بناءً على البيانات الواردة منه.

في الختام ، يوفر هذا الإعداد أساسًا جيدًا لتوسيع اللعبة إلى شيء يمكن استخدامه. على الرغم من أن الفيزياء ليست مثالية تمامًا ، إلا أنها تعمل جيدًا بما يكفي لأغراضنا ، وهو استخدام Arduino في شيء يحبه الجميع: ممارسة الألعاب!

موصى به: