أبسط لعبة اردوينو مع شاشة 1602 - الجزء الثاني

الجزء الثاني من البداية إلى النهاية


نواصل صنع لعبة على arduino ثم نضع هذه اللعبة في البرنامج الذي أقوم به للسيارة وبناءً على معرفتنا ، سنقوم بإنشاء لعبة ثانية للمتعة ونصنع الموسيقى المناسبة لها.

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

قررنا الأشياء ، ودعنا نرسمها ، على الفور جميع العفاريت ونكتبها.





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

"--------------------------------------------------------------------------" //   : byte Player_1[SYMBOL_HEIGHT] = {B01110,B01110,B00100,B01110,B10101,B00100,B01110,B01010,}; //   : byte Player_2[SYMBOL_HEIGHT] = {B00000,B01110,B01110,B00100,B11111,B00100,B01110,B01010,}; // : byte Enemy_1[SYMBOL_HEIGHT] = {B00010,B00110,B10111,B10110,B11111,B00110,B00110,B11111,}; // : byte Heart_L[SYMBOL_HEIGHT] = {B00000,B01010,B11111,B11111,B11111,B01110,B00100,B00000,}; // : byte Heart_R[SYMBOL_HEIGHT] = {B00000,B00000,B01010,B11111,B01110,B00100,B00000,B00000,}; //  : byte Battery1[SYMBOL_HEIGHT] = {B01110,B11111,B11111,B11111,B11111,B11111,B11111,B11111,}; //  : byte Battery2[SYMBOL_HEIGHT] = {B01110,B10001,B10011,B10111,B11111,B11111,B11111,B11111,}; //  : byte Battery3[SYMBOL_HEIGHT] = {B01110,B10001,B10001,B10001,B10011,B10111,B11111,B11111,}; //  : byte Battery4[SYMBOL_HEIGHT] = {B01110,B10001,B10001,B10001,B10001,B10001,B10001,B11111,}; "--------------------------------------------------------------------------" 

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

- تحريك القلب
- بطل الرسوم المتحركة
- التحقق من تلف البطل
- حركة الصبار الشرير
- تراكم النقاط (في الوقت الحالي ، كل ثانية +1 ، ثم تغييرها)
- تحديث الشاشة (ولكن هذا ليس دقيقا ، على الأرجح سنقوم بإزالة هذه الوظيفة وإضافة وظيفة أخرى ، لم تعجبني الشاشة وامض ، أريد الاستقرار). في وقت لاحق ، نستبدل هذه الوظيفة بإزالة موقع البطل الماضي ، سيؤدي ذلك إلى إزالة الوميض الفعلي للشاشة ، وسيكون وضع الشرير داخل النص الشرير صفرًا ، أعتقد أنه سيكون هناك سطر واحد أو سطرين كحد أقصى.
- جهاز تحكم عن بعد
- إعدادات الحلقة والإعداد

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

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

lcd.createChar // هذا أمر للوصول إلى الشاشة واستخدام إحدى خلايا الذاكرة لتسجيل شخصيات جديدة. يتم كتابة رقم الخلية ، ويفصل بينها بفاصلة ، اسم المتغير بالمعلومات ، بين قوسين.

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

 "--------------------------------------------------------------------------" void HeartHit () //    { if (HeartControl == 0 || HeartControl == 2){lcd.createChar(1, Heart_L);} //      ,        if (HeartControl == 1 || HeartControl == 3){lcd.createChar(1, Heart_R);} //      ,        if (currentMillis - HeartHitBigCheck >= HeartHitBig) { //     if (currentMillis - HeartHitLightCheck >= HeartHitLight) { //    HeartHitLightCheck = currentMillis; //      if (HeartControl<3){HeartControl++;} //      ,           else {HeartControl = 0; HeartHitBigCheck = currentMillis;} //     ,          } } } "--------------------------------------------------------------------------" 

مرة أخرى ، أريد تركيز انتباهك على هذا الرمز:
lcd.createChar (س ، ص) ؛ تخصيص لخلية الذاكرة "x" من بيانات (0 ... 7) للعرض على الشاشة "y"

المضي قدما =)

الآن ، لدينا كود يخلق تأثير ضربات القلب المثيرة للاهتمام ، ولا يفعل أي شيء مفيد ، فقط التباهي =)

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

 "--------------------------------------------------------------------------" //             ().     =)  ,         . void PlAn () //     { If (JumpB == true && GGpozY == 0){ //    (      )   =     . if (currentMillis - JumpUPCheck >= JumpUP) { //     0.8f JumpB = false; GGclear (); GGpozY = 1; //   ,         .  = ;      ();     =  ; } } if (AnimPlayer == 1){lcd.createChar(0, Player_1);} //    ,        if (AnimPlayer == 2){lcd.createChar(0, Player_2);} //    ,        if (AnimPlayer < 2) //    ,     ,            { lcd.setCursor(GGpozX, GGpozY); //    lcd.write(0); //  } if (currentMillis - AnimatedTimeCheck >= AnimatedTime) { //   AnimatedTimeCheck = currentMillis; //   if (AnimPlayer == 2){AnimPlayer = 1;} //        else{AnimPlayer = 2;} //   ,  . } } void GGclear () //    { lcd.setCursor(GGpozX, GGpozY); //   lcd.print(" "); //  } "--------------------------------------------------------------------------" 

الآن العداد ، أم ، أو بالأحرى نقاطنا التي سيتم منحها ، دعنا نكتب مؤقتًا ونفترض أن هذه نقاط.

 "--------------------------------------------------------------------------" void timer () //   { if (currentMillis - DHTTimeRCheck >= DHTTimeR) //       { DHTTimeRCheck = currentMillis; //   Timer_z ++; //      lcd.setCursor(0, 0); //       lcd.print(Timer_z); //     } } --------------------------------------------------------------------------" 

هذا كل شيء. كلما كان أسهل.

الآن ، يبقى عمل الصبار لدينا.

مهمته بسيطة ، على ما يبدو ، للذهاب على طول الطريق من اليمين إلى اليسار ومحاولة لمس البطل من أجل التسبب في الضرر. مع الضرر كل شيء أسهل ، لمسة واحدة - ضربة واحدة. حتى الآن ، لن نزيد من التعقيد. دع الصبار يتحرك بسرعة 0.5f (التعقيد ، سيكون هذا بالفعل واجبك =)) جيدًا ، أو بالروسية ، نصف ثانية هي خطوة واحدة.

دعونا نلقي نظرة على كيف سيبدو هذا الجزء من التعليمات البرمجية:

 "--------------------------------------------------------------------------" void enemy_go () //   { if (Emeny_check_1 == 0) //       ,            ,        ,            { Emeny_control = random (100); //  ,     ,    ,  ,    ,   . if (Emeny_control == 1) { //   = 1  100   . Emeny_check_1 = 1; //  ,  ,    bool      ,    ,       hitON = false; //          } } if (Emeny_check_1 == 1) //   ,     { if (currentMillis - TimeBlinkCheck >= TimeBlink) //  0.5f { TimeBlinkCheck = currentMillis; //   lcd.createChar(2, Enemy_1); //   2   lcd.setCursor(E1pozX, E1pozY); // 1   lcd.print(" "); //  E1pozX--; //     lcd.setCursor(E1pozX, E1pozY); // 2  lcd.write(2); //  if (E1pozX <= 0) //      { lcd.setCursor(0,1); //     lcd.print(" "); //  Emeny_control = 0; //   Emeny_check_1 = 0; //      E1pozX = 16; // - \/ \/ \/ E1pozY = 1; // -         } } } } "--------------------------------------------------------------------------" 

يبقى الأمر قليلاً وبعد تجربة كل قطعة ، يمكنني بالفعل وضع النص الكامل الذي تم تجميعه وتكوينه وجاهز للاختبار على أجهزتك.

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

 "--------------------------------------------------------------------------" void check_hit_gg_1 () //   { if (E1pozX == GGpozX && E1pozY == GGpozY && hitON == false){ //     Y ,   ,    LifeCheck -= 1; //    hitON = true; //           if (LifeCheck <= 0){ //      AnimPlayer = 50; //  loop () Emeny_check_1 = 50; //     lcd.clear(); //  lcd.setCursor(3, 0); //  lcd.print("GAME OVER"); //    } } else { // !         … lcd.setCursor(13, 0); //    … lcd.write(1); //   lcd.setCursor(14, 0); lcd.print("="); //    lcd.setCursor(15, 0); lcd.write(3); //   } } "--------------------------------------------------------------------------" 

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

الآن الوظيفة الأخيرة هي الإدارة. في الواقع ، إذا قمنا بتحليل الرمز أعلاه ، فسيبدو الأمر أسهل بالنسبة لنا. من الدرس الأول ، قمنا بسحب رموز التحكم عن بعد ، وكتبتها كلها ، وهي تبدو كما يلي:

* CH- 0xFFA25D
* CH 0xFF629D
* CH+ 0xFFE21D
* << 0xFF22DD
* >> 0xFF02FD
* >|| 0xFFC23D
* - 0xFFE01F
* + 0xFFA857
* EQ 0xFF906F
* 0 0xFF6897
* 100+ 0xFF9867
* 200+ 0xFFB04F
* 1 0xFF30CF
* 2 0xFF18E7
* 3 0xFF7A85
* 4 0xFF10EF
* 5 0xFF38C7
* 6 0xFF5AA5
* 7 0xFF42BD
* 8 0xFF4AB5
* 9 0xFF52AD


زر _ رمز (انتباه!) (قد تختلف رموز التحكم عن بعد)

من لم يقرأ ، أنصحك بقراءة الجزء الأول.

شيء مشابه ، ثم سيكون لديك ، ويمكنك بسهولة تكوين كل ما تحتاجه.

الآن سنقوم بإنشاء أبسط خوارزمية ، بناءً على ما نعرفه بالفعل وستبدأ لعبتنا في الحياة.

 "--------------------------------------------------------------------------" void IRCheck () //    { if ( irrecv.decode( &results )) //   ,  { if (results.value == 0xFF18E7 && GGpozY == 1){ //    « 2 »    «» GGclear (); //     GGpozY = 0; //    2  ( ) JumpB = true; //        JumpUPCheck = currentMillis; //       } // 2 if (results.value == 0xFF10EF && GGpozX >= 0){ //             GGclear (); //      GGpozX -= 1; //     } // 4 if (results.value == 0xFF5AA5 && GGpozX <= 15){ //          GGclear (); //    GGpozX += 1; //   } // 6 if (results.value == 0xFF6897){ // 0 //  ,    … lcd.clear(); //   AnimPlayer = 1; //    LifeCheck = 3; //   Timer_z = 0; //   GGpozX = 8; // \/ \/ \/ GGpozY = 1; //       Emeny_check_1 = 0; //     E1pozX = 16; // \/ \/ \/ E1pozY = 1; //    . } irrecv.resume(); //    } "--------------------------------------------------------------------------" 

استنتاج من الرمز المكتوب أعلاه:
الزر 2 قفزة
الزر 4 خطوة إلى اليسار
الزر 6 خطوة إلى اليمين
زر 0 يعيد اللعبة ويعيد تشغيلها

الآن ، يبقى لنا تكوين الإعداد والحلقة ، كل شيء يقترب بالفعل من نهايته. لقد أنشأنا جميع الوظائف الإضافية وكل ما تبقى لنا هو الغراء وإضافة جميع المكتبات. أعتقد أننا سنلقي نظرة على المتغيرات وإعدادات الإعداد / الحلقة الرئيسية الموجودة بالفعل في الكود العام ، لذلك دعونا نبدأ ، وبعد ذلك يُطلب منك ctrl + c & ctrl + v وهذا كل شيء =) والمزيد من التطوير المستقل في هذا الاتجاه ، إذا كنت بالطبع أعجبني.

 "--------------------------------------------------------------------------" #include <IRremote.h> //   #include <Wire.h> // i2P  #include <LiquidCrystal_I2C.h> //  1602 LiquidCrystal_I2C lcd(0x3F,16,2); //   int AnimPlayer = 1; //   int GGpozX = 8; //     int GGpozY = 1; //     int Emeny_check_1 = 0; //   int Emeny_control = 0; //           int E1pozX = 16; //    int E1pozY = 1; //    int HeartControl = 0; //    int LifeCheck = 3; //   long Timer_z = 0; //   long AnimatedTime = 300; //     long AnimatedTimeCheck = 0; //   long HeartHitBig = 800; //     long HeartHitLight = 250; //     long HeartHitBigCheck = 0; //     long HeartHitLightCheck = 0; //     long BatteyBlink = 200; //      1  long BatteyBlinkCheck = 0; //   long JumpUP = 800; //     long JumpUPCheck = 0; //   long DHTTimeR = 1000; //  long DHTTimeRCheck = 0; //   long TimeBlink = 500; //    long TimeBlinkCheck = 0; //   long currentMillis = 0; //    bool JumpB = false; //    bool BatteryB = false; //     bool hitON = false; //    decode_results results; //      IRrecv irrecv(A0); //      enum { SYMBOL_HEIGHT = 8 }; byte Player_1[SYMBOL_HEIGHT] = {B01110,B01110,B00100,B01110,B10101,B00100,B01110,B01010,}; byte Player_2[SYMBOL_HEIGHT] = {B00000,B01110,B01110,B00100,B11111,B00100,B01110,B01010,}; byte Enemy_1[SYMBOL_HEIGHT] = {B00010,B00110,B10111,B10110,B11111,B00110,B00110,B11111,}; byte Heart_L[SYMBOL_HEIGHT] = {B00000,B01010,B11111,B11111,B11111,B01110,B00100,B00000,}; byte Heart_R[SYMBOL_HEIGHT] = {B00000,B00000,B01010,B11111,B01110,B00100,B00000,B00000,}; byte Battery1[SYMBOL_HEIGHT] = {B01110,B11111,B11111,B11111,B11111,B11111,B11111,B11111,}; byte Battery2[SYMBOL_HEIGHT] = {B01110,B10001,B10011,B10111,B11111,B11111,B11111,B11111,}; byte Battery3[SYMBOL_HEIGHT] = {B01110,B10001,B10001,B10001,B10011,B10111,B11111,B11111,}; byte Battery4[SYMBOL_HEIGHT] = {B01110,B10001,B10001,B10001,B10001,B10001,B10001,B11111,}; void setup() { Serial.begin(9600); //   irrecv.enableIRIn(); //   lcd.init(); //   Wire.begin(); //   lcd.backlight();//    } void loop() { currentMillis = millis(); //   IRCheck (); //    if (AnimPlayer < 3){ //   ,   ,    if (LifeCheck == 3) {lcd.createChar(3, Battery1);} //   if (LifeCheck == 2) {lcd.createChar(3, Battery2);} //   if (LifeCheck == 1) {//  ,  1   if (BatteryB == false){lcd.createChar(3, Battery3);} //    if (BatteryB == true){lcd.createChar(3, Battery4);} //   if (currentMillis - BatteyBlinkCheck >= BatteyBlink) {BatteyBlinkCheck = currentMillis; //  if (BatteryB == false) {BatteryB = true;} else {BatteryB = false;}} //  } timer(); //  check_hit_gg_1 (); //   PlAn(); //   HeartHit (); //    enemy_go(); //   } } void IRCheck () //    { if ( irrecv.decode( &results )) //   ,  { if (results.value == 0xFF18E7 && GGpozY == 1){ //    « 2 »    «» GGclear (); //     GGpozY = 0; //    2  ( ) JumpB = true; //        JumpUPCheck = currentMillis; //       } // 2 if (results.value == 0xFF10EF && GGpozX >= 0){ //             GGclear (); //      GGpozX -= 1; //     } // 4 if (results.value == 0xFF5AA5 && GGpozX <= 15){ //          GGclear (); //    GGpozX += 1; //   } // 6 if (results.value == 0xFF6897){ // 0 //  ,    … lcd.clear(); //   AnimPlayer = 1; //    LifeCheck = 3; //   Timer_z = 0; //   GGpozX = 8; // \/ \/ \/ GGpozY = 1; //       Emeny_check_1 = 0; //     E1pozX = 16; // \/ \/ \/ E1pozY = 1; //    . } irrecv.resume(); //    } } void timer () //   { if (currentMillis - DHTTimeRCheck >= DHTTimeR) //       { DHTTimeRCheck = currentMillis; //   Timer_z ++; //      lcd.setCursor(0, 0); //       lcd.print(Timer_z); //     } } //             ().     =)  ,         . void PlAn () //     { if (JumpB == true && GGpozY == 0){ //    (      )   =     . if (currentMillis - JumpUPCheck >= JumpUP) { //     0.8f JumpB = false; GGclear (); GGpozY = 1; //   ,         .  = ;      ();     =  ; } } if (AnimPlayer == 1){lcd.createChar(0, Player_1);} //    ,        if (AnimPlayer == 2){lcd.createChar(0, Player_2);} //    ,        if (AnimPlayer < 2) //    ,     ,            { lcd.setCursor(GGpozX, GGpozY); //    lcd.write(0); //  } if (currentMillis - AnimatedTimeCheck >= AnimatedTime) { //   AnimatedTimeCheck = currentMillis; //   if (AnimPlayer == 2){AnimPlayer = 1;} //        else{AnimPlayer = 2;} //   ,  . } } void GGclear () //    { lcd.setCursor(GGpozX, GGpozY); //   lcd.print(" "); //  } void enemy_go () //   { if (Emeny_check_1 == 0) //       ,            ,        ,            { Emeny_control = random (100); //  ,     ,    ,  ,    ,   . if (Emeny_control == 1) { //   = 1  100   . Emeny_check_1 = 1; //  ,  ,    bool      ,    ,       hitON = false; //          } } if (Emeny_check_1 == 1) //   ,     { if (currentMillis - TimeBlinkCheck >= TimeBlink) //  0.5f { TimeBlinkCheck = currentMillis; //   lcd.createChar(2, Enemy_1); //   2   lcd.setCursor(E1pozX, E1pozY); // 1   lcd.print(" "); //  E1pozX--; //     lcd.setCursor(E1pozX, E1pozY); // 2  lcd.write(2); //  if (E1pozX <= 0) //      { lcd.setCursor(0,1); //     lcd.print(" "); //  Emeny_control = 0; //   Emeny_check_1 = 0; //      E1pozX = 16; // - \/ \/ \/ E1pozY = 1; // -         } } } } void check_hit_gg_1 () //   { if (E1pozX == GGpozX && E1pozY == GGpozY && hitON == false){ //     Y ,   ,    LifeCheck -= 1; //    hitON = true; //           if (LifeCheck <= 0){ //      AnimPlayer = 50; //  loop () Emeny_check_1 = 50; //     lcd.clear(); //  lcd.setCursor(3, 0); //  lcd.print("GAME OVER"); //    } } else { // !         … lcd.setCursor(13, 0); //    … lcd.write(1); //   lcd.setCursor(14, 0); lcd.print("="); //    lcd.setCursor(15, 0); lcd.write(3); //   } } void HeartHit () //    { if (HeartControl == 0 || HeartControl == 2){lcd.createChar(1, Heart_L);} //      ,        if (HeartControl == 1 || HeartControl == 3){lcd.createChar(1, Heart_R);} //      ,        if (currentMillis - HeartHitBigCheck >= HeartHitBig) { //     if (currentMillis - HeartHitLightCheck >= HeartHitLight) { //    HeartHitLightCheck = currentMillis; //      if (HeartControl<3){HeartControl++;} //      ,           else {HeartControl = 0; HeartHitBigCheck = currentMillis;} //     ,          } } } "--------------------------------------------------------------------------" 

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



A5 Display 1602 - SCL
A4 Display 1602 - SDA
A0 IR sensor

الآن أعمل على إنشاء مفتاح راديو لسيارة تعتمد على أردوينو ، وعلى الشاشة 1602 ، أريد عرض بيانات مستشعر الرطوبة ودرجة الحرارة خارج السيارة (بما أنني سأكون في موسكو قريبًا ، أبحث عن وظيفة جديدة ، سأحتاج إلى معرفة ما يجري خارج السيارة الجو بارد جدًا هناك) ، ساعة ، بطارية الفولتميتر ووضع الألعاب هناك (لا يزال لدي 4 دبابيس مجانية ، ولكن لا يزال يتعين علي دفعها هناك) حتى أتمكن من كزة هذه اللعبة أو الثانية التي أخطط لها عند إشارة المرور جعل مثل سباق prist الجيب القديم الجيد 2000s في كاليفورنيا من حيث كانت نقطة فقط للذهاب حول العقبة والموسيقى وضعت على خلفية الصخرة رول سباق. Ugh Classic =) والتزم بها على النحو الأمثل في اردوينو واحد دون استخدام تخزين البيانات الخارجية (تحدي محض) ، لكنني استخدمت بالفعل 60٪ وإذا كانت شفرة اللعبة تستغرق بحد أقصى 15٪ - 20٪ ،ثم الموسيقى ... أوه ... ستكون هناك مشاكل في هذا ، إنها تزن الكثير ، تحتاج إلى تحسين ، لقد بدأت بالفعل في جمع المسار وتمكنت من تقليل الوزن بنحو 10 مرات ، لكنني ارتكبت أخطاء في بناء النغمات والنغمات والآن يجب أن أقوم بذلك مرة أخرى. على الأرجح ، سأكتب هنا النسخة الكاملة مع وصف للمشروع الذي أعمل عليه حاليًا. آمل أن أعطاني شخص ما شيئًا جديدًا أفكر فيه ، إذا كان كل شيء على ما يرام والوقت ، فسأواصل كتابة المقالات. هل من أسئلة؟ اكتب في التعليقات.آمل أن يعطيني شخص ما شيئًا جديدًا أفكر فيه ، إذا كان كل شيء على ما يرام والوقت ، فسأواصل كتابة المقالات. هل من أسئلة؟ اكتب في التعليقات.آمل أن يعطيني شخص ما شيئًا جديدًا أفكر فيه ، إذا كان كل شيء على ما يرام والوقت ، فسأواصل كتابة المقالات. هل من أسئلة؟ اكتب في التعليقات.

الكل ، اشترك ، مثل ، اتبع المقالات الجديدة.

شكرا لكم جميعا على اهتمامكم ، كاكاو!

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

الجزء الأول من المقال ->

Source: https://habr.com/ru/post/ar425367/


All Articles