#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Preferences.h> // Библиотека для работы с энергонезависимой памятью
// Настройки дисплея и пинов
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define BUZZER_PIN 25
#define BUTTON_PIN 15
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
Preferences preferences;
// Игровые переменные
int dinoY = 45;
int velocity = 0;
int gravity = 2;
bool isJumping = false;
int obstacleX = 128;
int score = 0;
int highScore = 0;
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("OLED не найден"));
for(;;);
}
// Загружаем рекорд из памяти
preferences.begin("dino-game", false);
highScore = preferences.getInt("highscore", 0);
showStartScreen();
}
void playSound(int freq, int duration) {
tone(BUZZER_PIN, freq, duration);
}
void loop() {
// 1. ВВОД (Кнопка)
if (digitalRead(BUTTON_PIN) == LOW && !isJumping) {
velocity = -12;
isJumping = true;
playSound(600, 100); // Звук прыжка
}
// 2. ЛОГИКА (Физика)
if (isJumping) {
dinoY += velocity;
velocity += gravity;
if (dinoY >= 45) {
dinoY = 45;
isJumping = false;
}
}
// Движение препятствия
obstacleX -= 7;
if (obstacleX < -10) {
obstacleX = 128;
score++;
// Короткий звук за каждое пройденное препятствие (опционально)
// playSound(1000, 10);
}
// Проверка столкновения
if (obstacleX > 15 && obstacleX < 25 && dinoY > 35) {
handleGameOver();
}
// 3. ОТРИСОВКА
drawGame();
delay(30);
}
void showStartScreen() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(25, 15);
display.print("DINO RUN ESP32");
display.setCursor(20, 35);
display.print("HI-SCORE: ");
display.print(highScore);
display.setCursor(15, 50);
display.print("Press to Start");
display.display();
// Цикл ожидания нажатия
while(digitalRead(BUTTON_PIN) == HIGH) {
delay(10);
}
playSound(800, 100);
delay(200); // Антидребезг
}
void handleGameOver() {
playSound(150, 600); // Грустный звук проигрыша
// Проверяем и сохраняем новый рекорд
if (score > highScore) {
highScore = score;
preferences.putInt("highscore", highScore);
}
display.clearDisplay();
display.setCursor(30, 15);
display.setTextSize(2);
display.print("GAME OVER");
display.setTextSize(1);
display.setCursor(40, 40);
display.print("Score: "); display.print(score);
display.setCursor(35, 52);
display.print("HI-Score: "); display.print(highScore);
display.display();
delay(2000);
// Сброс игры
score = 0;
obstacleX = 128;
dinoY = 45;
showStartScreen(); // Возврат на главный экран
}
void drawGame() {
display.clearDisplay();
// Текущий счет и Рекорд
display.setTextSize(1);
display.setCursor(0, 0);
display.print("S:"); display.print(score);
display.setCursor(60, 0);
display.print("HI:"); display.print(highScore);
// Земля
display.drawLine(0, 55, 128, 55, WHITE);
// Дино (квадрат)
display.fillRect(20, dinoY, 10, 10, WHITE);
// Кактус (прямоугольник)
display.fillRect(obstacleX, 45, 6, 10, WHITE);
display.display();
}