ArtemTechnologies

ATWatch - Arduino совместимая носимая платформа для обучения робототехнике и программированию на языке C++

Реализация популярной игры Flappy Bird на платформе ATWatch. Бесконечная игра, в которой необходимо управлять маленькой птичкой и как можно дольше не врезаться в препятствия в виде труб.

Простой вариант кода:
  1. #include <SPI.h>
  2. #include <Adafruit_GFX.h>
  3. #include <Adafruit_SSD1306.h>
  4. #include "GyverButton.h"
  5.  
  6. #define OLED_DC    26
  7. #define OLED_CS    31
  8. #define OLED_RESET 24
  9. #define BTN1       2
  10. #define BTN2       12
  11. #define BTN3       13
  12. #define BuzzerPin  15
  13.  
  14. static const unsigned char PROGMEM PicBird1[] =
  15. {
  16.   0x0, 0x0, 0x0,
  17.   0x3, 0xf0, 0x0,
  18.   0xc, 0x48, 0x0,
  19.   0x10, 0x84, 0x0,
  20.   0x78, 0x8a, 0x0,
  21.   0x84, 0x8a, 0x0,
  22.   0x82, 0x42, 0x0,
  23.   0x82, 0x3f, 0x0,
  24.   0x82, 0x40, 0x80,
  25.   0x44, 0xbf, 0x0,
  26.   0x38, 0x41, 0x0,
  27.   0x10, 0x3e, 0x0,
  28.   0xf, 0xc0, 0x0
  29. };
  30.  
  31. static const unsigned char PROGMEM PicBird2[] =
  32. {
  33.   0x0, 0x0, 0x0,
  34.   0x3, 0xf0, 0x0,
  35.   0xc, 0x48, 0x0,
  36.   0x10, 0x84, 0x0,
  37.   0x20, 0x8a, 0x0,
  38.   0x40, 0x8a, 0x0,
  39.   0x40, 0x42, 0x0,
  40.   0x7c, 0x3f, 0x0,
  41.   0x82, 0x40, 0x80,
  42.   0x84, 0xbf, 0x0,
  43.   0x88, 0x41, 0x0,
  44.   0x78, 0x3e, 0x0,
  45.   0x7, 0xc0, 0x0
  46. };
  47.  
  48. Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);
  49. GButton butt1(BTN1, LOW_PULL, NORM_OPEN);
  50. GButton butt2(BTN2, LOW_PULL, NORM_OPEN);
  51. GButton butt3(BTN3, LOW_PULL, NORM_OPEN);
  52.  
  53. // Высота птички
  54. byte pos = 28;
  55. // Множитель падения
  56. byte fallCount = 0;
  57. // Счёт
  58. byte score = 0;
  59. // Последняя пройдённая труба
  60. byte lastTube = 255;
  61. // Переключатель для анимации
  62. bool animState = false;
  63. // Статус игры
  64. bool gameStatus = true;
  65. // Координаты труб
  66. int tubePos[3];
  67. // Высота труб
  68. int ran[3];
  69. // Время смены анимации и увеличения множителя падения
  70. unsigned long flyTime = 0;
  71. // Время движения труб
  72. unsigned long tubeTime = 0;
  73. // Функция обработки действия кнопок
  74. void buttons();
  75. // Функция обработки конца игры
  76. void gameOver();
  77.  
  78. void setup()
  79. {
  80.   display.begin(SSD1306_SWITCHCAPVCC);
  81.   display.setTextSize(1);
  82.   display.setTextColor(WHITE);
  83.   display.setCursor(0, 0);
  84.   randomSeed(micros());
  85.   // Начальные положения труб (через каждые 44 пикселя)
  86.   tubePos[0] = 50;
  87.   tubePos[1] = 94;
  88.   tubePos[2] = 138;
  89.   // Начальные положения высоты труб
  90.   ran[0] = 0;
  91.   ran[1] = 6;
  92.   ran[2] = -3;
  93. }
  94. void buttons()
  95. {
  96.   // Обновляем состояние кнопок
  97.   butt1.tick();
  98.   butt2.tick();
  99.   butt3.tick();
  100.  
  101.   // Ждём нажатия любой кнопки
  102.   if (butt1.isClick() || butt2.isClick() || butt3.isClick())
  103.   {
  104.     // Издаём звук
  105.     tone(BuzzerPin, 4000, 100);
  106.     // Если игра запущена то делаем прыжок
  107.     if (gameStatus == false)
  108.     {
  109.       //Верхняя граница
  110.       if (pos > 0)
  111.       {
  112.         fallCount = 0;
  113.         pos -= 10;
  114.       }
  115.     }
  116.     else
  117.     {
  118.       // Перезапуск игры
  119.       gameStatus = false;
  120.       fallCount = 0;
  121.       pos = 28;
  122.       ran[0] = 0;
  123.       ran[1] = 6;
  124.       ran[2] = -3;
  125.       tubePos[0] = 50;
  126.       tubePos[1] = 94;
  127.       tubePos[2] = 138;
  128.       score = 0;
  129.       lastTube = 255;
  130.     }
  131.   }
  132. }
  133. void gameOver()
  134. {
  135.   gameStatus = true;
  136. }
  137. void loop()
  138. {
  139.   buttons();
  140.  
  141.   display.clearDisplay();
  142.   // Игра окончена выводим счёт
  143.   if (gameStatus == true)
  144.   {
  145.     display.setCursor (0, 50);
  146.     display.println ("Score: ");
  147.     display.setCursor (37, 50);
  148.     display.println (score);
  149.     display.setCursor (60, 30);
  150.     display.println ("Game over");
  151.   }
  152.  
  153.   if (millis() > flyTime)
  154.   {
  155.     flyTime = millis() + 100;
  156.     if (gameStatus == false)
  157.     {
  158.       // Переключаем анимацию
  159.       animState = !animState;
  160.       // Падение птички
  161.       pos += fallCount;
  162.       // Увеличиваем множитель
  163.       fallCount++;
  164.       // Птичка упала
  165.       if (pos >= 50)
  166.       {
  167.         gameOver();
  168.       }
  169.     }
  170.   }
  171.  
  172.   if (millis() > tubeTime)
  173.   {
  174.     tubeTime = millis() + 20;
  175.     // Если игра запущена
  176.     if (gameStatus == false)
  177.     {
  178.       // Двигаем все трубы
  179.       for (int i = 0 ; i < 3; i++)
  180.       {
  181.         if (tubePos[i] > 0)
  182.           tubePos[i]--;
  183.         else
  184.         {
  185.           // Если труба достигла границы то передвигаем её в начало
  186.           tubePos[i] = 128;
  187.           ran[i] = random(-20, 20);
  188.         }
  189.       }
  190.     }
  191.   }
  192.  
  193.   // Рисуем трубы, сверху и снизу
  194.   for (int i = 0 ; i < 3; i++)
  195.   {
  196.     display.drawRect(tubePos[i], 0, 5, 16 - ran[i], 1);
  197.     display.drawRect(tubePos[i], 47 - ran[i], 5, 16 + ran[i], 1);
  198.   }
  199.  
  200.   // Рисуем птичку
  201.   if (animState)
  202.     display.drawBitmap(20, pos, PicBird1, 17, 13, 1);
  203.   else
  204.     display.drawBitmap(20, pos, PicBird2, 17, 13, 1);
  205.  
  206.   for (int i = 0 ; i < 3 && gameStatus == false; i++)
  207.   {
  208.     // Если труба находится в зоне птички
  209.     if (tubePos[i] <= 37 && tubePos[i] >= 20)
  210.     {
  211.       // Проверка что бы увеличить счёт только ОДИН раз
  212.       if (lastTube != i)
  213.       {
  214.         lastTube = i;
  215.         score++;
  216.       }
  217.       // Если птичка ударилась об границы
  218.       if ((pos < 16 - ran[i]) || pos + 13 > 47 - ran[i])
  219.       {
  220.         gameOver();
  221.       }
  222.     }
  223.   }
  224.   // Отрисовываем кадр
  225.   display.display();
  226. }

Вы должны авторизоваться для того, чтобы оставить комментарий.