#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C // I2C address for the SSD1306 OLED
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Ultrasonic sensor pins
#define TRIG_PIN 7
#define ECHO_PIN 6
// Game variables
int birdY = SCREEN_HEIGHT / 2; // Bird's vertical position
int birdX = 20; // Bird's horizontal position
int obstacleX = SCREEN_WIDTH; // Obstacle's horizontal position
int obstacleGapY; // Obstacle's gap vertical position
const int obstacleGapSize = 20; // Size of the gap in the obstacle
bool gameOver = false;
// Timing variables
unsigned long lastObstacleUpdate = 0;
unsigned long lastFrameUpdate = 0;
// Function prototypes
void resetGame();
void updateGame();
void drawGame();
int getDistance();
void setup() {
Serial.begin(9600);
// Initialize OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.display();
// Initialize ultrasonic sensor
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
// Start the game
resetGame();
}
void loop() {
if (!gameOver) {
updateGame();
drawGame();
}
}
void resetGame() {
birdY = SCREEN_HEIGHT / 2;
obstacleX = SCREEN_WIDTH;
obstacleGapY = random(10, SCREEN_HEIGHT - obstacleGapSize - 10);
gameOver = false;
}
void updateGame() {
unsigned long currentTime = millis();
// Update bird position based on ultrasonic distance
int distance = getDistance();
birdY = map(constrain(distance, 1, 30), 1, 30, 0, SCREEN_HEIGHT - 1);
// Update obstacle position
if (currentTime - lastObstacleUpdate > 50) {
obstacleX -= 2; // Move obstacle to the left
if (obstacleX < -10) { // Reset obstacle when it goes off screen
obstacleX = SCREEN_WIDTH;
obstacleGapY = random(10, SCREEN_HEIGHT - obstacleGapSize - 10);
}
lastObstacleUpdate = currentTime;
}
// Check for collisions
if (birdY < 0 || birdY > SCREEN_HEIGHT - 1 ||
(birdX + 5 > obstacleX && birdX < obstacleX + 10 &&
(birdY < obstacleGapY || birdY > obstacleGapY + obstacleGapSize))) {
gameOver = true;
}
}
void drawGame() {
display.clearDisplay();
// Draw the bird as a small rectangle
display.fillRect(birdX, birdY, 5, 5, SSD1306_WHITE);
// Draw the obstacle
display.fillRect(obstacleX, 0, 10, obstacleGapY, SSD1306_WHITE); // Top part
display.fillRect(obstacleX, obstacleGapY + obstacleGapSize, 10, SCREEN_HEIGHT, SSD1306_WHITE); // Bottom part
// Display "Game Over" if game ends
if (gameOver) {
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20, SCREEN_HEIGHT / 2 - 10);
display.print("GAME OVER");
display.setCursor(20, SCREEN_HEIGHT / 2 + 10);
display.print("Reset Arduino");
}
display.display();
}
int getDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH);
int distance = duration * 0.034 / 2; // Convert to centimeters
return distance;
}