#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
// Define screen dimensions
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Define the pin for the button
#define BUTTON_PIN 2
// Initialize the OLED display
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Define bird properties
int birdY = SCREEN_HEIGHT / 2;
int birdX = 15;
int birdSize = 2;
int birdVelocity = 0;
int gravity = 1;
int jumpStrength = -8;
// Define pipe properties
int pipeX = SCREEN_WIDTH;
int pipeWidth = 15;
int pipeGap = 40;
int pipeSpeed = 4;
int pipeGapY;
// Game state
bool gameOver = false;
bool buttonPressed = false;
int score = 0;
void setup() {
// Initialize serial communication for debugging
Serial.begin(9600);
// Initialize the OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
// Set the button pin as input with internal pull-up resistor
pinMode(BUTTON_PIN, INPUT_PULLUP);
// Randomly set the pipe gap position
randomSeed(analogRead(0));
pipeGapY = random(10, SCREEN_HEIGHT - pipeGap - 10);
// Display intro message
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(F("Flappy Bird Game"));
display.println(F("Press button to start"));
display.display();
// Wait for the player to press the button to start
while (digitalRead(BUTTON_PIN) == HIGH) {
// Button is not pressed (HIGH state due to pull-up resistor)
}
}
void loop() {
if (!gameOver) {
// Button press for jumping
if (digitalRead(BUTTON_PIN) == LOW && !buttonPressed) {
birdVelocity = jumpStrength;
buttonPressed = true;
}
if (digitalRead(BUTTON_PIN) == HIGH) {
buttonPressed = false;
}
// Apply gravity
birdVelocity += gravity;
birdY += birdVelocity;
// Pipe movement
pipeX -= pipeSpeed;
if (pipeX < -pipeWidth) {
pipeX = SCREEN_WIDTH;
pipeGapY = random(10, SCREEN_HEIGHT - pipeGap - 10);
score++;
}
// Check for collision with pipes or ground
if (birdY < 0 || birdY + birdSize > SCREEN_HEIGHT ||
(birdX + birdSize > pipeX && birdX < pipeX + pipeWidth &&
(birdY < pipeGapY || birdY + birdSize > pipeGapY + pipeGap))) {
gameOver = true;
}
// Clear the screen
display.clearDisplay();
// Draw the bird
display.fillCircle(birdX, birdY, birdSize, SSD1306_WHITE);
// Draw the pipes
display.fillRect(pipeX, 0, pipeWidth, pipeGapY, SSD1306_WHITE);
display.fillRect(pipeX, pipeGapY + pipeGap, pipeWidth, SCREEN_HEIGHT - pipeGapY - pipeGap, SSD1306_WHITE);
// Display the score
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("Score: "));
display.print(score);
// Update the display
display.display();
// Delay for game speed
delay(20);
} else {
// Game over screen
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("Game Over!"));
display.setCursor(0, 10);
display.print(F("Score: "));
display.print(score);
display.setCursor(0, 20);
display.println(F("Press button to restart"));
display.display();
// Wait for button press to restart the game
while (digitalRead(BUTTON_PIN) == HIGH) {
// Button is not pressed (HIGH state due to pull-up resistor)
}
resetGame();
}
}
void resetGame() {
// Reset game variables
birdY = SCREEN_HEIGHT / 2;
birdVelocity = 0;
pipeX = SCREEN_WIDTH;
score = 0;
gameOver = false;
pipeGapY = random(10, SCREEN_HEIGHT - pipeGap - 10);
}