#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

#define OLED_RESET    -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define BUTTON_PIN 2

int dino_pos_y = SCREEN_HEIGHT - 10;
float dino_vel_y = 0;
bool dino_jump = false;

int obstacle_pos_x = SCREEN_WIDTH;
int obstacle_width = 10;
int obstacle_speed = 2;
float game_speed = 0.1;
int score = 0;

void setup() {
  Serial.begin(9600);

  pinMode(BUTTON_PIN, INPUT_PULLUP);

  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }

  display.display();
  delay(2000);
  display.clearDisplay();
}

void drawDinosaur(int y) {
  display.fillRect(10, y, 8, 8, WHITE);
  display.fillRect(20, y+2, 4, 6, WHITE);
  display.drawPixel(8, y+4, WHITE);
}

void drawObstacle(int x, int width) {
  display.fillRect(x, SCREEN_HEIGHT-10, width, 10, WHITE);
}

void jump() {
  if (!dino_jump) {
    dino_vel_y = -2;
    dino_jump = true;
  }
}

void gameOver() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(25, SCREEN_HEIGHT/2);
  display.println(F("GAME OVER"));
  display.setCursor(30, SCREEN_HEIGHT/2 + 10);
  display.print(F("Score: "));
  display.println(score);
  display.display();
  delay(2000);
  resetGame();
}

void resetGame() {
  dino_pos_y = SCREEN_HEIGHT - 10;
  dino_vel_y = 0;
  dino_jump = false;
  obstacle_pos_x = SCREEN_WIDTH;
  score = 0;
}

void gameLoop() {
  unsigned long lastTime = millis();
  while (true) {
    unsigned long currentTime = millis();
    float deltaTime = (currentTime - lastTime) / 1000.0;
    lastTime = currentTime;

    if (!digitalRead(BUTTON_PIN)) {
      jump();
    }

    if (dino_jump) {
      dino_vel_y += 0.2;
      dino_pos_y += dino_vel_y;
      if (dino_pos_y >= SCREEN_HEIGHT - 10) {
        dino_pos_y = SCREEN_HEIGHT - 10;
        dino_jump = false;
      }
    }

    obstacle_pos_x -= obstacle_speed;
    if (obstacle_pos_x <= -obstacle_width) {
      obstacle_pos_x = SCREEN_WIDTH;
      score++;
    }

    if (obstacle_pos_x <= 20 && obstacle_pos_x + obstacle_width >= 10 && dino_pos_y >= SCREEN_HEIGHT - 20) {
      gameOver();
    }

    display.clearDisplay();
    drawDinosaur(int(dino_pos_y));
    drawObstacle(obstacle_pos_x, obstacle_width);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 0);
    display.print(F("Score: "));
    display.println(score);
    display.display();
    delay(game_speed * 1000);
  }
}

void loop() {
  resetGame();
  gameLoop();
}