#include <Wire.h>
#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);
#define BUTTON_START 2
#define BUTTON_EXIT 3
#define PADDLE_PIN A0
const int paddleWidth = 30;
const int paddleHeight = 4;
const int brickWidth = 15;
const int brickHeight = 6;
const int brickRowCount = 3;
const int brickColumnCount = 8;
bool bricks[brickRowCount][brickColumnCount];
int paddleX;
int ballX, ballY, ballDX, ballDY;
const int deadband = 15; // Deadband to reduce sensitivity
int currentLevel = 1;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_START, INPUT_PULLUP);
pinMode(BUTTON_EXIT, INPUT_PULLUP);
// Initialize OLED display
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.display();
delay(2000);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("Choose an option:");
display.println("1. Start game");
display.println("2. Exit");
display.display();
}
void loop() {
if(digitalRead(BUTTON_START) == LOW) {
startGame();
}
if(digitalRead(BUTTON_EXIT) == LOW) {
exitGame();
}
}
void startGame() {
// Initialize game variables
initializeGame();
// Read initial potentiometer value for paddle position
int potValue = analogRead(PADDLE_PIN);
paddleX = map(potValue, 0, 1023, 0, SCREEN_WIDTH - paddleWidth);
while(true) {
// Read potentiometer value for paddle position
potValue = analogRead(PADDLE_PIN);
int newPaddleX = map(potValue, 0, 1023, 0, SCREEN_WIDTH - paddleWidth);
// Check if the potentiometer reading has changed significantly
if(abs(newPaddleX - paddleX) > deadband) {
paddleX = newPaddleX;
}
// Move the ball
moveBall();
// Check for collisions
handleCollisions();
// Update display
updateDisplay();
// Check for game over
if(ballY >= SCREEN_HEIGHT) {
displayGameOver();
break;
}
}
}
void initializeGame() {
// Clear the display
display.clearDisplay();
// Initialize bricks
resetBricksLayout();
// Initialize ball position and velocity
ballX = SCREEN_WIDTH / 2;
ballY = SCREEN_HEIGHT / 2;
ballDX = 1;
ballDY = -1;
}
void moveBall() {
// Move the ball
ballX += ballDX;
ballY += ballDY;
// Bounce off the walls
if(ballX >= SCREEN_WIDTH || ballX <= 0) {
ballDX = -ballDX;
}
if(ballY <= 0) {
ballDY = -ballDY;
}
}
void handleCollisions() {
// Check for paddle collision
if(ballY + 1 >= SCREEN_HEIGHT - paddleHeight && ballX >= paddleX && ballX <= paddleX + paddleWidth) {
ballDY = -ballDY;
}
// Check for brick collision
int brickWidthWithGap = brickWidth + 2;
int brickHeightWithGap = brickHeight + 2;
for(int i = 0; i < brickRowCount; i++) {
for(int j = 0; j < brickColumnCount; j++) {
if(bricks[i][j]) {
int brickX = j * brickWidthWithGap;
int brickY = i * brickHeightWithGap;
if(ballX >= brickX && ballX <= brickX + brickWidth && ballY >= brickY && ballY <= brickY + brickHeight) {
bricks[i][j] = false;
ballDY = -ballDY;
}
}
}
}
}
void updateDisplay() {
// Clear the display
display.clearDisplay();
// Draw bricks
for(int i = 0; i < brickRowCount; i++) {
for(int j = 0; j < brickColumnCount; j++) {
if(bricks[i][j]) {
int brickX = j * (brickWidth + 2);
int brickY = i * (brickHeight + 2);
display.fillRect(brickX, brickY, brickWidth, brickHeight, SSD1306_WHITE);
}
}
}
// Draw paddle
display.fillRect(paddleX, SCREEN_HEIGHT - paddleHeight, paddleWidth, paddleHeight, SSD1306_WHITE);
// Draw ball
display.fillCircle(ballX, ballY, 2, SSD1306_WHITE);
// Display everything
display.display();
}
void displayGameOver() {
// Clear the display
display.clearDisplay();
// Display game over message
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 20);
display.println("Game Over");
// Display everything
display.display();
}
void exitGame() {
// Add any necessary exit routines here
// Exit the program
while(true); // Infinite loop, effectively stops the program
}
void nextLevel() {
// Increase the current level
currentLevel++;
// Increase ball speed
// For example, increase the speed by 10%:
ballDX *= 1.4;
ballDY *= 1.4;
// Reset bricks layout for the next level
resetBricksLayout();
// Display next level message
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 20);
display.print("Level ");
display.println(currentLevel);
display.display();
delay(2000); // Wait for 2 seconds before starting the next level
}
void resetBricksLayout() {
// Clear the bricks array
for(int i = 0; i < brickRowCount; i++) {
for(int j = 0; j < brickColumnCount; j++) {
bricks[i][j] = true;
}
}
}