תוכן עניינים:

משחק פלטפורמה מבוקר Arduino עם ג'ויסטיק ומקלט IR: 3 שלבים (עם תמונות)
משחק פלטפורמה מבוקר Arduino עם ג'ויסטיק ומקלט IR: 3 שלבים (עם תמונות)

וִידֵאוֹ: משחק פלטפורמה מבוקר Arduino עם ג'ויסטיק ומקלט IR: 3 שלבים (עם תמונות)

וִידֵאוֹ: משחק פלטפורמה מבוקר Arduino עם ג'ויסטיק ומקלט IR: 3 שלבים (עם תמונות)
וִידֵאוֹ: מה אתם מעדיפים? (שאלות מטורפות בהגזמה!) 2024, יולי
Anonim
משחק פלטפורמה מבוקר Arduino עם ג'ויסטיק ומקלט IR
משחק פלטפורמה מבוקר Arduino עם ג'ויסטיק ומקלט IR

היום נשתמש במיקרו-בקר Arduino לשליטה במשחק פשוט מבוסס C#. אני משתמש ב- Arduino כדי לקבל קלט ממודול ג'ויסטיק ולשלוח את הקלט הזה ליישום C# שמקשיב ומפענח קלט בחיבור סידורי. למרות שאינך זקוק לניסיון קודם בבניית משחקי וידיאו כדי להשלים את הפרויקט, זה עשוי לדרוש זמן מה כדי לספוג כמה מהדברים המתרחשים ב"לולאת המשחקים ", עליה נדון בהמשך.

כדי להשלים פרויקט זה, תזדקק ל:

  • קהילת Visual Studio
  • אונו ארדואינו (או דומה)
  • מודול בקר ג'ויסטיק
  • סבלנות

אם אתה מוכן להתחיל, המשך!

שלב 1: חבר את הג'ויסטיק ונורית ה- IR

חיבר את הג'ויסטיק ואת נורית ה- IR
חיבר את הג'ויסטיק ואת נורית ה- IR
חיבר את הג'ויסטיק ונורית ה- IR
חיבר את הג'ויסטיק ונורית ה- IR

כאן, החיבור הוא די פשוט. כללתי דיאגרמות המראות רק את הג'ויסטיק המחובר, כמו גם את ההתקנה שבה אני משתמש, הכולל את הג'ויסטיק בתוספת נורית אינפרא אדום לשליטה במשחק עם שלט רחוק, המגיע עם ערכות ארדואינו רבות. זה אופציונלי, אבל זה נראה כמו רעיון מגניב להיות מסוגל לעשות משחקים אלחוטיים.

הסיכות המשמשות בהתקנה הן:

  • A0 (אנלוגי) <- אופקי או ציר X
  • A1 (אנלוגי) <- ציר אנכי או Y
  • פין 2 <- קלט מתג ג'ויסטיק
  • פין 2 <- כניסת LED אינפרא אדום
  • VCC <- 5V
  • קרקע, אדמה
  • קרקע מס '2

שלב 2: צור סקיצה חדשה

צור סקיצה חדשה
צור סקיצה חדשה

נתחיל ביצירת קובץ הסקיצות של Arduino. זה סוקר את הג'ויסטיק לשינויים ושולח את השינויים האלה לתוכנית C# כל כמה אלפיות השנייה. במשחק וידיאו בפועל, היינו בודקים את היציאה הסדרתית בלולאת משחקים לאיתור קלט, אבל התחלתי את המשחק כניסוי, כך שמספר המסגרות מבוסס למעשה על מספר האירועים ביציאה הסדרתית. למעשה התחלתי את הפרויקט בפרויקט האחות Arduino, עיבוד, אבל מסתבר שהוא היה הרבה הרבה יותר איטי ולא יכול היה להתמודד עם מספר הקופסאות על המסך.

אז תחילה צור סקיצה חדשה בתוכנית עורך הקוד של Arduino. אני אראה את הקוד שלי ואז אסביר מה הוא עושה:

#כלול "IRremote.h"

// משתני IR int מקלט = 3; // סיכת אות של מקלט IR IRrecv irrecv (מקלט); // ליצור מופע של תוצאות decode_results של 'irrecv'; // צור מופע של '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 לחכות בין ההודעות [הערה: המתנה נמוכה יותר = מסגרת מהירה יותר] button bool נדיף Butpressed = false; // מד אם נלחץ על הלחצן void setup () {Serial.begin (9600); pinMode (joySwitch, INPUT_PULLUP); attachInterrupt (0, קפיצה, נפילה); הנוכחי = מילי (); // הגדר את השעה הנוכחית // הגדר מקלט אינפרא אדום: irrecv.enableIRIn (); // הפעל את המקלט} // הגדר לולאת חלל () {int xMovement = analogRead (joyXPin); int yPos = analogRead (joyYPin); // לטפל בתנועת הג'ויסטיק X ללא קשר לתזמון: אם (xMovement> minMoveHigh || xMovement הנוכחי + המתן) {currentSpeed = yPos> minMoveLow && yPos <minMoveHigh // אם רק זז קצת …? 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;} אחרת אם (yPos> minMoveHigh) // מתפרש "למטה" {// הגנה מפני עובר תחת 0 החזר currentSpeed - speedIncrement <0? 0: currentSpeed - speedIncrement;}} // getSpeed void jump () {buttonPressed = true; // ציין לחצן.} // קפיצה // כאשר לוחצים על כפתור על מרחוק, לטפל בתגובה הנכונה void translateIR (decode_results 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; break; case 0xFF4AB5: //Serial.println("8 "); currentSpeed -= speedIncrement * 2; break; ברירת מחדל: //Serial.println (" כפתור אחר "); break;} // End switch} // END translateIR

ניסיתי ליצור את הקוד שיהיה ברובו מובן מאליו, אבל יש כמה דברים שכדאי להזכיר. דבר אחד שניסיתי להסביר הוא בשורות הבאות:

int minYMoveUp = 520;

int minYMoveDown = 500;

כאשר התוכנית פועלת, הקלט האנלוגי מהג'ויסטיק נוטה לקפוץ מסביב, בדרך כלל להישאר בסביבות 507. כדי לתקן זאת, הקלט אינו משתנה אלא אם הוא גדול מ- minYMoveUp או קטן מ- minYMoveDown.

pinMode (joySwitch, INPUT_PULLUP);

attachInterrupt (0, קפיצה, נפילה);

שיטת ה- attachInterrupt () מאפשרת לנו לקטוע את הלולאה הרגילה בכל עת, כך שנוכל לקחת קלט, כמו לחיצה על הלחצן בלחיצה על כפתור הג'ויסטיק. כאן, צירפנו את הפסיקה בשורה שלפניה, בשיטת pinMode (). הערה חשובה כאן היא שעל מנת לצרף הפרעה ב- Arduino Uno, עליך להשתמש בסיכה 2 או ב -3 דגמים אחרים משתמשים בסיכות הפרעה שונות, כך שתצטרך לבדוק באילו סיכות הדגם שלך משתמש באתר Arduino. הפרמטר השני הוא לשיטת החזרה, המכונה כאן ISR או "שגרת שירות קטיעה". זה לא אמור לקחת פרמטרים או להחזיר שום דבר.

Serial.print (…)

זהו הקו שישלח את הנתונים שלנו למשחק C#. כאן אנו שולחים את קריאת ציר ה- X, קריאת ציר ה- Y ומשתנה מהירות למשחק. ניתן להרחיב את הקריאות הללו כך שיכללו תשומות וקריאות אחרות כדי להפוך את המשחק למעניין יותר, אך כאן נשתמש רק בזוג.

אם אתה מוכן לבדוק את הקוד שלך, העלה אותו ל- Arduino ולחץ על [Shift] + [Ctrl] + [M] כדי לפתוח את הצג הטורי ולבדוק אם אתה מקבל פלט כלשהו. אם אתה מקבל נתונים מהארדואינו, אנו מוכנים לעבור לחלק C# של הקוד …

שלב 3: צור את פרויקט C#

כדי להציג את הגרפיקה שלנו, התחלתי בתחילה פרוייקט בעיבוד, אך מאוחר יותר החלטתי שיהיה איטי מדי להציג את כל האובייקטים שאנחנו צריכים להציג. לכן בחרתי להשתמש ב- C#, שהתברר כהרבה יותר חלק ומגיב יותר בעת הטיפול בקלט שלנו.

עבור חלק ה- C# של הפרויקט, עדיף פשוט להוריד את קובץ ה- zip ולחלץ אותו לתיקייה שלו ולאחר מכן לשנות אותו. יש שתי תיקיות בקובץ ה- zip. כדי לפתוח את הפרויקט ב- Visual Studio, הזן את תיקיית RunnerGame_CSharp בסייר Windows. כאן, לחץ פעמיים על קובץ.sln (פתרון) ו- VS יטען את הפרויקט.

יש כמה שיעורים שונים שיצרתי למשחק. לא אכנס לכל הפרטים על כל כיתה, אבל אתן סקירה כללית של מה השיעורים העיקריים מיועדים.

מחלקת הקופסאות

יצרתי את מחלקת התיבות כדי לאפשר לך ליצור אובייקטים מלבניים פשוטים אותם ניתן לצייר על המסך בצורה של חלונות. הרעיון הוא ליצור כיתה שניתן להרחיב באמצעות שיעורים אחרים שאולי ירצו לצייר גרפיקה כלשהי. מילת המפתח ה"וירטואלית "משמשת כך שמעמדות אחרים עשויים לעקוף אותם (באמצעות מילת המפתח" לעקוף "). כך נוכל לקבל את אותה התנהגות עבור מחלקת השחקנים ומחלקת הפלטפורמה כשצריך, וגם לשנות את האובייקטים כפי שאנחנו צריכים.

אל תדאג יותר מדי לגבי כל הנכסים ותמשוך שיחות. כתבתי את השיעור הזה כדי שאוכל להרחיב אותו לכל משחק או תוכנית גרפית שאולי ארצה לעשות בעתיד. אם אתה פשוט צריך לצייר מלבן תוך כדי תנועה, אתה לא צריך לכתוב מחלקה גדולה כזאת. לתיעוד C# יש דוגמאות טובות כיצד לעשות זאת.

עם זאת, אפרט חלק מההיגיון בשיעור "תיבה" שלי:

bool וירטואלי ציבורי IsCollidedX (Box otherObject) {…}

כאן אנו בודקים התנגשויות עם חפצים בכיוון X, כי השחקן צריך לבדוק רק אם יש התנגשויות בכיוון Y (למעלה ולמטה) אם הוא מסודר איתו על המסך.

bool וירטואלי ציבורי IsCollidedY (Box otherObject) {…}

כאשר אנו מעל או מתחת לחפץ משחק אחר, אנו בודקים אם יש התנגשויות Y.

bool וירטואלי ציבורי 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 ("פורטים זמינים:" + יציאה);

אנו בוחרים באיזה מהם נקבל תקשורת, על פי היציאה שהארדואינו שלך כבר משתמש בה:

SerialPort = SerialPort חדש (SerialPort. GetPortNames () [2], 9600, Parity. None, 8, StopBits. One);

שימו לב לפקודה: SerialPort. GetPortNames () [2]. ה- [2] מסמן באיזה יציאה טורית להשתמש. לדוגמה, אם התוכנית מדפיסה את "COM1, COM2, COM3", היינו מקשיבים ב- COM3 מכיוון שהמספור מתחיל ב -0 במערך.

גם בבנאי, אנו יוצרים את כל הפלטפורמות עם ריווח אקראי למחצה ומיקום בכיוון Y על המסך. כל הפלטפורמות מתווספות לאובייקט רשימה, שב- C# היא פשוט דרך מאוד ידידותית למשתמש ויעילה לנהל מבנה נתונים דמוי מערך. לאחר מכן אנו יוצרים את השחקן, שהוא אובייקט הדמות שלנו, מגדירים את הציון ל- 0 ומגדירים את GameOver כ- false.

private static void DataReceived (שולח אובייקט, SerialDataReceivedEventArgs e)

זוהי השיטה הנקראת כאשר מתקבלים נתונים ביציאה הטורית. כאן אנו מיישמים את כל הפיזיקה שלנו, מחליטים אם להציג את המשחק מחדש, להזיז את הפלטפורמות וכו '. אם אי פעם בנית משחק, בדרך כלל יש לך מה שנקרא "לולאת משחקים", הנקראת בכל פעם שהמסגרת מרענן. במשחק זה, שיטת ה- DataReceived פועלת כלולאת המשחק, ורק מניפולציות בפיזיקה כאשר נתונים מתקבלים מהבקר. אולי זה עבד טוב יותר להגדיר טיימר בחלון הראשי ולרענן את האובייקטים על סמך הנתונים שהתקבלו, אך מכיוון שמדובר בפרויקט של ארדואינו, רציתי ליצור משחק שרץ למעשה על סמך הנתונים שנכנסים ממנו.

לסיכום, התקנה זו נותנת בסיס טוב להרחבת המשחק למשהו שמיש. למרות שהפיזיקה לא ממש מושלמת, היא פועלת מספיק טוב למטרות שלנו, כלומר להשתמש בארדואינו למשהו שכולם אוהבים: משחקים!

מוּמלָץ: