// Include necessary libraries
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// OLED display dimensions
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// OLED reset pin
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Define game variables
#define PLAYER_WIDTH 10
#define PLAYER_HEIGHT 15
#define OBSTACLE_WIDTH 10
#define OBSTACLE_HEIGHT 15
int playerX = 10; // Player's X position (fixed)
int playerY = 25; // Player's Y position
int playerSpeed = 2;
int obstacleX = SCREEN_WIDTH; // Obstacle's initial X position
int obstacleY = random(5, SCREEN_HEIGHT - OBSTACLE_HEIGHT - 5);
int obstacleSpeed = 3;
int score = 0;
bool gameOver = false;
// Buttons for input
#define BUTTON_UP D10
#define BUTTON_DOWN D9
void setup() {
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
// Initialize OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
for (;;); // Stop if OLED initialization fails
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Top-Down Racer");
display.display();
delay(2000);
}
void loop() {
if (gameOver) {
displayGameOver();
return;
}
updatePlayerPosition();
updateObstaclePosition();
checkCollision();
updateScore();
renderScene();
delay(30); // Control game speed
}
void updatePlayerPosition() {
if (digitalRead(BUTTON_UP) == LOW && playerY > 0) {
playerY -= playerSpeed;
}
if (digitalRead(BUTTON_DOWN) == LOW && playerY < SCREEN_HEIGHT - PLAYER_HEIGHT) {
playerY += playerSpeed;
}
}
void updateObstaclePosition() {
obstacleX -= obstacleSpeed;
if (obstacleX < 0) {
obstacleX = SCREEN_WIDTH;
obstacleY = random(5, SCREEN_HEIGHT - OBSTACLE_HEIGHT - 5);
score++;
// Increase speed slightly after each obstacle pass
if (score % 5 == 0) {
obstacleSpeed++;
}
}
}
void checkCollision() {
if (playerX < obstacleX + OBSTACLE_WIDTH &&
playerX + PLAYER_WIDTH > obstacleX &&
playerY < obstacleY + OBSTACLE_HEIGHT &&
playerY + PLAYER_HEIGHT > obstacleY) {
gameOver = true;
}
}
void updateScore() {
display.setCursor(0, 0);
display.setTextSize(1);
display.clearDisplay();
display.println("Score: ");
display.setCursor(40, 0);
display.println(score);
}
void renderScene() {
display.clearDisplay();
// Draw the player car
display.fillRect(playerX, playerY, PLAYER_WIDTH, PLAYER_HEIGHT, SSD1306_WHITE);
// Draw the obstacle car
display.fillRect(obstacleX, obstacleY, OBSTACLE_WIDTH, OBSTACLE_HEIGHT, SSD1306_WHITE);
// Draw score
display.setCursor(0, 0);
display.print("Score: ");
display.print(score);
display.display();
}
void displayGameOver() {
display.clearDisplay();
display.setTextSize(2);
display.setCursor(10, 20);
display.println("Game Over");
display.setTextSize(1);
display.setCursor(10, 50);
display.println("Press reset");
display.display();
}