#include <Adafruit_SSD1306.h>
// made by ultramegabombastiucfuze on https://projecthub.arduino.cc/
#define BUTTON_PIN 3 // button pin
// Game state variables
bool isJumping = false;
bool gameOver = false;
int dinoY = 40;
int velocity = 0;
const int gravity = 2;
const int groundY = 40;
int cactusX1 = 128;
int cactusX2 = 180;
int gameSpeed = 3;
unsigned long lastSpeedIncrease = 0;
unsigned long lastFrame = 0;
unsigned long score = 0;
// Button debounce state
bool buttonPressed = false;
Adafruit_SSD1306 display(128, 64, &Wire, -1);
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP); // Enable internal pull-up
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
while (1);
}
display.clearDisplay();
display.display();
randomSeed(analogRead(0)); // Randomize cactus spawn
}
void loop() {
unsigned long currentTime = millis();
if (currentTime - lastFrame < 50) return;
lastFrame = currentTime;
int buttonState = digitalRead(BUTTON_PIN);
// --- GAME OVER & RESTART HANDLING ---
if (gameOver) {
if (buttonState == HIGH && !buttonPressed) {
buttonPressed = true;
}
if (buttonState == LOW && buttonPressed) {
buttonPressed = false;
resetGame();
}
return;
}
// --- JUMP HANDLING ---
if (buttonState == HIGH && !buttonPressed && dinoY == groundY) {
buttonPressed = true;
isJumping = true;
velocity = -13;
}
if (buttonState == LOW) {
buttonPressed = false;
}
// --- PHYSICS ---
if (isJumping) {
dinoY += velocity;
velocity += gravity;
if (dinoY >= groundY) {
dinoY = groundY;
isJumping = false;
}
}
// --- MOVE CACTI ---
cactusX1 -= gameSpeed;
cactusX2 -= gameSpeed;
if (cactusX1 < -10) {
cactusX1 = 128 + random(0, 40);
if (random(0, 10) > 6) cactusX2 = cactusX1 + random(15, 30);
}
if (cactusX2 < -10) {
cactusX2 = 128 + random(30, 60);
}
// --- SPEED UP ---
if (currentTime - lastSpeedIncrease > 3000) {
gameSpeed++;
lastSpeedIncrease = currentTime;
}
// --- SCORE ---
score++;
// --- DRAW SCENE ---
display.clearDisplay();
display.fillRect(10, dinoY, 10, 10, SSD1306_WHITE); // Dino
display.fillRect(cactusX1, groundY, 10, 15, SSD1306_WHITE); // Cactus 1
display.fillRect(cactusX2, groundY, 10, 15, SSD1306_WHITE); // Cactus 2
display.drawLine(0, 58, 128, 58, SSD1306_WHITE); // Ground
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Score: ");
display.print(score / 10);
display.display();
// --- COLLISION DETECTION ---
bool hitCactus1 = (cactusX1 < 20 && cactusX1 > 5 && dinoY == groundY);
bool hitCactus2 = (cactusX2 < 20 && cactusX2 > 5 && dinoY == groundY);
if (hitCactus1 || hitCactus2) {
gameOver = true;
// Step 1: Show "You Lose!"
display.clearDisplay();
display.setTextSize(2);
display.setCursor(25, 20);
display.print("You Lose!");
display.display();
delay(3000); // Show for 3 seconds
// Step 2: Show "Game Over - Press to Restart"
display.clearDisplay();
display.setTextSize(2);
display.setCursor(20, 20);
display.print("Game Over");
display.setTextSize(1);
display.setCursor(10, 45);
display.print("Press to restart");
display.display();
}
}
// --- RESTART GAME FUNCTION ---
void resetGame() {
isJumping = false;
dinoY = groundY;
velocity = 0;
cactusX1 = 128;
cactusX2 = 180;
gameSpeed = 3;
score = 0;
gameOver = false;
lastSpeedIncrease = millis();
lastFrame = millis();
display.clearDisplay();
display.display();
}