تطوير اللعبة على المعالجة بالتحكم عبر لوحة Arduino Uno ، الجزء 2

المقدمة


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

الخطوة 1 "مهمة التطوير"


يجب أن يكون لدى SHG درجتين من الحرية.
-SHG لديه القدرة على تسجيل النقاط بسرعة وإبطاء سرعة حركة الصوامع عن طريق ضرب آخر شعاع خاص.
- تنفيذ قواعد جديدة - يتم لعب اللعبة حتى 1000 نقطة. لتجنب الاصطدام البسيط ، يتم منح نقطة واحدة. للاحتفاظ بالحزمة على الكرة +1 نقطة لكل 50 * 10 ^ -3 ثانية (يتم تعيين تأخير قدره 50 مللي ثانية في برنامج Arduino)

الخطوة 2 "وصف توصيل عصا تناظرية"


تحتوي العصا على 5 دبابيس للتوصيل: يتصل دبوس VCC بقوة + 5 فولت ، GND - على الأرض على لوحة Arduino Uno ، X - إلى الإدخال التناظري A0 ، Y - إلى A1 ، D - إلى الإدخال الرقمي D2.

الخطوة 3 "نقل إحداثيات متعددة عبر اتصال تسلسلي"


يتم نقل البيانات الموجودة على موضع العصا معًا لضمان معالجتها في أسرع وقت ممكن دون تأخير زمني. لوصف الوضع الحالي للعصا التناظرية ، يكفي 7 بت XXXYYYB - 3 للإحداثيات X ، 3 للإحداثيات Y ، 1 بت للتحكم في الزر على العصا. أرفق الرمز أدناه:
كود لوحة اردوينو اونو
#include <stdio.h>
int xPin = A0, yPin = A1, buttonPin = 2;
int xPosition = 0, yPosition = 0, buttonState = 0;
char strbuf[20]; //
void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 
  pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);
  //activate pull-up resistor on the push-button pin
  pinMode(buttonPin, INPUT_PULLUP);   }
void loop() {
  xPosition = map(analogRead(xPin),0,1023,0,639);
  yPosition = map(analogRead(yPin),0,1023,0,639);
  buttonState = digitalRead(buttonPin);
  sprintf(strbuf,"%03d%03d%1d",xPosition,yPosition,buttonState);
  Serial.println(strbuf); 
  delay(50); }// add some delay between reads

بعد توصيل العصا والبرامج الثابتة Arduino Uno ، يمكنك رؤية شيء مثل ما يلي في شاشة المنفذ التسلسلي.

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

الخطوة 4 "ترميز اللعبة"


لن أعلق بالتفصيل على الكود. حاولت أن أجعلها مفهومة. تقييم ما إذا كنت تستطيع أو لا تحت المفسد. في هذه الحالة فقط ، أعطي جدولاً من المتغيرات:
radiusOfHero-radius of the SH ؛
radiusOfEnemy - نصف قطر الصومعة ؛
radiusOfBullet - نصف قطر الرصاصة ؛ أنتجت SHG ؛
عداد النقطة المضادة.
speedOfEnemy - معامل يتناسب طرديًا مع سرعة سقوط الصوامع ؛
DeltaPositionOfHeroX - زيادة موضع SH على طول المحور X ، الذي تم الحصول عليه من العصا ؛
positionOfHeroX1 - الإحداثيات النهائية لحركة SH على طول المحور X (في نهاية ساعة القراءة) ؛
positionOfHeroX0 - الإحداثيات الأولية على طول المحور X (في بداية القياس) ؛
DeltapositionOfHeroY ، positionOfHeroY1 ، positionOfHeroY0 - نفس الشيء على طول المحور Y ؛
strbuf هو الخط الذي تتم فيه قراءة مؤشرات حالة العصا التناظرية المرسلة من Arduino Uno.
معالجة كود اللعبة
import processing.serial.*;//I/O library
Serial port;
PShape bot;
PFont font;
PImage img;
int radiusOfHero=100, radiusOfEnemy, radiusOfBullet=5, Counter=0, Fire;
float speedOfEnemy=1, DeltaPositionOfHeroX, positionOfHeroX1, positionOfHeroX0=640.0,
DeltapositionOfHeroY, positionOfHeroY1, positionOfHeroY0=640.0,
positionOfEnemyY = 0.0 ,positionOfEnemyX=0.0, positionOfBulletX=0.0,positionOfBulletY=0.0;
String strbuf="3223220";
void setup()
{
  size(640, 640);
  port = new Serial(this, "COM4", 9600);
  port.bufferUntil('\n');
  bot = loadShape("2.svg");
  font = loadFont("AgencyFB-Bold-200.vlw");
  img = loadImage("img.png");  // Load the image into the program  
  textFont(font,200);
}
void draw() {
    background(0);
    image(img, 0, 0);
    fill(255);
    text(Counter, 400,170);
//==========definiton of hero==========
fill(0, 200, 102);
positionOfHeroX1=positionOfHeroX0+(0.05*(DeltaPositionOfHeroX-width/2));
if (positionOfHeroX1<0){positionOfHeroX1=0.0;}
if (positionOfHeroX1>width){positionOfHeroX1=width;}
positionOfHeroY1=positionOfHeroY0+(0.05*(DeltapositionOfHeroY-height/2));
if (positionOfHeroY1<0){positionOfHeroY1=0.0;}
if (positionOfHeroY1>height){positionOfHeroY1=height;}
ellipse(positionOfHeroX1, positionOfHeroY1, radiusOfHero, radiusOfHero);
positionOfHeroX0=positionOfHeroX1;
positionOfHeroY0=positionOfHeroY1;
fill(244);
       positionOfBulletY= positionOfHeroY1-radiusOfHero/2;
      if (Fire==0){
            for(int i = 0; i < (positionOfHeroY1); i++){
                      positionOfBulletX = positionOfHeroX1; 
                      positionOfBulletY= positionOfBulletY-height/100;
                      ellipse(positionOfBulletX, positionOfBulletY, radiusOfBullet, radiusOfBullet);           }
                       }
//===============definition of enemy===============
fill(255,0,0);
radiusOfEnemy=round(random(60));{
   for(int i = 0; i < height; i++) 
     positionOfEnemyY=positionOfEnemyY+0.02*speedOfEnemy;
     ellipse(positionOfEnemyX, positionOfEnemyY, radiusOfEnemy*2, radiusOfEnemy*2); }
        if (positionOfEnemyY>height) {
        positionOfEnemyY=0.0;
        positionOfEnemyX = round(random(width)); 
        Counter++;}
//==========definition of counter==========        
        if (Counter>1000){
        text("YOU WON!", 50,height/2);
}
//==========clash==========
if (abs(positionOfHeroX1-positionOfEnemyX) < (radiusOfHero+radiusOfEnemy)/2 & 
   (abs(positionOfHeroY1-positionOfEnemyY) < (radiusOfHero+radiusOfEnemy)/2)){
background(255,0,0);
shape(bot, positionOfHeroX1-radiusOfHero/2,positionOfHeroY1-radiusOfHero, 100, 100);  
Counter=-1;
fill(255);
textFont(font,150);
text("TURN AWAY!", 0,height/2);}
//==========Checking of target hit==========
    if (((abs(positionOfBulletX-positionOfEnemyX) < (radiusOfBullet+radiusOfEnemy)/2))& (Fire==0))
      {speedOfEnemy=0.05;// decreasing of enemy speed
      Counter++;}
    else speedOfEnemy=0.2;}
   
void serialEvent (Serial port) {
  if(port.available()>0){
   strbuf=port.readStringUntil('\n'); 
if (strbuf.length()<7) {//condition to prevent artefacts
strbuf="3223220";
  }
DeltaPositionOfHeroX=float(strbuf.substring(0, 3)); 
DeltapositionOfHeroY=float(strbuf.substring(3, 6)); 
Fire=int(strbuf.substring(6, 7));
}
}

الخطوة 5 "الشرح"



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


All Articles