Flappy Bird

Typ_projektu
Arduino
Zdjecie główne
Krótki opis projektu

Projekt przedstawia klasyczną grę Flappy Bird, zaadaptowaną na mikrokontroler Arduino z wyświetlaczem OLED 128x64 (SSD1306). Gracz steruje ptakiem, który musi unikać przeszkód w postaci rur – rozgrywka polega na utrzymaniu się w powietrzu, klikając przycisk, który powoduje skok ptaka.

Niezbędne elementy

1. Płytka Arduino UNO lub kompatybilna
2. Shield SIC Game Console

Sprzęt

Komputer PC z Arduino IDE

Opis projektu

Projekt przedstawia klasyczną grę Flappy Bird, zaadaptowaną na mikrokontroler Arduino z wyświetlaczem OLED 128x64 (SSD1306). Gracz steruje ptakiem, który musi unikać przeszkód w postaci rur – rozgrywka polega na utrzymaniu się w powietrzu, klikając przycisk, który powoduje skok ptaka.

Głównymi założeniami gry są:
- opadanie postaci pod wpływem grawitacji
- zakończenie gry gdy postać dotknie przeszkody lub spadnie poza ekran
- po zakończeniu gry wyświetlany jest wynik oraz rekord
- po uzyskaniu 5pkt zmienia się grafika gry

Zdjęcia
kod programu

#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);

 

// Pins

const int buttonPin = 9;   //wybrort przyciskou do skoku

const int gravity = 1;     //wsp grawiatcji 

const int flapStrength = -5; //zmniejszac wrtosc z np. -4 na -5 powodujemyu wiekszy skok postaci

 

 

// wyglad postaci - bitmapa

const unsigned char PROGMEM flappyBirdSprite[] = {

  0b00001110,

  0b00001010,

  0b00001111,

  0b01111110,

  0b01111100,

  0b01111100,

  0b00010000,

  0b00010000

};

 

const unsigned char PROGMEM flappyBirdSpriteNew[] = {

  0b00011100,

  0b00111110,

  0b00101010,

  0b00111110,

  0b00100010,

  0b00111110,

  0b00111110,

  0b00101010

};

 

// Bird

int birdY;

int birdVelocity = 0;

const int birdX = 20;

 

// Pipes

int pipeX;

int pipeGap = 25;

int pipeTopHeight;

bool passedPipe = false;

 

// Timing

unsigned long lastUpdate = 0;

int gameSpeed = 30;

 

// Game state

bool isGameOver = false;

bool isIntro = true;

bool gameOverFalling = false;

int score = 0;

int highScore = 0;

bool useNewBird = false;

bool useNewPipes = false;

 

// Debounce

unsigned long lastButtonPress = 0;

const int debounceDelay = 150;

 

bool isButtonPressed() {

  if (digitalRead(buttonPin) == LOW) {

    if (millis() - lastButtonPress > debounceDelay) {

      lastButtonPress = millis();

      return true;

    }

  }

  return false;

}

 

void setup() {

  pinMode(buttonPin, INPUT_PULLUP);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  display.setRotation(2);

  display.setTextSize(1);

  display.setTextColor(WHITE);

  birdY = SCREEN_HEIGHT / 2;

  showIntroScreen();

}

 

void resetGame() {

  if (score > highScore) highScore = score;

  birdY = SCREEN_HEIGHT / 2;

  birdVelocity = 0;

  pipeX = SCREEN_WIDTH;

  pipeTopHeight = random(10, 40);

  isGameOver = false;

  gameOverFalling = false;

  score = 0;

  passedPipe = false;

  useNewBird = false;

  useNewPipes = false;

}

 

void showIntroScreen() {

  display.clearDisplay();

  display.setCursor(25, 10);

  display.setTextSize(2);

  display.println("Flappy");

  display.setCursor(35, 28);

  display.println("Bird");

  display.setTextSize(1);

  display.setCursor(10, 55);

  display.println("Press button to start");

  //display.drawBitmap(birdX, birdY, flappyBirdSprite, 8, 8, WHITE); // rysowanie bitmapy powodowalo zacinanie sie gry

  display.display();

}

 

 

//animacja po przegranej tzn postac spada swobodnie do opuszczenia ekranu

void animateGameOverFall() {

  while (birdY < SCREEN_HEIGHT - 😎 {

    birdVelocity += gravity;

    birdY += birdVelocity;

    display.clearDisplay();

    display.drawBitmap(birdX, birdY, useNewBird ? flappyBirdSpriteNew : flappyBirdSprite, 8, 8, WHITE);

    display.display();

    delay(30);

  }

  gameOverFalling = false;

}

 

//ekran koncowy wyswietlajacy wynik i rekord gry

void showGameOverScreen() {

  display.clearDisplay();

  display.setCursor(25, 15);

  display.println("Game Over");

  display.setCursor(10, 35);

  display.print("Final: ");

  display.print(score);

  display.print("  Best: ");

  display.println(highScore);

  display.setCursor(15, 50);

  display.println("Press to restart");

  display.display();

}

 

void loop() {

  if (isIntro) {

    showIntroScreen();

    if (isButtonPressed()) {

      isIntro = false;

      resetGame();

    }

    delay(10);

    return;

  }

 

  if (isGameOver) {

    if (gameOverFalling) {

      animateGameOverFall();

    } else {

      showGameOverScreen();

      if (isButtonPressed()) {

        isIntro = true;

      }

    }

    return;

  }

 

  if (millis() - lastUpdate > gameSpeed) {

    lastUpdate = millis();

 

    if (isButtonPressed()) {

      birdVelocity = flapStrength;

    }

 

    birdVelocity += gravity;

    birdY += birdVelocity;

    if (birdY < 0) birdY = 0;

 

    pipeX -= 2;

 

    if (!passedPipe && pipeX + 10 < birdX) {

      score++;

      passedPipe = true;

      if (score >= 5) {

        useNewBird = true;

        useNewPipes = true;

      }

    }

 

    if (pipeX < -10) {

      pipeX = SCREEN_WIDTH;

      pipeTopHeight = random(10, 40);

      passedPipe = false;

    }

 

    if (birdY > SCREEN_HEIGHT ||

        (birdX + 8 > pipeX && birdX < pipeX + (useNewPipes ? 20 : 10) &&

         (birdY < pipeTopHeight || birdY > pipeTopHeight + pipeGap))) {

      isGameOver = true;

      gameOverFalling = true;

      birdVelocity = 0;

      return;

    }

 

    // RENDER

    display.clearDisplay();

    display.drawBitmap(birdX, birdY, useNewBird ? flappyBirdSpriteNew : flappyBirdSprite, 8, 8, WHITE);

 

    if (useNewPipes) {

      display.fillRect(pipeX, 0, 20, pipeTopHeight, WHITE);

      display.fillRect(pipeX, pipeTopHeight + pipeGap, 20, SCREEN_HEIGHT - (pipeTopHeight + pipeGap), WHITE);

    } else {

      display.fillRect(pipeX, 0, 10, pipeTopHeight, WHITE);

      display.fillRect(pipeX, pipeTopHeight + pipeGap, 10, SCREEN_HEIGHT - (pipeTopHeight + pipeGap), WHITE);

    }

 

    display.setCursor(0, 0);

    display.print("Score: ");

    display.print(score);

    display.setCursor(80, 0);

    display.print("Best: ");

    display.print(highScore);

    display.display();

  }

}

Pliki_projektu
Schemat
Youtube
Tagi
projekt arduinouno flappybird OLED gra