فهرست مطالب:

بازی Platformer کنترل شده با آردوینو با جوی استیک و گیرنده IR: 3 مرحله (همراه با تصاویر)
بازی Platformer کنترل شده با آردوینو با جوی استیک و گیرنده IR: 3 مرحله (همراه با تصاویر)

تصویری: بازی Platformer کنترل شده با آردوینو با جوی استیک و گیرنده IR: 3 مرحله (همراه با تصاویر)

تصویری: بازی Platformer کنترل شده با آردوینو با جوی استیک و گیرنده IR: 3 مرحله (همراه با تصاویر)
تصویری: داستان غم انگیز Subway Surfers 2024, جولای
Anonim
بازی Platformer کنترل شده با آردوینو با جوی استیک و گیرنده IR
بازی Platformer کنترل شده با آردوینو با جوی استیک و گیرنده IR

امروز ، ما قصد داریم از یک میکروکنترلر آردوینو برای کنترل یک بازی ساده platformer مبتنی بر C#استفاده کنیم. من از آردوینو برای گرفتن ورودی از یک ماژول جوی استیک استفاده می کنم و آن ورودی را به برنامه C# ارسال می کنم که ورودی را از طریق اتصال سریال گوش می دهد و رمزگشایی می کند. اگرچه برای تکمیل پروژه نیازی به تجربه قبلی در ساخت بازی های ویدئویی ندارید ، اما ممکن است مدتی طول بکشد تا برخی از مواردی که در "حلقه بازی" اتفاق می افتد را جذب کنید ، که بعداً در مورد آنها صحبت خواهیم کرد.

برای تکمیل این پروژه به موارد زیر نیاز دارید:

  • Visual Studio Community
  • Arduino Uno (یا مشابه)
  • یک ماژول کنترل جوی استیک
  • صبر

اگر برای شروع آماده هستید ، ادامه دهید!

مرحله 1: جوی استیک و LED IR را وصل کنید

جوی استیک و LED IR را متصل کنید
جوی استیک و LED IR را متصل کنید
جوی استیک و LED IR را وصل کنید
جوی استیک و LED IR را وصل کنید

در اینجا ، اتصال بسیار ساده است. من نمودارهایی را نشان داده ام که فقط جوی استیک متصل شده است ، و همچنین تنظیماتی که من استفاده می کنم ، شامل جوی استیک به علاوه یک LED مادون قرمز برای کنترل بازی با کنترل از راه دور است که همراه با بسیاری از کیت های آردوینو ارائه شده است. این اختیاری است ، اما به نظر می رسید ایده خوبی برای انجام بازی های بی سیم باشد.

پین های مورد استفاده در تنظیمات عبارتند از:

  • A0 (آنالوگ) <- افقی یا محور X
  • A1 (آنالوگ) <- محور عمودی یا Y
  • پین 2 <- ورودی سوئیچ جوی استیک
  • پین 2 <- ورودی LED مادون قرمز
  • VCC <- 5V
  • زمین
  • زمین شماره 2

مرحله 2: یک طرح جدید ایجاد کنید

یک طرح جدید ایجاد کنید
یک طرح جدید ایجاد کنید

ما با ایجاد فایل طرح آردوینو شروع می کنیم. این جوی استیک تغییرات را بررسی می کند و این تغییرات را هر چند میلی ثانیه به برنامه C# ارسال می کند. در یک بازی ویدیویی واقعی ، ما پورت سریال را در یک حلقه بازی برای ورود بررسی می کنیم ، اما من بازی را به صورت آزمایشی آغاز کردم ، بنابراین نرخ فریم در واقع بر اساس تعداد رویدادها در پورت سریال است. من در واقع پروژه را در پروژه خواهر آردوینو ، Processing ، آغاز کرده بودم ، اما معلوم شد که بسیار بسیار کندتر بود و نمی توانست تعدادی جعبه روی صفحه را اداره کند.

بنابراین ، ابتدا یک Sketch جدید در برنامه ویرایشگر کد Arduino ایجاد کنید. من کد خود را نشان می دهم و سپس توضیح می دهم که چه کاری انجام می دهد:

#شامل "IRremote.h"

// متغیرهای IR int گیرنده = 3؛ // پین سیگنال گیرنده IR IRrecv irrecv (گیرنده) ؛ // ایجاد نمونه ای از نتایج 'irrecv' decode_results ؛ // ایجاد نمونه ای از 'decode_results' // جوی استیک/متغیرهای بازی int xPos = 507؛ int yPos = 507 ؛ بایت joyXPin = A0؛ بایت joyYPin = A1؛ بایت joySwitch = 2؛ بایت فرار clickCounter = -1؛ int minMoveHigh = 530؛ int minMoveLow = 490؛ int currentSpeed = 550؛ // پیش فرض = یک سرعت متوسط int speedIncrement = 25؛ // مقدار افزایش/کاهش سرعت با ورودی Y بدون جریان طولانی = 0 ؛ // دارای زمانبر فعلی int wait = 40؛ // ms برای انتظار بین پیامها [توجه: انتظار کمتر = سرعت فریم سریعتر] دکمه فرار boolPressed = false؛ // اگر دکمه فشار داده شده است اندازه گیری کنید void setup () {Serial.begin (9600)؛ pinMode (joySwitch ، INPUT_PULLUP) ؛ attachInterrupt (0 ، jump ، FALLING) ؛ جریان = میلی ()؛ // تنظیم زمان فعلی // راه اندازی گیرنده مادون قرمز: irrecv.enableIRIn ()؛ // گیرنده را راه اندازی کنید} // setup void loop () {int xMovement = analogRead (joyXPin)؛ int yPos = analogRead (joyYPin) ؛ // حرکت Joystick X را بدون توجه به زمان انجام دهید: currentSpeed //… فقط سرعت فعلی را برگردانید: getSpeed (yPos) ؛ // yPos را فقط در صورتی تغییر دهید که جوی استیک به طور قابل توجهی حرکت کرده باشد // int distance =؛ Serial.print ((String) xPos + "،" + (String) yPos + '،' + (String) currentSpeed + '\ n')؛ جریان = میلی ()؛ }} // loop int getSpeed (int yPos) {// مقادیر منفی نشان می دهد که جوی استیک به سمت بالا حرکت کرده است (yPos 1023؟ 1023: currentSpeed + speedIncrement؛} else if (yPos> minMoveHigh) // تفسیر "پایین" {// محافظت از رفتن زیر 0 بازگشت جریان از راه دور ، پاسخ مناسب را خالی کنید 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: // سریال. println ("6") ؛ xPos = 900 ؛ شکستن ؛ مورد 0xFF4AB5: //Serial.println("8 ")؛ currentSpeed -= speedIncrement * 2 ؛ شکستن ؛ پیش فرض: //Serial.println (" دکمه دیگر ") ؛ break؛} // 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 ، باید از پین 2 یا 3 استفاده کنید. سایر مدلها از پین های وقفه مختلف استفاده می کنند ، بنابراین ممکن است مجبور شوید بررسی کنید که مدل شما از کدام پین در وب سایت آردوینو استفاده می کند. پارامتر دوم مربوط به روش تماس مجدد است که در اینجا ISR یا "روال سرویس وقفه" نامیده می شود. نباید هیچ پارامتری داشته باشد یا چیزی را برگرداند.

Serial.print (…)

این خطی است که داده های ما را به بازی C# ارسال می کند. در اینجا ، خواندن محور X ، خواندن محور Y و یک متغیر سرعت را به بازی ارسال می کنیم. این قرائت ها را می توان برای ورودی ها و قرائت های دیگر افزایش داد تا بازی جذاب تر شود ، اما در اینجا ، ما فقط از دو استفاده می کنیم.

اگر آمادگی تست کد خود را دارید ، آن را در Arduino بارگذاری کنید و [Shift] + [Ctrl] + [M] را فشار دهید تا مانیتور سریال باز شود و ببینید خروجی دریافت می کنید یا خیر. اگر اطلاعاتی از آردوینو دریافت می کنید ، ما آماده حرکت به سمت قسمت C# کد هستیم…

مرحله 3: پروژه C# را ایجاد کنید

برای نمایش گرافیک ما ، ابتدا یک پروژه را در پردازش شروع کردم ، اما بعداً تصمیم گرفتم که نمایش همه اجسامی که برای نمایش نیاز داریم بسیار کند باشد. بنابراین ، من از C#استفاده کردم ، که هنگام کنترل ورودی ما بسیار روان تر و پاسخگوتر بود.

برای قسمت C# پروژه ، بهتر است فایل.zip را به سادگی بارگیری کرده و در پوشه خود استخراج کنید ، سپس آن را اصلاح کنید. دو پوشه در فایل زیپ وجود دارد. برای باز کردن پروژه در Visual Studio ، پوشه RunnerGame_CSharp را در Windows Explorer وارد کنید. در اینجا ، فایل.sln (راه حل) را دوبار کلیک کنید و VS پروژه را بارگیری می کند.

چند کلاس مختلف وجود دارد که من برای بازی ایجاد کردم. من به همه جزئیات مربوط به هر کلاس نمی پردازم ، اما مروری بر کلاسهای اصلی دارم.

کلاس جعبه

من کلاس جعبه را ایجاد کردم تا به شما امکان ایجاد اشیاء مستطیل ساده را بدهد که می توانند به شکل پنجره روی صفحه ترسیم شوند. ایده این است که یک کلاس ایجاد کنیم که با استفاده از کلاس های دیگر که ممکن است بخواهند نوعی گرافیک را ترسیم کنند ، قابل گسترش باشد. از کلمه کلیدی "مجازی" استفاده می شود تا کلاسهای دیگر آنها را نادیده بگیرند (با استفاده از کلمه کلیدی "لغو"). به این ترتیب ، ما می توانیم همان رفتار را برای کلاس Player و کلاس Platform در صورت نیاز داشته باشیم ، و همچنین اشیاء را هرطور که نیاز داریم تغییر دهیم.

نگران همه ویژگی ها نباشید و تماس بگیرید. من این کلاس را نوشتم تا بتوانم آن را برای هر بازی یا برنامه گرافیکی که می خواهم در آینده بسازم گسترش دهم. اگر نیاز دارید که به سادگی یک مستطیل را در حال حرکت بکشید ، لازم نیست یک کلاس بزرگ مانند این بنویسید. اسناد C# نمونه های خوبی از نحوه انجام این کار دارد.

با این حال ، من برخی از منطق کلاس "جعبه" خود را بیان می کنم:

بول مجازی عمومی IsCollidedX (Box otherObject) {…}

در اینجا ما برخورد با اجسام در جهت X را بررسی می کنیم ، زیرا بازیکن فقط باید در صورت برخورد با جهت Y (بالا و پایین) در صورت قرار گرفتن روی صفحه روی صفحه را بررسی کند.

بول مجازی عمومی IsCollidedY (Box otherObject) {…}

هنگامی که روی یک بازی دیگر یا زیر آن قرار داریم ، برخورد Y را بررسی می کنیم.

بول مجازی عمومی IsCollided (Box otherObject) {…}

این ترکیبی از برخورد X و Y است ، و اینکه آیا هر جسمی با این برخورد کرده است را برمی گرداند.

خلاء عمومی مجازی OnPaint (گرافیک گرافیکی) {…}

با استفاده از روش فوق ، هر شیء گرافیکی را وارد کرده و هنگام اجرای برنامه از آن استفاده می کنیم. ما مستطیل هایی را ایجاد می کنیم که ممکن است نیاز به کشیدن داشته باشند. با این حال ، این می تواند برای انیمیشن های مختلف استفاده شود. برای اهداف ما ، مستطیل ها هم برای سکوها و هم برای پخش کننده خوب عمل می کنند.

کلاس شخصیت

کلاس Character کلاس Box من را گسترش می دهد ، بنابراین ما فیزیک خاصی را خارج از جعبه داریم. من روش "CheckForCollisions" را برای بررسی سریع همه سیستم عامل هایی که برای برخورد ایجاد کرده ایم ، ایجاد کردم. روش "پرش" سرعت صعود بازیکن را به متغیر JumpSpeed تنظیم می کند ، که سپس فریم به فریم در کلاس MainWindow تغییر می کند.

برخوردها در اینجا کمی متفاوت از کلاس Box انجام می شود. من در این بازی تصمیم گرفتم که اگر به سمت بالا بپریم ، می توانیم از روی یک سکو بپریم ، اما در صورت برخورد با آن ، بازیکن ما را در راه پایین می گیرد.

کلاس پلتفرم

در این بازی ، من فقط از سازنده این کلاس که مختصات X را به عنوان ورودی می گیرد ، استفاده می کنم و تمام مکان های X سیستم عامل ها را در کلاس MainWindow محاسبه می کنم. هر پلت فرم در یک مختصات Y تصادفی از 1/2 صفحه تا 3/4 ارتفاع صفحه تنظیم شده است. ارتفاع ، عرض و رنگ نیز به طور تصادفی تولید می شوند.

کلاس MainWindow

اینجاست که ما تمام منطق را برای استفاده در حین اجرای بازی قرار می دهیم. ابتدا ، در سازنده ، تمام پورت های COM موجود در برنامه را چاپ می کنیم.

foreach (پورت رشته در SerialPort. GetPortNames ())

Console. WriteLine ("پورت های موجود:" + پورت) ؛

ما انتخاب می کنیم که با کدام یک از آنها ارتباطات را بپذیریم و بر اساس کدام پورت Arduino شما قبلاً از آن استفاده می کند:

SerialPort = جدید SerialPort (SerialPort. GetPortNames () [2] ، 9600 ، Parity. None ، 8 ، StopBits. One) ؛

به دستور: SerialPort. GetPortNames () [2] توجه زیادی داشته باشید. [2] نشان می دهد که از کدام پورت سریال استفاده کنید. به عنوان مثال ، اگر برنامه "COM1 ، COM2 ، COM3" را چاپ کند ، ما به COM3 گوش می دهیم زیرا شماره گذاری در 0 در آرایه شروع می شود.

همچنین در سازنده ، همه سکوها را با فاصله نیمه تصادفی و در جهت Y روی صفحه ایجاد می کنیم. همه سیستم عامل ها به یک شیء List اضافه می شوند که در C# به سادگی یک راه بسیار کاربر پسند و کارآمد برای مدیریت ساختار داده های آرایه ای است. سپس Player را که شی Character ما است ایجاد می کنیم ، نمره را روی 0 قرار می دهیم و GameOver را روی false قرار می دهیم.

خلأ استاتیک خصوصی DataReceived (ارسال کننده شی ، SerialDataReceivedEventArgs e)

این روشی است که هنگام دریافت داده ها در پورت سریال فراخوانی می شود. اینجاست که ما تمام فیزیک خود را به کار می گیریم ، تصمیم می گیریم که بازی را نمایش دهیم ، پلتفرم ها را منتقل کنیم یا غیره. تازه می کند در این بازی ، روش DataReceived به عنوان حلقه بازی عمل می کند ، فقط فیزیک را دستکاری می کند زیرا داده ها از کنترلر دریافت می شوند. شاید بهتر باشد یک تایمر در پنجره اصلی تنظیم کنید و اشیاء را بر اساس داده های دریافت شده تازه کنید ، اما از آنجا که این یک پروژه آردوینو است ، من می خواستم یک بازی بسازم که بر اساس داده هایی که از آن وارد می شود اجرا شود به

در نتیجه ، این تنظیمات زمینه خوبی برای گسترش بازی به چیزی قابل استفاده است. اگرچه فیزیک کاملاً کامل نیست ، اما برای اهداف ما به خوبی کار می کند ، یعنی استفاده از آردوینو برای کاری که همه دوست دارند: بازی کردن!

توصیه شده: