Урок 50. Игра "Лабиринт" на Arduino

В этом уроке мы создадим игру «Лабиринт». Это классическая игра для телефонов и планшетов на Android и Ios, суть которой заключается в том, что вам требуется провести шарик через лабиринт. Управление шариком производится посредством акселерометра, поэтому каждое ваше неосторожное движение может привести к завершению игры.

Правила игры «Лабиринт»:

На игровом поле появляется шарик и лабиринт, представленный сетью разных ходов. В начальный момент игры шарик стоит на месте в точке равновесия, игрок посредством наклона всего устройства вверх, вниз, вправо, влево двигает шарик в соответствующую сторону. Чем больше угол наклона, тем быстрее катится шарик. Задача игрока заключается в том, что бы загнать шарик из начальной точки в лузу, пройдя непосредственно лабиринт. Если шарик дотронется до стенок лабиринта шарик, то происходит завершение игры. Как только игрок загонят шар в лунку, данный уровень считается пройденным происходит переход на следующий уровень. Всего уровней пять. Но желающие совершенствовать игру могут добавить новые локации (Лабиринт), посредством вмешательства добавления новых лабиринтов.

Управление:

Как и в предыдущем уроке игрок управляет шариком используя не кнопки или джойстик, а акселерометр, присутствующий в Trema-модуле IMU 9 DOF (Inertial Measurement Unit 9 Degrees Of Freedom). Таким образом управление шариком совершается наклоном всего устройства влево, вправо, вперёд или назад.

Нам понадобится:

Для реализации проекта нам необходимо установить следующие библиотеки:

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.

Видео:

Схема подключения:

Перед подключением модулей, закрепите винтами нейлоновые стойки в отверстиях секций 3 и 4 Trema Set Shield.
После чего закрепите установленные модули вкрутив через их отверстия нейлоновые винты в установленные ранее нейлоновые стойки (нейлоновые стойки и винты входят в комплектацию Trema Set Shield).

Рисунок 1

Наличие всего двух колодок в секциях Trema Set Shield, не позволит Вам неправильно установить модули, т.к. при неправильном подключении модули будут смещены относительно разметки своей секции и Вы не сможете закрепить их винтами.

Модули необязательно устанавливать в секции 3 или 4. Trema Set Shield распознает модули в любой из секций.

Код программы:

#include <iarduino_Position_BMX055.h>                                                 // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF.
iarduino_Position_BMX055 sensor(BMA);                                                 // Создаём объект sensor указывая что ему требуется работать только с акселерометром.
#define BMX055_DISABLE_BMG                                                            // Не использовать гироскоп.
#define BMX055_DISABLE_BMM                                                            // Не использовать магнитометр.
                                                                                      //
#include <iarduino_OLED.h>                                                            // Подключаем библиотеку iarduino_OLED.
iarduino_OLED myOLED(0x3C);                                                           // Объявляем объект myOLED, указывая адрес дисплея на шине I2C: 0x3C.
extern uint8_t MediumFontRus[];                                                       // Подключаем шрифт MediumFontRus.
                                                                                      //
                    /* Объявляем массивы и переменные: */                             //
const int startLevel = 1;                                                             // Константа определяющая с какого уровня загрузить игру.
const int quantityLevel = 5;                                                          // Константа определяющая количество уровней массива.
const uint32_t tableArray[quantityLevel][68] PROGMEM = {                              // Двумерный массив для локаций, содержащий в себе 5 уровней. Каждый массив содержит в себе 64 элемента по 32 бита. Каждый бит соответствует квадрату на экране размером 2 на два пикселя.
{                                                                                     //
  0b00000000000000000000000000000000, // 1                                            //
  0b00000000000000000000000000000000, // 2                                            //
  0b00000000000000000000000000000000, // 3                                            //
  0b00000000000000000000000000000000, // 4                                            //
  0b00000000000000000000000000000000, // 5                                            //
  0b00000000000000000000000000000000, // 6                                            //
  0b00000011111111111111111111111111, // 7                                            //
  0b00000000000000000000000000000000, // 8                                            //
  0b00000000000000000000000000000000, // 9                                            //
  0b00000000000000000000000000000000, // 10                                           //
  0b00000000000000000000000000000000, // 11                                           //
  0b00000000000000000000000000000000, // 12                                           //
  0b00000000000000000000000000000000, // 13                                           //
  0b11111111111111111111111111000000, // 14                                           //
  0b00000000000000000000000000000000, // 15                                           //
  0b00000000000000000000000000000000, // 16                                           //
  0b00000000000000000000000000000000, // 17                                           //
  0b00000000000000000000000000000000, // 18                                           //
  0b00000000000000000000000000000000, // 19                                           //
  0b00000000000000000000000000000000, // 20                                           //
  0b00000011111111111111111111111111, // 21                                           //
  0b00000000000000000000000000000000, // 22                                           //
  0b00000000000000000000000000000000, // 23                                           //
  0b00000000000000000000000000000000, // 24                                           //
  0b00000000000000000000000000000000, // 25                                           //
  0b00000000000000000000000000000000, // 26                                           //
  0b00000000000000000000000000000000, // 27                                           //
  0b11111111111111111111111111000000, // 28                                           //
  0b00000000000000000000000000000000, // 29                                           //
  0b00000000000000000000000000000000, // 30                                           //
  0b00000000000000000000000000000000, // 31                                           //
  0b00000000000000000000000000000000, // 32                                           //
  0b00000000000000000000000000000000, // 33                                           //
  0b00000000000000000000000000000000, // 34                                           //
  0b00000011111111111111111111111111, // 35                                           //
  0b00000000000000000000000000000000, // 36                                           //
  0b00000000000000000000000000000000, // 37                                           //
  0b00000000000000000000000000000000, // 38                                           //
  0b00000000000000000000000000000000, // 39                                           //
  0b00000000000000000000000000000000, // 40                                           //
  0b00000000000000000000000000000000, // 41                                           //
  0b11111111111111111111111111000000, // 42                                           //
  0b00000000000000000000000000000000, // 43                                           //
  0b00000000000000000000000000000000, // 44                                           //
  0b00000000000000000000000000000000, // 45                                           //
  0b00000000000000000000000000000000, // 46                                           //
  0b00000000000000000000000000000000, // 47                                           //
  0b00000000000000000000000000000000, // 48                                           //
  0b00000011111111111111111111111111, // 49                                           //
  0b00000000000000000000000000000000, // 50                                           //
  0b00000000000000000000000000000000, // 51                                           //
  0b00000000000000000000000000000000, // 52                                           //
  0b00000000000000000000000000000000, // 53                                           //
  0b00000000000000000000000000000000, // 54                                           //
  0b00000000000000000000000000000000, // 55                                           //
  0b11111111111111111111111111000000, // 56                                           //
  0b00000000000000000000000000000000, // 57                                           //
  0b00000000000000000000000000000000, // 58                                           //
  0b00000000000000000000000000000000, // 59                                           //
  0b00000000000000000000000000000000, // 60                                           //
  0b00000000000000000000000000000000, // 61                                           //
  0b00000000000000000000000000000000, // 62                                           //
  0b00000000000000000000000000000000, // 63                                           //
  0b00000000000000000000000000000000, // 64                                           //
  6,                                                                                  // X - координата положения шарика.
  7,                                                                                  // Y - координата положения шарика.
  119,                                                                                // X - координата положения лунки.
  55,                                                                                 // Y - координата положения лунки.
},                                                                                    //
                                                                                      //
{                                                                                     //
  0b00000000000000000000000000000000, // 1                                            //
  0b00000000000000000000000000000000, // 2                                            //
  0b00000000000000000000000000000000, // 3                                            //
  0b00000000000000000000000000000000, // 4                                            //
  0b00000000000000000000000000000000, // 5                                            //
  0b00000000000000000000000000000000, // 6                                            //
  0b00000011111111111111111111000000, // 7                                            //
  0b00000010000000000000000001000000, // 8                                            //
  0b00000010000000000000000001000000, // 9                                            //
  0b00000010000000000000000001000000, // 10                                           //
  0b00000010000000000000000001000000, // 11                                           //
  0b00000010000000000000000001000000, // 12                                           //
  0b00000010000000000000000001000000, // 13                                           //
  0b00000010000001111110000001000000, // 14                                           //
  0b00000010000001000000000001000000, // 15                                           //
  0b00000010000001000000000001000000, // 16                                           //
  0b00000010000001000000000001000000, // 17                                           //
  0b00000010000001000000000001000000, // 18                                           //
  0b00000010000001000000000001000000, // 19                                           //
  0b00000010000001000000000001000000, // 20                                           //
  0b00000010000001000000111111000000, // 21                                           //
  0b00000010000001000000000001000000, // 22                                           //
  0b00000010000001000000000001000000, // 23                                           //
  0b00000010000001000000000001000000, // 24                                           //
  0b00000010000001000000000001000000, // 25                                           //
  0b00000010000001000000000001000000, // 26                                           //
  0b00000010000001000000000001000000, // 27                                           //
  0b00000010000001111110000001000000, // 28                                           //
  0b00000010000001000000000001000000, // 29                                           //
  0b00000010000001000000000001000000, // 30                                           //
  0b00000010000001000000000001000000, // 31                                           //
  0b00000010000001000000000001000000, // 32                                           //
  0b00000010000001000000000001000000, // 33                                           //
  0b00000010000001000000000001000000, // 34                                           //
  0b00000010000001000000111111000000, // 35                                           //
  0b00000010000001000000000001000000, // 36                                           //
  0b00000010000001000000000001000000, // 37                                           //
  0b00000010000001000000000001000000, // 38                                           //
  0b00000010000001000000000001000000, // 39                                           //
  0b00000010000001000000000001000000, // 40                                           //
  0b00000010000001000000000001000000, // 41                                           //
  0b00000010000001111111000001000000, // 42                                           //
  0b00000010000001000000000001000000, // 43                                           //
  0b00000010000001000000000001000000, // 44                                           //
  0b00000010000001000000000001000000, // 45                                           //
  0b00000010000001000000000001000000, // 46                                           //
  0b00000010000001000000000001000000, // 47                                           //
  0b00000010000001000000000001000000, // 48                                           //
  0b00000010000001000000000001000000, // 49                                           //
  0b00000010000001000000000001000000, // 50                                           //
  0b00000010000001111111111111000000, // 51                                           //
  0b00000010000000000000000000000000, // 52                                           //
  0b00000010000000000000000000000000, // 53                                           //
  0b00000010000000000000000000000000, // 54                                           //
  0b00000010000000000000000000000000, // 55                                           //
  0b00000010000000000000000000000000, // 56                                           //
  0b00000010000000000000000000000000, // 57                                           //
  0b00000011111111111111111111111111, // 58                                           //
  0b00000000000000000000000000000000, // 59                                           //
  0b00000000000000000000000000000000, // 60                                           //
  0b00000000000000000000000000000000, // 61                                           //
  0b00000000000000000000000000000000, // 62                                           //
  0b00000000000000000000000000000000, // 63                                           //
  0b00000000000000000000000000000000, // 64                                           //
  121,                                                                                // X - координата положения шарика.
  7,                                                                                  // Y - координата положения шарика.
  92,                                                                                 // X - координата положения лунки.
  24,                                                                                 // Y - координата положения лунки.
},                                                                                    //
                                                                                      //
{                                                                                     //
  0b00000000000000000000000000000000, // 1                                            //
  0b00000000000000000000000000000000, // 2                                            //
  0b00000000000000000000000000000000, // 3                                            //
  0b00000000000000000000000000000000, // 4                                            //
  0b00000000000000000000000000000000, // 5                                            //
  0b00000000000000000000000000000000, // 6                                            //
  0b00000000000000000000000000000000, // 7                                            //
  0b00000001111111111111111100000000, // 8                                            //
  0b00000000000000010000000000000000, // 9                                            //
  0b00000000000000010000000000000000, // 10                                           //
  0b00000000000000010000000000000000, // 11                                           //
  0b00000000000000010000000000000000, // 12                                           //
  0b00000000000000010000000000000000, // 13                                           //
  0b00000000000000010000000000000000, // 14                                           //
  0b11111111111111110000000111111111, // 15                                           //
  0b00000000000000010000000000000000, // 16                                           //
  0b00000000000000010000000000000000, // 17                                           //
  0b00000000000000010000000000000000, // 18                                           //
  0b00000000000000010000000000000000, // 19                                           //
  0b00000000000000010000000000000000, // 20                                           //
  0b00000000000000010000000000000000, // 21                                           //
  0b00000001000000011111111100000000, // 22                                           //
  0b00000001000000000000000000000000, // 23                                           //
  0b00000001000000000000000000000000, // 24                                           //
  0b00000001000000000000000000000000, // 25                                           //
  0b00000001000000000000000000000000, // 26                                           //
  0b00000001000000000000000000000000, // 27                                           //
  0b00000001000000000000000000000000, // 28                                           //
  0b00000001111111111111111111111111, // 29                                           //
  0b00000000000000000000000000000000, // 30                                           //
  0b00000000000000000000000000000000, // 31                                           //
  0b00000000000000000000000000000000, // 32                                           //
  0b00000000000000000000000000000000, // 33                                           //
  0b00000000000000000000000000000000, // 34                                           //
  0b00000000000000000000000000000000, // 35                                           //
  0b11111111111111111111111100000000, // 36                                           //
  0b00000000000000000000000000000000, // 37                                           //
  0b00000000000000000000000000000000, // 38                                           //
  0b00000000000000000000000000000000, // 39                                           //
  0b00000000000000000000000000000000, // 40                                           //
  0b00000000000000000000000000000000, // 41                                           //
  0b00000000000000000000000000000000, // 42                                           //
  0b00000001111111111111111111111111, // 43                                           //
  0b00000001000000000000000000000000, // 44                                           //
  0b00000001000000000000000000000000, // 45                                           //
  0b00000001000000000000000000000000, // 46                                           //
  0b00000001000000000000000000000000, // 47                                           //
  0b00000001000000000000000000000000, // 48                                           //
  0b00000001000000000000000000000000, // 49                                           //
  0b00000001000000011111111100000000, // 50                                           //
  0b00000000000000010000000000000000, // 51                                           //
  0b00000000000000010000000000000000, // 52                                           //
  0b00000000000000010000000000000000, // 53                                           //
  0b00000000000000010000000000000000, // 54                                           //
  0b00000000000000010000000000000000, // 55                                           //
  0b00000000000000010000000000000000, // 56                                           //
  0b11111111111111110000000111111111, // 57                                           //
  0b00000000000000000000000000000000, // 58                                           //
  0b00000000000000000000000000000000, // 59                                           //
  0b00000000000000000000000000000000, // 60                                           //
  0b00000000000000000000000000000000, // 61                                           //
  0b00000000000000000000000000000000, // 62                                           //
  0b00000000000000000000000000000000, // 63                                           //
  0b00000000000000000000000000000000, // 64                                           //
  120,                                                                                // X - координата положения шарика.
  55,                                                                                 // Y - координата положения шарика.
  22,                                                                                 // X - координата положения лунки.
  40,                                                                                 // Y - координата положения лунки.
},                                                                                    //
                                                                                      //
{                                                                                     //
  0b00000000100000000000010000000000, // 1                                            //
  0b00000000100000000000001000000000, // 2                                            //
  0b00000000100000000000000100000000, // 3                                            //
  0b00000000100000000000000010000000, // 4                                            //
  0b00000000100000000000000001000000, // 5                                            //
  0b00000000100000000000000000100000, // 6                                            //
  0b00000000100000000100000000010000, // 7                                            //
  0b00000000010000000010000000001000, // 8                                            //
  0b10000000001000000001000000000100, // 9                                            //
  0b01000000000100000000100000000010, // 10                                           //
  0b00100000000010000000010000000001, // 11                                           //
  0b00010000000001000000001000000000, // 12                                           //
  0b00001000000001000000001000000000, // 13                                           //
  0b00000100000000100000000100000000, // 14                                           //
  0b00000100000000100000000100000000, // 15                                           //
  0b00001000000001000000001000000000, // 16                                           //
  0b00010000000001000000001000000001, // 17                                           //
  0b00100000000010000000010000000010, // 18                                           //
  0b01000000000100000000100000000100, // 19                                           //
  0b10000000001000000001000000001000, // 20                                           //
  0b00000000010000000010000000010000, // 21                                           //
  0b00000000100000000100000000100000, // 22                                           //
  0b00000000100000000100000000100000, // 23                                           //
  0b00000000100000000100000000100000, // 24                                           //
  0b00000000100000000100000000100000, // 25                                           //
  0b00000000010000000010000000010000, // 26                                           //
  0b10000000001000000001000000001000, // 27                                           //
  0b01000000000100000000100000000100, // 28                                           //
  0b00100000000010000000010000000010, // 29                                           //
  0b00010000000001000000001000000001, // 30                                           //
  0b00001000000001000000001000000000, // 31                                           //
  0b00000100000000100000000100000000, // 32                                           //
  0b00000100000000100000000100000000, // 33                                           //
  0b00001000000001000000001000000000, // 34                                           //
  0b00010000000001000000001000000001, // 35                                           //
  0b00100000000010000000010000000010, // 36                                           //
  0b01000000000100000000100000000100, // 37                                           //
  0b10000000001000000001000000001000, // 38                                           //
  0b00000000010000000010000000010000, // 39                                           //
  0b00000000100000000100000000100000, // 40                                           //
  0b00000000100000000100000000100000, // 41                                           //
  0b00000000100000000100000000100000, // 42                                           //
  0b00000000100000000100000000100000, // 43                                           //
  0b00000000010000000010000000010000, // 44                                           //
  0b10000000001000000001000000001000, // 45                                           //
  0b01000000000100000000100000000100, // 46                                           //
  0b00100000000010000000010000000010, // 47                                           //
  0b00010000000001000000001000000001, // 48                                           //
  0b00001000000001000000001000000000, // 49                                           //
  0b00000100000000100000000100000000, // 50                                           //
  0b00000100000000100000000100000000, // 51                                           //
  0b00001000000001000000001000000000, // 52                                           //
  0b00010000000001000000001000000001, // 53                                           //
  0b00100000000010000000010000000010, // 54                                           //
  0b01000000000100000000100000000100, // 55                                           //
  0b10000000001000000001000000001000, // 56                                           //
  0b00000000010000000010000000010000, // 57                                           //
  0b00000000100000000100000000100000, // 58                                           //
  0b00000000000000001000000001000000, // 59                                           //
  0b00000000000000010000000010000000, // 60                                           //
  0b00000000000000010000000010000000, // 61                                           //
  0b00000000000000010000000010000000, // 62                                           //
  0b00000000000000010000000010000000, // 63                                           //
  0b00000000000000010000000010000000, // 64                                           //
  7,                                                                                  // X - координата положения шарика.
  56,                                                                                 // Y - координата положения шарика.
  122,                                                                                // X - координата положения лунки.
  23,                                                                                 // Y - координата положения лунки.
},                                                                                    //
                                                                                      //
{                                                                                     //
  0b00000000000000000000001000000000, // 1                                            //
  0b00000000000000000000000100000000, // 2                                            //
  0b00000000000000000000000010000000, // 3                                            //
  0b00000000000000000000000001000000, // 4                                            //
  0b00000000000000000000000000100000, // 5                                            //
  0b00000000000000000000000000010000, // 6                                            //
  0b11111111111111111111100000001000, // 7                                            //
  0b00000000000000000000010000000100, // 8                                            //
  0b00000000000000000000001000000010, // 9                                            //
  0b00000000000000000000000100000001, // 10                                           //
  0b00000000000000000000000010000000, // 11                                           //
  0b00000000000000000000000010000000, // 12                                           //
  0b10000000100000000000000010000000, // 13                                           //
  0b01000000010000000000000010000000, // 14                                           //
  0b00100000001000000000000010000000, // 15                                           //
  0b00010000000100000000000010000000, // 16                                           //
  0b00001000000011111111111110000000, // 17                                           //
  0b00010000000100000000000010000000, // 18                                           //
  0b00100000001000000000000010000000, // 19                                           //
  0b01000000010000000000000010000000, // 20                                           //
  0b10000000100000000000000010000000, // 21                                           //
  0b00000001000000000000000010000000, // 22                                           //
  0b00000000000000001000000010000000, // 23                                           //
  0b00000000000000010000000100000001, // 24                                           //
  0b00000000000000100000001000000010, // 25                                           //
  0b00000000000001000000010000000100, // 26                                           //
  0b00000000000010000000100000001000, // 27                                           //
  0b00000000000100000001000000010000, // 28                                           //
  0b00000000001100000001000000010000, // 29                                           //
  0b00000000010010000000100000001000, // 30                                           //
  0b11111111100001000000010000000100, // 31                                           //
  0b00000000000000100000001000000010, // 32                                           //
  0b00000000000000010000000100000001, // 33                                           //
  0b00000000000000001000000010000000, // 34                                           //
  0b00000000000000000100000010000000, // 35                                           //
  0b00000000000000000100000010000000, // 36                                           //
  0b00000000000000000100000010000000, // 37                                           //
  0b00000011110000000000000010000000, // 38                                           //
  0b00000000001000000000000010000000, // 39                                           //
  0b00000000000100000000000010000000, // 40                                           //
  0b00000000000010000000000010000000, // 41                                           //
  0b00000000000001000000000010000000, // 42                                           //
  0b00000000000000100000000010000000, // 43                                           //
  0b11111110000000010000000010000000, // 44                                           //
  0b00000001000000001000000010000000, // 45                                           //
  0b00000000100000000100000010000000, // 46                                           //
  0b00000000010000000010000010000000, // 47                                           //
  0b00000000001000000001000010000000, // 48                                           //
  0b00000000000100000000100100000001, // 49                                           //
  0b00000000000010000000011000000010, // 50                                           //
  0b00000000000000000000010000000100, // 51                                           //
  0b00000000000000000000100000001000, // 52                                           //
  0b00000010000000000001000000010000, // 53                                           //
  0b00000001000000000011000000010000, // 54                                           //
  0b00000000100000000100100000001000, // 55                                           //
  0b00000000010000001000010000000100, // 56                                           //
  0b00000000001000010000001000000010, // 57                                           //
  0b00000000000100100000000100000001, // 58                                           //
  0b00000000000011000000000010000000, // 59                                           //
  0b00000000000000000000000000000000, // 60                                           //
  0b00000000000000000000000000000000, // 61                                           //
  0b00000000000000000011000000000000, // 62                                           //
  0b00000000000000000100100000000000, // 63                                           //
  0b00000000000000001000010000000000, // 64                                           //
  6,                                                                                  // X - координата положения шарика.
  55,                                                                                 // Y - координата положения шарика.
  25,                                                                                 // X - координата положения лунки.
  25,                                                                                 // Y - координата положения лунки.
},                                                                                    //
//************************************************************************************//
// Место для нового массива нового уровня.                                            //
//************************************************************************************//
};                                                                                    //
                                                                                      //
int y, x;                                                                             // Переменные положения движения.
int yh, xh;                                                                           // Переменные положения лунки.
int ys, xs;                                                                           // Вспомогательные переменные для запоминания последних координат.
int limited;                                                                          // Переменная регулирования скорости.
int Level;                                                                            // Переменная выбора уровня.
                                                                                      //
                                  /* Объявляем функции: */                            //
                                                                                      //
void Draw();                                                                          // Функция прорисовки шарик.
void Logic();                                                                         // Функция движения шарика.
void GameOver();                                                                      // Функция завершения игры.
void CheckBlock();                                                                    // Функция проверки столкновения шарика с препятствиями.
void Location();                                                                      // Функция прорисовки локации.
void LevelWin();                                                                      // Функция прохождения уровня.
void GameWin();                                                                       // Функция прохождения игры.
void Position();                                                                      // Функция для задания начального положения шарика и лунки.
void ShowLevel();                                                                     // Функция вывода заставки уровня.
void StartScreen();                                                                   // Функция вывода заставки игры.
                                                                                      //
void setup()                                                                          //
{                                                                                     //
  myOLED.begin();                                                                     // Инициируем работу с дисплеем.
  myOLED.autoUpdate(false);                                                           // Запрещаем автоматический вывод данных. Информация на дисплее будет обновляться только после обращения к функции update().
                                                                                      //
  while(!Serial){}                                                                    // Ждём готовность Serial к передаче данных в монитор последовательного порта.
  sensor.begin(true);                                                                 // Инициируем работу с датчиками объекта sensor.
                                                                                      // 
  StartScreen();                                                                      // Выводим заставку игры.
  Level = startLevel - 1;                                                             // Присваиваем переменной выбора уровня первый уровень. Цифра ноль соответствует первому элементу двумерного массива.
  ShowLevel();                                                                        // Показываем заставку уровня.
  Position();                                                                         // Определяем начальные координаты шарика и координаты лунки.
  Location();                                                                         // Прорисовываем локацию.
}                                                                                     //
                                                                                      //
void loop()                                                                           //
{                                                                                     //
  xs = x; ys = y;                                                                     // Каждый цикл присваиваем вспомогательным переменным предыдущие координаты шарика.
  Logic();                                                                            // Двигаем шарик в зависимости от направления. От угла наклона акселерометра.
  Draw();                                                                             // Рисуем шарик на новых координатах.
  CheckBlock();                                                                       // Проверяем не столкнулся ли шарик с преградой.
  LevelWin();                                                                         // Проверяем выигрышную позицию.
  myOLED.update();                                                                    // Разрешаем автоматический вывод данных.
}                                                                                     //
                                                                                      //
void StartScreen(){                                                                   // Функция вывода заставки игры.
  myOLED.drawRect (0, 0, 127, 63, false, 1);                                          // Прорисовываем рамку игрового поля.
  myOLED.setFont(MediumFontRus);                                                      // Указываем шрифт который требуется использовать для вывода цифр и текста.
  myOLED.print("ЛАБИРИНТ", OLED_C, 60);                                               // Выводим текст по центру 50 строки.
                                                                                      //
  for (int i = 35; i >= 3; i = i - 8) {                                               // Цикл формирования картинки.          //
  myOLED.drawRect   (30, i,  36, i + 6, true , 1);}                                   // Выводим картинку на экран.           //
  for (int i = 30; i <= 94; i = i + 8){                                               // Цикл формирования картинки.          //        # # # # # # # # #
  myOLED.drawRect   (i, 3,  i + 6, 9, true , 1);}                                     // Выводим картинку на экран.           //        #               #
  for (int i = 3; i <= 35; i = i + 8) {                                               // Цикл формирования картинки.          //        #   # # # # #   #
  myOLED.drawRect   (94, i,  100, i + 6, true , 1);}                                  // Выводим картинку на экран.           //        #               #
  for (int i = 94; i >= 30; i = i - 8){                                               // Цикл формирования картинки.          //        # # # # # # # # #
  myOLED.drawRect   (i, 35,  i + 6, 41, true , 1);}                                   // Выводим картинку на экран.           //
  for (int i = 46; i <= 78; i = i + 8){                                               // Цикл формирования картинки.          //
  myOLED.drawRect   (i, 19,  i + 6, 25, true , 1);}                                   // Выводим картинку на экран.           //
                                                                                      // 
  x = 89; y = 29; xh = 41; yh = 29;                                                   // Координаты начального положения шарика и лунки для анимации заставки
                                                                                      //
  for (int i = 1; i <= 48; i++){                                                      // Цикл формирования анимацию.
  xs = x; ys = y;                                                                     // Каждый цикл присваиваем вспомогательным переменным предыдущие координаты шарика.
  x--;                                                                                // Двигаем шарик влево.
  myOLED.drawCircle (xs, ys, 2,  true, 0);                                            // Очищаем последнее положения шарика.
  myOLED.drawCircle ( x,  y, 2,  true, 1);                                            // Рисуем шарик в указанных координатах радиусом 2.
  myOLED.drawCircle (xh, yh, 3, false, 1);                                            // Рисуем лунку в указанных координатах радиусом 3.
  myOLED.update();}                                                                   // Разрешаем автоматический вывод данных.
  delay(2000);                                                                        // Задержка 2 секунды.
                                                                                      //  
  myOLED.clrScr();                                                                    // Чистим экран.
  myOLED.drawRect (0, 0, 127, 63, false, 1);                                          // Прорисовываем рамку игрового поля.
  myOLED.print("От", OLED_C, 25);                                                     // Выводим текст по центру 20 строки.
  myOLED.print("IARDUINO", OLED_C, 50);                                               // Выводим текст по центру 20 строки.
  myOLED.update();                                                                    // Разрешаем автоматический вывод данных.
  delay (2000);                                                                       // Задержка 2 секунды.
}                                                                                     //
                                                                                      //
void ShowLevel(){                                                                     // Функция показа заставки уровня.
  myOLED.clrScr();                                                                    // Очищаем дисплей.
  myOLED.drawRect (0, 0, 127, 63, false, 1);                                          // Прорисовываем рамку игрового поля.
  myOLED.setFont(MediumFontRus);                                                      // Указываем шрифт который требуется использовать для вывода цифр и текста.
  myOLED.print("Уровень", 12, OLED_C);                                                // Выводим текст по центру 5 столбца.
  myOLED.print(Level+1, 101, OLED_C);                                                 // Выводим текст по центру 100 столбца.
  myOLED.update();                                                                    // Разрешаем автоматический вывод данных.
  delay(3000);                                                                        // Задержка 3 секунды.
}                                                                                     //
                                                                                      //
void GameWin(){                                                                       // Функция прохождения игры.
  if (Level == quantityLevel){                                                        // Сравниваем переменную выбора уровня с числом 5. Если она равна пяти, то игра пройдена.
    myOLED.clrScr();                                                                  // Очищаем дисплей.
    myOLED.setFont(MediumFontRus);                                                    // Указываем шрифт который требуется использовать для вывода цифр и текста.
    myOLED.print("ВЫИГРЫШ!", 20, OLED_C);                                             // Выводим текст по центру 20 столбца.
    myOLED.update();                                                                  // Разрешаем автоматический вывод данных.
    delay(3000);                                                                      // Задержка 3 секунды.
    return setup();                                                                   // Возвращаемся в начало игры.
  }                                                                                   //
}                                                                                     //
void LevelWin(){                                                                      // функция прохождения игры.
  if ( y == yh && x == xh || y == yh + 1 && x == xh || y == yh - 1 && x == xh || y == yh && x == xh + 1 || y == yh && x == xh - 1){ // Если координаты лунки совпадают с координатами шарика, то уровень пройден.
    Level++;                                                                          // Увеличиваем переменную выбора уровней на один. Будет отрисовываться следующий уровень.
    GameWin();                                                                        // Проверяем, мы прошли все уровни.
    ShowLevel();                                                                      // Показываем заставку следующего уровня.
    Position();                                                                       // Определяем начальные координаты шарика и координаты лунки следующего уровня.
    Location();                                                                       // Отрисовываем уровень.
    return loop();                                                                    // Возвращаемся в цикл игры.
  }                                                                                   //
}                                                                                     //
                                                                                      //
void Location(){                                                                      // Функция прорисовки уровня.
    for (int j = 0; j < 64; j++){                                                     // Прорисовываем массив с помощью циклов. Цикл по j соответствует X-координате.
    for (int i = 0; i < 32; i++){                                                     // Цикл по i соответствует Y-координате.
    myOLED.drawRect (j*2, i*2, j*2+2, i*2+2, true, bitRead(pgm_read_dword(&tableArray[Level][j]),i));}} // Заполняем поле квадратиками размером 2 на 2 пикселя в соответствии с выбранным массивом. Если бит элемента массива равен 1, то на экране отрисуется квадрат.
    myOLED.drawRect (0, 0, 127, 63, false, 1);                                        // Прорисовываем рамку игрового поля.
}                                                                                     //
                                                                                      //
void CheckBlock(){                                                                    // Функция проверки столкновения шарика с препятствием.
  if (x > 124 || x < 3 || y > 60 || y < 3){GameOver();}                               // Проверка выхода шарика за пределы игрового поля. Если координаты движения больше, чем игровое поле, то игра заканчивается.
  bool f = 0;                                                                         // Вспомогательная переменная для проверки совершения события.
  for(int i=x-2; i<=x+2; i++){                                                        // Проходим по колонкам шарика.
  for(int j=y-2; j<=y+2; j++){                                                        // Проходим по строкам шарика. Соответствуют координаты шарика с координатами препятствий.
  if(bitRead(pgm_read_dword(&tableArray[Level][i/2]),j/2)){f =1;}}}                   // Проверка на соответствие координат шарика с координатами препятствий. Если соответствуют, то присваиваем переменной события значение true.
  if(f){GameOver();}                                                                  // Если переменная события равна 1, то игра заканчивается.
}                                                                                     //
                                                                                      //
void Draw(){                                                                          // Функция отрисовки шарика и лунки.
  myOLED.drawCircle (xs, ys, 2,  true, 0);                                            // Очищаем последнее положения шарика.
  myOLED.drawCircle ( x,  y, 2,  true, 1);                                            // Рисуем шарик в указанных координатах радиусом 2.
  myOLED.drawCircle (xh, yh, 3, false, 1);                                            // Рисуем лунку в указанных координатах радиусом 3.
}                                                                                     //
                                                                                      //
void Logic(){                                                                         // Функция движения шарика.
  sensor.read();                                                                      // Читаем данные датчика (акселерометра).
                                                                                      // Движение влево.
  if (sensor.axisX <= -2.5){for (limited=3;limited >= 1;limited--){x--;}}             // Движение влево осуществляется при уменьшении Х-координаты в отрицательную сторону.
  if (sensor.axisX <= -1.5){for (limited=2;limited >= 1;limited--){x--;}}             // При уменьшении X-координаты, то есть увеличении наклона акселерометра влево, скорость передвижения шарика увеличивается.
  if (sensor.axisX <= -0.3){x--;}                                                     // Это реализовано с помощью цикла, который ограничивает прорисовку шарика. Шарик при большой скорости рисуется не в каждой следующей координате, а через определенное количество шагов в зависимости от скорости.
                                                                                      // Движение вправо.
  if (sensor.axisX >= 2.5){for (limited=3;limited >= 1;limited--){x++;}}              // Движение вправо осуществляется при увеличении Х-координаты в положительную сторону.
  if (sensor.axisX >= 1.5){for (limited=2;limited >= 1;limited--){x++;}}              // При увеличении X-координаты, то есть увеличении наклона акселерометра вправо, скорость передвижения шарика увеличивается.
  if (sensor.axisX >= 0.3){x++;}                                                      // Это реализовано с помощью цикла, который ограничивает прорисовку шарика. Шарик при большой скорости рисуется не в каждой следующей координате, а через определенное количество шагов в зависимости от скорости.
                                                                                      // Движение вниз.
  if (sensor.axisY <= -2.5){for (limited=3;limited >= 1;limited--){y++;}}             // Движение вниз осуществляется при уменьшении Y-координаты в отрицательную сторону.
  if (sensor.axisY <= -1.5){for (limited=2;limited >= 1;limited--){y++;}}             // При уменьшении Y-координаты, то есть увеличении наклона акселерометра вниз, скорость передвижения шарика увеличивается.
  if (sensor.axisY <= -0.3){y++;}                                                     // Это реализовано с помощью цикла, который ограничивает прорисовку шарика. Шарик при большой скорости рисуется не в каждой следующей координате, а через определенное количество шагов в зависимости от скорости.
                                                                                      // Движение вверх.
  if (sensor.axisY >= 2.5){for(limited=3;limited >= 1;limited--){y--;}}               // Движение вверх осуществляется при увеличении Y-координаты в положительную сторону.
  if (sensor.axisY >= 1.5){for(limited=2;limited >= 1;limited--){y--;}}               // При увеличении Y-координаты, то есть увеличении наклона акселерометра вверх, скорость передвижения шарика увеличивается.
  if (sensor.axisY >= 0.3){y--;}                                                      // Это реализовано с помощью цикла, который ограничивает прорисовку шарика. Шарик при большой скорости рисуется не в каждой следующей координате, а через определенное количество шагов в зависимости от скорости.
}                                                                                     //
                                                                                      //
void GameOver(){                                                                      // Функция завершения игры.
  myOLED.drawPixel (x+6, y, 1);                                                       // Прорисовываем картинку проигрышного положения.
  myOLED.drawPixel (x+5, y, 1);                                                       //
  myOLED.drawPixel (x+4, y, 1);                                                       //
  myOLED.drawPixel (x-6, y, 1);                                                       //
  myOLED.drawPixel (x-5, y, 1);                                                       //                              #
  myOLED.drawPixel (x-4, y, 1);                                                       //                         #    #    #
  myOLED.drawPixel (x, y+6, 1);                                                       //                          #   #   #  
  myOLED.drawPixel (x, y+5, 1);                                                       //                           #     #   
  myOLED.drawPixel (x, y+4, 1);                                                       //                             ###     
  myOLED.drawPixel (x, y-6, 1);                                                       //                            #####    
  myOLED.drawPixel (x, y-5, 1);                                                       //                        ### ##### ###
  myOLED.drawPixel (x, y-4, 1);                                                       //                            #####    
  myOLED.drawPixel (x+5, y+5, 1);                                                     //                             ###     
  myOLED.drawPixel (x+4, y+4, 1);                                                     //                           #     #   
  myOLED.drawPixel (x+3, y+3, 1);                                                     //                          #   #   #  
  myOLED.drawPixel (x-5, y-5, 1);                                                     //                         #    #    #
  myOLED.drawPixel (x-4, y-4, 1);                                                     //                              #
  myOLED.drawPixel (x-3, y-3, 1);                                                     //
  myOLED.drawPixel (x-5, y+5, 1);                                                     //
  myOLED.drawPixel (x-4, y+4, 1);                                                     //
  myOLED.drawPixel (x-3, y+3, 1);                                                     //
  myOLED.drawPixel (x+5, y-5, 1);                                                     //
  myOLED.drawPixel (x+4, y-4, 1);                                                     //
  myOLED.drawPixel (x+3, y-3, 1);                                                     //
  myOLED.update();                                                                    // Разрешаем автоматический вывод данных.
  delay(500);                                                                         // Задержка 500 мс.
  myOLED.clrScr();                                                                    // Очищаем экран.
  Position();                                                                         // Определяем начальные координаты шарика и координаты лунки следующего уровня.
  Location();                                                                         // Отрисовываем уровень.
  return loop();                                                                      // Возвращаемся в цикл игры.
}                                                                                     //
                                                                                      //
void Position()                                                                       // Функция для задания начального положения шарика и лунки.
{                                                                                     //
    x = pgm_read_dword(&tableArray[Level][64]);                                       // Координаты начального положения шарика в зависимости от уровня.
    y = pgm_read_dword(&tableArray[Level][65]);                                       //
                                                                                      //
    xh = pgm_read_dword(&tableArray[Level][66]);                                      // Координаты начального положения шарика и лунки второго уровня.
    yh = pgm_read_dword(&tableArray[Level][67]);                                      //
}                                                                                     //

Алгоритм работы:

  • В начале скетча (до кода setup) выполняются следующие действия:
    • Подключаем библиотеку iarduino_Position_BMX055 для работы с датчиком Trema IMU 9 DOF.
    • Объявляем объект sensor, указывая работу только с акселерометром.
    • Подключаем графическую библиотеку iarduino_OLED для работы с Trema OLED дисплеем.
    • Объявляем объект myOLED указывая адрес дисплея на шине I2C, он должен совпадать с адресом установленным переключателем на обратной стороне платы OLED дисплея.
    • Подключаем шрифты предустановленные в библиотеке myOLED.
    • Объявляем двумерный массив для локаций (лабиринта) и переменные участвующие в работе скетча.
    • Объявляем функции используемые в скетче.
  • В коде setup выполняются следующие действия:
    • Инициируем работу с Trema OLED дисплеем и запрещаем автоматический вывод данных.
    • Выводим заставку игры (текст «Лабиринт» на фоне картинки, функция "StartScreen()" и очищаем экран.
    • Инициируем работу с датчиком Trema IMU 9 DOF.
    • Определяем начальные параметры игры (Задаем уровень первый, показываем его заставку (функция" ShowLevel()"); задаем начальные координаты шарика и координаты лунки (функция "Position()"), прорисовываем локацию (лабиринт) первого уровня (функция "Location()").
  • В коде loop выполняются следующие действия:
    • Запоминаем предыдущие координаты шарика, чтобы потом очищать след от шарика.
    • Функция "Logic()", функция логики движения шарика. В ней происходит считывание данных акселерометра и в зависимости от наклона акселерометра, шарик двигается в заданном направлении. При увеличении наклона акселерометра, увеличивается скорость передвижения шарика.
    • Функция "Draw()", функция прорисовки шарика и лунки. А так же очищаем след от шарика.
    • Функция "CheckBlock()", функция проверки столкновения шарика с препятствием. В ней происходит проверка выхода шарика за пределы игрового поля, а так проверка столкновения шарика с препятствием по средством проверки координат самого шарика с координатами препятствия локации (лабиринта) в заданном массиве уровня. Если произошло столкновение, то игра заканчивается (функция "GameOver()"). При этом, пройденные уровни сохраняются до отключения питания.
    • Функция "LevelWin()", функция проверки выигрыша игроком уровня. В ней, если игрок загонят шарик в лунку, то уровень пройден. Если пройдены все уровни то игра закончится с вашим выигрышем (функция "GameWin()").
    • Разрешаем автоматический вывод данных.

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

Виды уровней:

В игре присутствуют пять видов уровней. Они показаны на рисунках 2 ниже:

Уровень 1 Уровень 2 Уровень 3 Уровень 4 Уровень 5

Рисунок 2

Добавление уровней:

Существует возможность создать свой уровень и добавить его в программу. Для этого нам понадобиться:

  1. Открыть код программы в начале скетча.
  2. Указать количество уровней. Для этого переменную "quantityLevel" присваиваем новое значение. По умолчанию указана цифра "5", что соответствует пяти уровням. Если нам необходимо добавить шестой уровень, указываем цифру "6".
  3. Создать новый массив, как очередной элемент двумерного массива" tableArray[]". Для этого можно скопировать уже имеющийся массив и вставить его в поле, где указано "Место для нового массива нового уровня." Не забудьте обязательно скопировать скобки, ограничивающий новый массив, вместе с запятой после второй скобки. Либо составить массив вручную в указанном поле.
  4. Задать новые координаты начального положения шарика и лунки. Для этого в конце массива необходимо указать 4 переменные. Первая переменная - это X - координата положения шарика. Вторая переменная - Y - координата положения шарика. Третья координата - это X - координата положения лунки. Четвертая переменная - это Y - координата положения лунки.
  5. После проделанных операций обязательно убедитесь что шарик расположен правильно и он не заходит за пределы препятствий, иначе новый уровень не запустится.
  6. Для быстрого перехода к созданному уровню, необходимо в начале программы переменной "startLevel" присвоить номер уровня. То есть, если необходимо загрузить шестой уровень, указываем цифру "6".

Ссылки:


Обсуждение