#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// OLED display configuration
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Button pins
const int buttonLeft = D10;
const int buttonRight = D9;
const int buttonSpeedUp = D8;
const int buttonSlowDown = D7;
// Car bitmap (16x16 pixels)
const unsigned char PROGMEM carBitmap[] = {
0x18, 0x18, 0x3C, 0x3C, 0x7E, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x7E, 0x3C, 0x3C, 0x18, 0x18
};
// Global variables
int carX = 56; // Initial X position of the car
int carY = 48; // Fixed Y position for the car
int speed = 1; // Speed of the obstacles
int score = 0;
// Obstacle properties
const int numObstacles = 3;
int obstacleX[numObstacles];
int obstacleY[numObstacles];
// Initialize the game
void setup() {
pinMode(buttonLeft, INPUT_PULLUP);
pinMode(buttonRight, INPUT_PULLUP);
pinMode(buttonSpeedUp, INPUT_PULLUP);
pinMode(buttonSlowDown, INPUT_PULLUP);
// Initialize the OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
for (;;);
}
display.clearDisplay();
// Randomize obstacle positions
for (int i = 0; i < numObstacles; i++) {
obstacleX[i] = random(0, SCREEN_WIDTH - 8);
obstacleY[i] = random(-20, -8); // Start off-screen
}
}
void loop() {
// Handle car movement
if (digitalRead(buttonLeft) == LOW && carX > 0) {
carX -= 2;
}
if (digitalRead(buttonRight) == LOW && carX < SCREEN_WIDTH - 16) {
carX += 2;
}
// Handle speed adjustments
if (digitalRead(buttonSpeedUp) == LOW && speed < 5) {
speed++;
}
if (digitalRead(buttonSlowDown) == LOW && speed > 1) {
speed--;
}
// Clear the display
display.clearDisplay();
// Draw the car
display.drawBitmap(carX, carY, carBitmap, 16, 16, SSD1306_WHITE);
// Move and draw obstacles
for (int i = 0; i < numObstacles; i++) {
obstacleY[i] += speed;
// If the obstacle goes off-screen, reset it
if (obstacleY[i] > SCREEN_HEIGHT) {
obstacleY[i] = random(-20, -8);
obstacleX[i] = random(0, SCREEN_WIDTH - 8);
score++; // Increase score for avoiding an obstacle
}
// Draw the obstacle
display.fillRect(obstacleX[i], obstacleY[i], 8, 8, SSD1306_WHITE);
// Check for collision
if (carY < obstacleY[i] + 8 && carY + 16 > obstacleY[i] && carX < obstacleX[i] + 8 && carX + 16 > obstacleX[i]) {
gameOver();
}
}
// Display the score
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Score: ");
display.print(score);
// Update the display
display.display();
// Delay to control frame rate
delay(30);
}
// Game Over function
void gameOver() {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20, 20);
display.println("GAME OVER");
display.setTextSize(1);
display.setCursor(20, 50);
display.print("Final Score: ");
display.print(score);
display.display();
// Pause the game
while (true);
}
Loading
xiao-esp32-c3
xiao-esp32-c3