Cat hungry.png
Здравствуйте! Собираем деньги на перевод материалов по электронике(https://www.allaboutcircuits.com/education/). Реквизиты указаны здесь.

Arduino:Примеры/Rocket

Материал из Онлайн справочника
Перейти к: навигация, поиск

Перевод: Максим Кузьмин (Cubewriter)
Перевел 2686 статей для сайта.

Контакты:

Проверка/Оформление/Редактирование: Мякишев Е.А.


Игра «Ракета» [1]

Этот пример показывает при помощи Arduino и библиотеки GLCD воспроизвести на GLCD-панели игру в стиле аркадной игры «Asteroids».

Код

  1.  
  2. /*
  3.  * Ракета
  4.  *
  5.  * Примитивная игра в духе «Asteroids» от biegematchbox
  6.  * http://www.beigematchbox.co.uk/site/BeigeMatchbox.co.uk/Electronics/Electronics.html
  7.  *
  8.  * Чтобы управлять позицией ракеты, подключаем регулируемый резистор
  9.  * к входному аналоговому контакту (potPin)
  10.  * Чтобы был звук, к контакту speakerPin можно подключить пьезодинамик
  11.  * (или обычный динамик, но понадобится добавочный резистор)
  12.  *
  13.  * Дискуссия на форуме Arduino: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1265067548
  14.  *
  15.  */
  16.  
  17.  
  18. #include <glcd.h>
  19. #include "fonts/SystemFont5x7.h"   // шрифт
  20. #include "bitmaps.h"               // картинки
  21.  
  22. /*
  23. ****************************************************
  24. * Секция, в которой настраиваются нужные контакты. *
  25. * Чтобы активировать нужную функцию,               *
  26. * уберите слеши у соответствующей строчки          *
  27. ****************************************************
  28. */
  29.  
  30.  
  31. //#define potPin        5   // входной аналоговый контакт, к которому подключается регулируемый резистор
  32. //#define speakerPin    2   // цифровой контакт (опциональный), к которому можно подключить пьезодинамик или обычный динамик (для звука)
  33. //#define brightnessPin 3   // выходной контакт (тоже опциональный) для управления фоновой подсветкой
  34.  
  35.  
  36. /*
  37.  * Проверяем, не маленький ли дисплей, т.к. этот код требует
  38.  * большого дисплея.
  39.  */
  40. #if DISPLAY_HEIGHT < 64
  41. #error Игра «Ракета» требует дисплея высотой как минимум 64 пикселя
  42. #endif
  43. #if DISPLAY_WIDTH < 128
  44. #error Игра «Ракета» требует дисплея шириной как минимум 128 пикселей
  45. #endif
  46.  
  47.  
  48. byte brightness = 64;
  49.  
  50. #define PLAYER 0
  51. #define ROCK1 1
  52. #define ROCK2 2
  53. #define ROCK3 3
  54. #define ROCK4 4
  55. #define ROCK5 5
  56. #define ROCK6 6
  57. #define ROCK7 7
  58. #define ROCK8 8
  59. #define BONUS 9
  60.  
  61. #define EX1 0
  62. #define EX2 1
  63. #define EX3 2
  64.  
  65.  
  66. #define playerX tracker[0][1]
  67. #define playerY tracker[0][2]
  68.  
  69. #define enemy1type tracker[1][0]
  70. #define enemy1X tracker[3][1]
  71. #define enemy1Y tracker[4][2]
  72.  
  73. #define playerXOld trackerOld[0][1]
  74. #define playerYOld trackerOld[0][2]
  75. #define enemy1XOld trackerOld[3][1]
  76. #define enemy1YOld trackerOld[4][2]
  77.  
  78. char lives = 3;
  79. char score = 0;
  80. char level = 0;
  81. char fastSpeed = 25;
  82. char rockAmount = 6;
  83.  
  84. long speedMillis[] = {0, 0, 0, 0, 0, 0};
  85.  
  86. char tracker[8][5] = {
  87. //Картинка, X,      Y,             скорость:
  88.   {PLAYER,  15,     32,            0}  ,
  89.   {ROCK2,   119,    random(0, 56), random(25, 75)}  ,
  90.   {ROCK5,   119,    random(0, 56), random(25, 75)}  ,
  91.   {ROCK8,   119,    random(0, 56), random(25, 75)}  ,
  92.   {ROCK1,   119,    random(0, 56), random(25, 75)}  ,
  93.   {ROCK3,   119,    random(0, 56), random(25, 75)}  ,
  94.   {BONUS,   119,    random(0, 56), random(25, 75)}
  95. };
  96.  
  97. char trackerOld[8][5] = {
  98. // Картинка, X,      Y,             скорость:
  99.   {PLAYER,  15,     32,            0}  ,
  100.   {ROCK2,   119,    random(0, 56), random(25, 75)}  ,
  101.   {ROCK5,   119,    random(0, 56), random(25, 75)}  ,
  102.   {ROCK8,   119,    random(0, 56), random(25, 75)}  ,
  103.   {ROCK1,   119,    random(0, 56), random(25, 75)}  ,
  104.   {ROCK3,   119,    random(0, 56), random(25, 75)}  ,
  105.   {BONUS,   119,    random(0, 56), random(25, 75)}
  106. };
  107.  
  108. void setup(){
  109.   GLCD.Init();
  110. #ifdef brightnessPin
  111.   analogWrite(brightnessPin, brightness);
  112. #endif
  113. #ifdef speakerPin
  114.   pinMode(speakerPin, OUTPUT);
  115. #endif
  116.    
  117.   GLCD.SelectFont(System5x7);
  118. #ifdef potPin
  119.   randomSeed(analogRead(potPin));
  120. #endif
  121.   GLCD.DrawBitmap(startup, 0, 0, BLACK);
  122.   delay(2000);
  123.   GLCD.ClearScreen();
  124. }
  125.  
  126. /*
  127. ******************************
  128. *  Главный цикл              *
  129. *                            *
  130. ******************************
  131. */
  132. void  loop(){
  133.   getControls();
  134.   drawFrame();
  135.   drawLives();
  136.   drawScore();
  137. }
  138.  
  139.  
  140. /*
  141. ******************************
  142. *  Рисуем оставшиеся жизни   *
  143. *                            *
  144. ******************************
  145. */
  146. void drawLives(){
  147.   GLCD.DrawBitmap(heart, 0, 0, BLACK);
  148.   GLCD.CursorTo(1,0);
  149.   GLCD.print((int)lives);
  150. }
  151.  
  152.  
  153. /*
  154. ******************************
  155. *  Рисуем текущий счет       *
  156. *                            *
  157. ******************************
  158. */
  159. void drawScore(){
  160.   GLCD.CursorTo(0,7);
  161.   GLCD.print('S');
  162.   GLCD.print((int)score);
  163. }
  164.  
  165.  
  166.  
  167. /*
  168. ******************************
  169. *  Задаем позицию ракеты     *
  170. *                            *
  171. ******************************
  172. */
  173. void getControls(){
  174. #ifdef potPin
  175.   playerY = map(analogRead(potPin), 0, 1023, 0, 56);
  176. #else
  177. /*
  178.  * От потенциометра нет данных, поэтому начинаем двигать ракету вниз и вверх
  179.  */
  180. static uint8_t yval;
  181. static uint8_t iter = 0;
  182. static int8_t dir = 1;
  183.   if(++iter == 0)
  184.     yval += dir;
  185.  
  186.   if(yval == 0)
  187.     dir = 1;
  188.  
  189.   if(yval == 56)
  190.     dir = -1;
  191.   playerY = yval;
  192. #endif
  193. }
  194.  
  195.  
  196.  
  197. /*
  198. ******************************
  199. *  Обновляем позицию         *
  200. *  астероидов                *
  201. ******************************
  202. */
  203. void updatePos(int entity){
  204.     if (millis() - speedMillis[entity-1] > tracker[entity][3]) {
  205.       speedMillis[entity-1] = millis();
  206.       tracker[entity][1] --;
  207.      
  208.         if(collision(entity) == true){
  209.           BLOWUP();
  210.         }
  211.      
  212.       if(tracker[entity][1] < 1){
  213.         score++;
  214.         level++;
  215.         constrain(level, 0, 75);
  216.         if(level > 75){
  217.           fastSpeed --;
  218.           constrain(fastSpeed, 10, 25);
  219.         }
  220.        
  221.         tracker[entity][0] = random(1, 8);   // картинка
  222.         tracker[entity][1] = 119;            // стартовая точка
  223.         tracker[entity][2] = random(8, 56);  // высота
  224.         tracker[entity][3] = random(fastSpeed, 100-level); // скорость
  225.       }  
  226.   }
  227. }
  228.  
  229.  
  230. /*
  231. ******************************
  232. *  Определяем столкновения   *
  233. *                            *
  234. ******************************
  235. */
  236. boolean collision(char entity){
  237.   for(char playerScanCOL = 0; playerScanCOL<=9; playerScanCOL++){
  238.     if(tracker[0][1]+playerScanCOL == tracker[entity][1]+1){
  239.       for(char playerScanROW = -1; playerScanROW < 6; playerScanROW  ++){
  240.       for(char entityScanROW = -1; entityScanROW < 6; entityScanROW  ++){
  241.         if(tracker[0][2]+playerScanROW == tracker[entity][2]+entityScanROW){
  242.           return true;
  243.          }
  244.       }
  245.      }
  246.     }
  247.   }
  248.   return false;
  249. }
  250.  
  251.  
  252. /*
  253. ******************************
  254. *  Взрываем корабль          *
  255. *                            *
  256. ******************************
  257. */
  258. void BLOWUP(){
  259.   lives--;
  260.   digitalWrite(13, HIGH);
  261.   explosionAnim(tracker[0][1]-2, tracker[0][2]-4);
  262.   digitalWrite(13, LOW);
  263.   GLCD.ClearScreen();
  264.   if(lives < 0){
  265.     gameOver();
  266.     lives = 3;
  267.     level = 0;
  268.   }
  269.   resetTracker();
  270. }
  271.  
  272.  
  273. /*
  274. ******************************
  275. *  Сбрасываем трекер, задаем *
  276. *  ему новое состояние       *
  277. ******************************
  278. */
  279. void resetTracker(){
  280.   char trackerReset[8][5] = {
  281.   {PLAYER, 15, 32, 0}  ,
  282.   {ROCK2,   119, random(0, 56), random(25, 75)}  ,
  283.   {ROCK5,   119, random(0, 56), random(25, 75)}  ,
  284.   {ROCK8,   119, random(0, 56), random(25, 75)}  ,
  285.   {ROCK1,   119, random(0, 56), random(25, 75)}  ,
  286.   {ROCK3,   119, random(0, 56), random(25, 75)}  ,
  287.   {BONUS,   119, random(0, 56), random(25, 75)}
  288.   };
  289.  
  290.   for(byte entity = 0; entity <= 6; entity++){
  291.     for(byte data = 0; data <= 3; data++){
  292.       tracker[entity][data] = trackerReset[entity][data];
  293.     }
  294.   }
  295. }
  296.  
  297.  
  298. /*
  299. ******************************
  300. *  Рисуем GAME OVER          *
  301. *  и сбрасываем очки         *
  302. ******************************
  303. */
  304. void gameOver(){
  305.   GLCD.DrawBitmap(gameover, 37, 0, BLACK);
  306.   delay(5000);
  307.   score = 0;
  308.   GLCD.ClearScreen();
  309. }
  310.  
  311.  
  312.  
  313.  
  314. /*
  315. ***********************************
  316. * Анимированный 3-кадровый взрыв. *
  317. * Кадрам нужен один массив.       *
  318. ***********************************
  319. */
  320. void explosionAnim(char xPos, char yPos){
  321.   GLCD.DrawBitmap(ex1, xPos, yPos, BLACK);
  322. #ifdef speakerPin
  323.   noise(175);
  324. #else
  325.   delay(175);
  326. #endif
  327.   GLCD.DrawBitmap(ex2, xPos, yPos, BLACK);
  328. #ifdef speakerPin
  329.   noise(175);
  330. #else
  331.   delay(175);
  332. #endif
  333.   GLCD.DrawBitmap(ex3, xPos, yPos, BLACK);
  334. #ifdef speakerPin
  335.   noise(175);
  336. #else
  337.   delay(175);
  338. #endif
  339.  
  340. }
  341.  
  342.  
  343. /*
  344. *************************************
  345. *  Рисуем рамку, игрока и астероиды *
  346. *                                   *
  347. *************************************
  348. */
  349. void drawFrame(){
  350.   for(int i=1; i<=rockAmount; i++){
  351.     updatePos(i);
  352.     drawRock(i);
  353.   }
  354.   if(playerY != playerYOld){
  355.     GLCD.FillRect(playerXOld, playerYOld, 10, 8, WHITE);
  356.     GLCD.DrawBitmap(player, playerX, playerY, BLACK);
  357.   }
  358.  
  359.   for(byte entity = 0; entity <= 6; entity++){
  360.     for(byte data = 0; data <= 3; data++){
  361.       trackerOld[entity][data] = tracker[entity][data];
  362.     }
  363.   }
  364. }
  365.  
  366.  
  367. /*
  368. ******************************
  369. *  Рисуем астероиды          *
  370. *                            *
  371. ******************************
  372. */
  373. void drawRock(char entity){
  374. // Картинки астероидов должны быть в 2D-массиве; они будут уменьшены ниже
  375.  
  376.   if(tracker[entity][1] != trackerOld[entity][1]){
  377.  
  378.     GLCD.FillRect(trackerOld[entity][1], trackerOld[entity][2], 12, 8, WHITE);
  379.     GLCD.DrawBitmap(rocks[tracker[entity][0]], tracker[entity][1], tracker[entity][2], BLACK);
  380.   }
  381. }
  382.  
  383. #ifdef speakerPin
  384. /*
  385. ********************************************      
  386. *  Делаем шум, который будет продолжаться  *
  387. *  заданное количество секунд.             *
  388. ********************************************
  389. */
  390. void noise(int duration)
  391. {
  392.   unsigned long start = millis();
  393.  
  394.   while( millis() - start < duration)
  395.   {
  396.     int period = random(8,25);
  397.     digitalWrite(speakerPin, HIGH);
  398.     delay(period);
  399.     digitalWrite(speakerPin, LOW);      
  400.     delay(period);
  401.   }
  402. }  
  403. #endif

См.также

Внешние ссылки

  1. glcd-v3-20111205.zip