Пишем для Arduino на C++ игру в стиле Google Dino (https://trex-runner.com/). Из электронных компонентов нам понадобится плата Arduino NANO или UNO, дисплей MT16S2H или LCD 1602 подключённый к плате Arduino с помощью сдвигового регистра 74HC595B1 и кнопка. В программе используется библиотека LiquidCrystal_74HC595.

Легенда игры: Мы пошли пешком в пустыню и должны перепрыгнуть все встречающиеся на пути препятствия.

Задание на проектирование игры-тренажёра «Поход в пустыню»:

Символьный дисплей MT16S2H или LCD 1602 имеет две строки по 16 символов каждый символ на дисплее состоит из 8-ми строк по 5 пикселей. Расстояние между символами 1 пиксель. На этот дисплей нам необходимо вывести анимированного человечка, который должен уметь ходить и прыгать. Так же мы должны вывести на дисплей пустынный ландшафт, который преодолевает человечек. На экране дисплея действие будет происходить относительно воображаемой камеры, которая перемещается по пустыне вместе с человечком и снимает его. В результате, на экране дисплея человечек будет идти на месте, а пустыня будет двигаться на него. Все встречающиеся на пути препятствия человек преодолевает в прыжке. 

Идёт

Mov 1. Идущий человек. 

        

Mov 2. Подпрыгивающий человек и раскадровка. 

Управление человечком будет происходить с помощью одной кнопки, подключённой одним контактом к шине GND, а другим - к выводу D6 платы Arduino.

 Для упрощения интерфейса связи дисплея MT16S2H или LCD 1602 с микроконтроллером, мы соединили интерфейсные выводы этого дисплея с микросхемой CN74HC595B1. Микросхема CN74HC595B1 это сдвиговый регистр с защёлкой. Эта микросхема очень часто используется для преобразования последовательного интерфейса в параллельный. 

Управление дисплеем MT16S2H осуществляется с помощью 8- битной (DB0...DB7) или 4-битной (DB4...DB7) шины данных и двух линий управления (RS, E). см. рис. 1.

Микросхема CN74HC595B1 преобразует синхронный поток последовательных данных на входе SER в параллельные данные на своих выходах Q0...Q7. Для синхронной передачи данных по входу SER в микросхему CN74HC595B1 должны быть задействованы входы синхронизации SRCLK (вход тактовых импульсов) и RCLK  (строб передачи байта данных).

В связке, дисплея MT16S2H и микросхемы CN74HC595B1 получился двух-строчный, по 16 символов в каждой строке, дисплей с последовательным интерфейсом передачи данных.

Рис. 1. Схема подключения буквенно-цифрового индикатора МТ-16S2H к плате Arduino с помощью сдвигового регистра 74HC595B1.

Рис. 2. Макет игры «Красный или синий». 

#include <LiquidCrystal_74HC595.h>
LiquidCrystal_74HC595 lcd(4, 3, 2, 1, 2, 3, 4, 5, 6);

#define imgs 3

byte man[imgs][8] = {
   {
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000
  }, 
  {
    0b01110,
    0b01110,
    0b00100,
    0b01111,
    0b10100,
    0b00110,
    0b01011,
    0b11000
  },
  {
    0b01110,
    0b01110,
    0b00100,
    0b11110,
    0b00101,
    0b01100,
    0b11010,
    0b00011
  }
};

void setup() {
  lcd.begin(16, 2);
  for (int i = 0; i < imgs; i++) {
    lcd.createChar(i, man[i]);
  }
  lcd.setCursor(0, 0);
  lcd.write(byte(0)); // when calling lcd.write() '0' must be cast as a byte
  lcd.write(1);
  lcd.write(2);
}

void loop() {
  lcd.setCursor(6, 1);
  lcd.write(1);
  delay(500);
  lcd.setCursor(6, 1);
  lcd.write(2);
  delay(500);
}

Программа 1. Для mov 1.

  1. В программе 1 в первой строке мы подключаем библиотеку, а далее  с помощью конструктора класса из этой библиотеки создаём объект lcd. Конструктору класса, в качестве параметров требуются три номера выводов (портов) на плате Arduino к которым подключена микросхема 595 и номера пяти ножек микросхемы 595 к которым подключён LCD дисплей. Перечислим параметры конструктора класса по порядку: SER, SRCLK, RCLK, RS
#include <LiquidCrystal_74HC595.h>
LiquidCrystal_74HC595 lcd(4, 3, 2, 1, 2, 3, 4, 5, 6);

#define imgs 5

byte man[imgs][8] = {
   {
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000
  }, 
  {
    0b01110,
    0b01110,
    0b00100,
    0b01110,
    0b10101,
    0b00100,
    0b01010,
    0b11011
  },
  {
    0b00000,
    0b01110,
    0b01110,
    0b10101,
    0b01110,
    0b00100,
    0b01010,
    0b11011
  },
  {
    0b01110,
    0b01110,
    0b00100,
    0b01111,
    0b10100,
    0b00110,
    0b01011,
    0b11000
  },
  {
    0b01110,
    0b01110,
    0b00100,
    0b11110,
    0b00101,
    0b01100,
    0b11010,
    0b00011
  }
};

void setup() {
  lcd.begin(16, 2);
  for (int i = 0; i < imgs; i++) {
    lcd.createChar(i, man[i]);
  }
  lcd.setCursor(0, 0);
  lcd.write(byte(0)); // when calling lcd.write() '0' must be cast as a byte
  lcd.write(1);
  lcd.write(2);
  lcd.write(3);
  lcd.write(4);
}

void loop() {
  lcd.setCursor(8, 1);
  lcd.write(1);
  lcd.setCursor(6, 1);
  lcd.write(3);
  delay(500);
  lcd.setCursor(8, 1);
  lcd.write(2);
  lcd.setCursor(6, 1);
  lcd.write(4);
  delay(500);
  lcd.setCursor(8, 1);
  lcd.write(3);
  lcd.setCursor(6, 1);
  lcd.write(3);
  delay(500);
  lcd.setCursor(8, 1);
  lcd.print(' ');
  lcd.setCursor(8, 0);
  lcd.write(2);
  lcd.setCursor(6, 1);
  lcd.write(4);
  delay(500);
   lcd.setCursor(8, 0);
  lcd.write(2);
  lcd.setCursor(6, 1);
  lcd.write(3);
  delay(500);
   lcd.setCursor(8, 0);
  lcd.write(1);
  lcd.setCursor(6, 1);
  lcd.write(1);
  delay(500);
  lcd.setCursor(8, 0);
  lcd.print(' ');
}

Программа 2.