Dino Run на ESP32: Создаем игру на OLED 0.96 (Часть 1). Запускаем игру из Chrome своими руками
У каждого мейкера в ящике валяется пара лишних ESP32 и тот самый крошечный OLED-дисплей 0.96″, с которого начинаются 90% всех DIY-проектов. Сегодня мы заставим это железо работать на полную: мы портируем легендарного Динозаврика из Chrome на ESP32. В этой части мы не просто запустим игру, но и разберем, как реализовать физику прыжка в условиях ограниченных ресурсов микроконтроллера. А если у вас нет под рукой деталей — вы сможете запустить мой код в онлайн-симуляторе за один клик.
Железо и схема подключения
Для первой части нашего проекта мы будем использовать максимально доступные компоненты. I2C интерфейс позволяет подключить экран всего по двум сигнальным проводам.
Список компонентов:
Схема подключения компонентов
Для подключения мы используем интерфейс I2C. Это стандарт для OLED-дисплеев, который требует всего два сигнальных провода, помимо питания.
Важно: В коде мы будем использовать внутреннюю подтяжку пина кнопки (INPUT_PULLUP), поэтому дополнительный резистор на кнопку ставить не обязательно — просто подключаем её напрямую между пином 15 и землей (GND).
| Компонент | Пин дисплея / кнопки | Пин ESP32 (GPIO) | Описание |
|---|---|---|---|
| OLED Display | VCC | 3.3V | Питание дисплея |
| OLED Display | GND | GND | Общий минус |
| OLED Display | SCL | GPIO 22 | Тактовая линия I2C |
| OLED Display | SDA | GPIO 21 | Линия данных I2C |
| Кнопка | Pin 1 | GPIO 15 | Сигнал прыжка |
| Кнопка | Pin 2 | GND | Замыкание на землю |
Симуляция в Wokwi: Тестируем без железа
Перед тем как брать в руки паяльник, я рекомендую проверить всё в онлайн-симуляторе. Это сэкономит время на отладку.
Попробовать игру в браузере:
Разбор программной части
Для работы экрана нам понадобятся проверенные инструменты от Adafruit. Вы можете установить их через «Менеджер библиотек» в Arduino IDE или скачать напрямую с GitHub:
Совет: При установке через менеджер библиотек Arduino IDE предложит установить все зависимости (dependencies) — обязательно соглашайтесь, чтобы не скачивать каждый компонент вручную. Adafruit BusIO эта библиотека загрузится автоматически
Логика игрового цикла
Программа для ESP32 состоит из двух основных фаз: подготовки (setup) и бесконечного повторения (loop). В играх это называется «игровым движком».
Функция loop() — Игровой цикл
Здесь мы «будим» железо. Программа выполняется один раз при включении питания:
Функция setup() — Инициализация
Это сердце игры. Цикл повторяется десятки раз в секунду, создавая иллюзию движения:
Физика прыжка (Пример кода) Dino Run на ESP32
Чтобы динозавр прыгал плавно, а не мгновенно телепортировался, мы используем простую математическую модель:
void updateDino() {
if (isJumping) {
velocity += gravity; // Гравитация тянет вниз
dinoY += velocity; // Изменяем высоту
// Проверка приземления
if (dinoY >= groundLevel) {
dinoY = groundLevel;
isJumping = false;
}
}
}Вход
Нажатие кнопки (GPIO 15).
Обработка
Расчет физики и логики игры.
Выход
Отрисовка кадра на OLED.
Код игры Dino Run на ESP32
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Настройки дисплея
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Пины
const int buttonPin = 15;
// Физика игры
int dinoY = 45; // Высота динозавра
int velocity = 0; // Скорость прыжка
int gravity = 2; // Гравитация
bool isJumping = false;
int obstacleX = 128; // Позиция кактуса
int score = 0;
void setup() {
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP); // Кнопка с внутренней подтяжкой
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("OLED не найден"));
for(;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
}
void loop() {
// 1. INPUT (Вход)
if (digitalRead(buttonPin) == LOW && !isJumping) {
velocity = -12; // Импульс прыжка вверх
isJumping = true;
}
// 2. PROCESS (Обработка)
// Логика прыжка
if (isJumping) {
dinoY += velocity;
velocity += gravity;
if (dinoY >= 45) {
dinoY = 45;
isJumping = false;
}
}
// Движение кактуса
obstacleX -= 6;
if (obstacleX < -10) {
obstacleX = 128;
score++;
}
// Проверка столкновения (упрощенная)
if (obstacleX > 15 && obstacleX < 25 && dinoY > 35) {
gameOver();
}
// 3. OUTPUT (Выход)
drawGame();
delay(30); // Ограничение FPS
}
void drawGame() {
display.clearDisplay();
// Рисуем землю
display.drawLine(0, 55, 128, 55, WHITE);
// Рисуем Динозавра (квадратик для простоты в 1 части)
display.fillRect(20, dinoY, 10, 10, WHITE);
// Рисуем кактус
display.fillRect(obstacleX, 45, 6, 10, WHITE);
// Рисуем счет
display.setCursor(0,0);
display.print("Score: ");
display.print(score);
display.display();
}
void gameOver() {
display.clearDisplay();
display.setCursor(30, 25);
display.setTextSize(2);
display.print("GAME OVER");
display.display();
delay(2000);
score = 0;
obstacleX = 128;
}

AndiBond.com
Поддержите проект AndiBond
Создание качественных гайдов, поиск рабочих решений и отладка кода занимают много времени. Все мои проекты остаются открытыми и бесплатными, чтобы каждый мог войти в мир электроники с минимальным порогом входа.
Если этот туториал сэкономил ваше время или помог запустить вашу первую игру на ESP32, вы можете поддержать развитие блога. Ваша поддержка помогает мне покупать новые датчики, дисплеи и контроллеры для будущих обзоров.
Каждый донат — это топливо для новых статей и видео. Спасибо, что вы со мной!»





Один комментарий