#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ================= DISPLAY =================
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(
SCREEN_WIDTH,
SCREEN_HEIGHT,
&Wire,
OLED_RESET
);
// ================= INPUT =================
#define BUTTON_PIN 3
bool lastButtonState = HIGH;
// ================= PLAYER =================
int playerX = 20;
float playerY = 48;
float velocityY = 0;
bool onGround = true;
// ================= PHYSICS =================
const float GRAVITY = 0.6;
const float JUMP_FORCE = -7;
// ================= OBSTACLE =================
int obstacleX = SCREEN_WIDTH;
int obstacleW = 8;
// ================= GAME =================
bool gameOver = false;
unsigned long lastFrame = 0;
unsigned long speedTimer = 0;
int gameSpeed = 3;
// ================= FUNCTIONS =================
void resetGame() {
playerY = 48;
velocityY = 0;
onGround = true;
obstacleX = SCREEN_WIDTH;
gameSpeed = 3;
gameOver = false;
speedTimer = millis();
}
void updateButton() {
bool state = digitalRead(BUTTON_PIN);
if (lastButtonState == HIGH && state == LOW) {
if (gameOver) {
resetGame();
} else if (onGround) {
velocityY = JUMP_FORCE;
onGround = false;
}
}
lastButtonState = state;
}
void updatePlayer() {
velocityY += GRAVITY;
playerY += velocityY;
if (playerY >= 48) {
playerY = 48;
velocityY = 0;
onGround = true;
}
}
void updateObstacle() {
obstacleX -= gameSpeed;
if (obstacleX < -obstacleW) {
obstacleX = SCREEN_WIDTH + random(20, 60);
}
}
void checkCollision() {
if (obstacleX < playerX + 6 &&
obstacleX + obstacleW > playerX &&
playerY + 6 > 48) {
gameOver = true;
}
}
void increaseSpeed() {
if (millis() - speedTimer > 3000) {
gameSpeed++;
speedTimer = millis();
}
}
void drawGame() {
display.clearDisplay();
// chão
display.drawLine(0, 54, SCREEN_WIDTH, 54, SSD1306_WHITE);
// jogador
display.fillRect(playerX, (int)playerY, 6, 6, SSD1306_WHITE);
// obstáculo
display.fillRect(obstacleX, 48, obstacleW, 6, SSD1306_WHITE);
if (gameOver) {
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(32, 20);
display.print("GAME OVER");
display.setCursor(18, 36);
display.print("PRESS BUTTON");
}
display.display();
}
// ================= SETUP / LOOP =================
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
while (true);
}
randomSeed(analogRead(0));
resetGame();
}
void loop() {
updateButton();
if (!gameOver && millis() - lastFrame > 33) { // ~30 FPS
updatePlayer();
updateObstacle();
checkCollision();
increaseSpeed();
lastFrame = millis();
}
drawGame();
}