#include <Wire.h> // библиотека для протокола IIC
#include <Adafruit_GFX.h> // библиотека для работы с графикой
#include <Adafruit_SSD1306.h> // библиотека для работы с SSD1306 OLED
#define SCREEN_WIDTH 128 // ширина дисплея в пикселях
#define SCREEN_HEIGHT 64 // высота дисплея в пикселях
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // создаем объект дисплея
int level = 1; // переменная для отсчета уровня
int pause = 400; // переменная для задержки
byte p1 = 0; // переменная для времени прыжка первого игрока
byte p2 = 0; // переменная для времени прыжка второго игрока
// создаем массивы дракончика, дерева, камня и птицы
const unsigned char dracon[] PROGMEM = {
0x7C, 0xFE, 0xFE, 0xFC, 0xFE, 0x6C, 0x92, 0xDB
};
const unsigned char dracon_flipped[] PROGMEM = {
0xDB, 0x92, 0x6C, 0xFE, 0xFC, 0xFE, 0xFE, 0x7C
};
const unsigned char derevo[] PROGMEM = {
0x00, 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0x36, 0x36
};
const unsigned char derevo_flipped[] PROGMEM = {
0x36, 0x36, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00
};
const unsigned char kamen[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE
};
const unsigned char kamen_flipped[] PROGMEM = {
0xFE, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void setup() {
pinMode(A1, INPUT_PULLUP); // подключаем первую кнопку с использованием внутреннего подтягивающего резистора
pinMode(A2, INPUT_PULLUP); // подключаем вторую кнопку с использованием внутреннего подтягивающего резистора
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // инициализация дисплея
for(;;); // если не удалось инициализировать, зацикливаемся
}
display.clearDisplay(); // очищаем дисплей
display.setTextSize(2); // устанавливаем размер текста
display.setTextColor(SSD1306_WHITE); // устанавливаем цвет текста
// начинаем игру: выводим надпись GO!
display.setCursor(48, 0);
display.print("GO!");
display.display();
delay(400);
display.clearDisplay();
}
void loop() {
unsigned long currentMillis = millis();
static unsigned long previousMillis = 0;
const long interval = pause;
// первоначальное положение дракончиков и препятствия
byte d1 = 0; // первый дракончик находится вверху
byte d2 = 0; // второй дракончик находится внизу
byte x1 = 15; // позиция препятствия для верхнего динозаврика
byte x2 = 15; // позиция препятствия для нижнего динозаврика
byte y1 = 1; // тип препятствия для верхнего динозаврика
byte y2 = 1; // тип препятствия для нижнего динозаврика
// выбираем препятствия, которые появятся, рандомно
byte i1 = random(1, 3); // 1 - дерево, 2 - камень
byte i2 = random(1, 3); // 1 - дерево, 2 - камень
while (x1 > 0 || x2 > 0) {
// очищаем экран и выводим номер уровня
display.clearDisplay();
display.setCursor(0, 0);
display.print(level);
// считываем данные с кнопок и учитываем количество циклов в прыжке
// если дракончики находятся в прыжке долго - возвращаем их вниз
if (digitalRead(A1) == LOW) d1 = 1; // Первая кнопка нажата, первый дракончик прыгает
if (digitalRead(A1) == HIGH) d1 = 0; // Первая кнопка не нажата, первый дракончик на земле
if (p1 > 3) d1 = 0; // Если первый дракончик в прыжке долго, возвращаем его на землю
if (digitalRead(A2) == LOW) d2 = 1; // Вторая кнопка нажата, второй дракончик прыгает
if (digitalRead(A2) == HIGH) d2 = 0; // Вторая кнопка не нажата, второй дракончик на земле
if (p2 > 3) d2 = 0; // Если второй дракончик в прыжке долго, возвращаем его на землю
// выводим первого дракончика в нужной строке
display.setCursor(4 * 8, d1 * 16);
display.drawBitmap(4 * 8, d1 * 16, dracon_flipped, 8, 8, SSD1306_WHITE);
// выводим второго дракончика в нужной строке
display.setCursor(4 * 8, SCREEN_HEIGHT - 8); // второй дракончик всегда на нижней грани
display.drawBitmap(4 * 8, SCREEN_HEIGHT - 8, dracon, 8, 8, SSD1306_WHITE);
// выводим препятствие для верхнего динозаврика
display.setCursor(x1 * 8, 0); // препятствие для верхнего динозаврика по верхнему краю
if (i1 == 1) display.drawBitmap(x1 * 8, 0, derevo_flipped, 8, 8, SSD1306_WHITE);
else if (i1 == 2) display.drawBitmap(x1 * 8, 0, kamen_flipped, 8, 8, SSD1306_WHITE);
// выводим препятствие для нижнего динозаврика
display.setCursor(x2 * 8, SCREEN_HEIGHT - 8); // препятствие для нижнего динозаврика по нижнему краю
if (i2 == 1) display.drawBitmap(x2 * 8, SCREEN_HEIGHT - 8, derevo, 8, 8, SSD1306_WHITE);
else if (i2 == 2) display.drawBitmap(x2 * 8, SCREEN_HEIGHT - 8, kamen, 8, 8, SSD1306_WHITE);
// если дракончики наткнулись на препятствие выводим надпись GAME OVER!
if ((x1 == 4 && d1 == 0) || (x2 == 4 && d2 == 0)) {
delay(400);
display.clearDisplay();
delay(200);
display.setCursor(16, 0);
display.print("GAME OVER!");
display.display();
delay(600);
display.clearDisplay();
delay(400);
display.setCursor(16, 0);
display.print("GAME OVER!");
display.display();
delay(600);
display.clearDisplay();
display.setCursor(16, 16);
display.print("LEVEL: ");
display.print(level);
display.display();
delay(400);
display.setCursor(16, 0);
display.print("GAME OVER!");
display.display();
delay(3000);
display.clearDisplay();
// начинаем игру заново, обнулив уровень игры
display.setCursor(48, 0);
display.print("GO!");
display.display();
delay(400);
display.clearDisplay();
level = 0;
pause = 400;
p1 = 0;
p2 = 0;
x1 = 0;
x2 = 0;
break;
}
// если дракончики не столкнулись, то меняем положение препятствий
// начинаем считать сколько циклов дракончики находятся в прыжке
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (x1 > 0) x1 = x1 - 1;
if (x2 > 0) x2 = x2 - 1;
p1 = p1 + 1;
p2 = p2 + 1;
if (p1 > 4) p1 = 0;
if (p2 > 4) p2 = 0;
}
display.display(); // обновляем дисплей
}
// переходим на следующий уровень и сокращаем время задержки
level = level + 1;
pause = pause - 2;
}