#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// OLED display size
#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);
// Button pins
#define BUTTON_LEFT D10
#define BUTTON_RIGHT D9
#define BUTTON_SHOOT D8
#define BUTTON_START D7
// Player properties
int playerX = 60;
const int playerY = 56;
bool bulletActive = false;
int bulletX, bulletY;
// Enemy properties
const int enemyRows = 3;
const int enemyCols = 5;
bool enemies[enemyRows][enemyCols];
int enemyX = 0;
int enemyDirection = 1; // 1: right, -1: left
int enemyY = 10;
int enemySpeed = 1; // Initial speed of enemies
// Game state
bool gameRunning = false;
int score = 0;
int roundNumber = 1;
void setup() {
// Initialize display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
while (true); // Stop if display fails
}
display.clearDisplay();
display.display();
// Initialize buttons
pinMode(BUTTON_LEFT, INPUT_PULLUP);
pinMode(BUTTON_RIGHT, INPUT_PULLUP);
pinMode(BUTTON_SHOOT, INPUT_PULLUP);
pinMode(BUTTON_START, INPUT_PULLUP);
// Initialize enemies
resetEnemies();
introScreen();
}
void loop() {
if (gameRunning) {
playGame();
} else {
if (digitalRead(BUTTON_START) == LOW) {
gameRunning = true;
resetGame();
}
}
}
void resetGame() {
playerX = 60;
bulletActive = false;
enemyX = 0;
enemyDirection = 1;
enemyY = 10;
enemySpeed = 1 + roundNumber - 1; // Increase speed with each round
resetEnemies();
}
void resetEnemies() {
for (int row = 0; row < enemyRows; row++) {
for (int col = 0; col < enemyCols; col++) {
enemies[row][col] = true;
}
}
}
void introScreen() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 20);
display.println("GALAGA-STYLE GAME");
display.setCursor(15, 40);
display.println("Press START to Play");
display.display();
}
void playGame() {
// Handle player movement
if (digitalRead(BUTTON_LEFT) == LOW && playerX > 0) {
playerX -= 2;
}
if (digitalRead(BUTTON_RIGHT) == LOW && playerX < (SCREEN_WIDTH - 12)) {
playerX += 2;
}
// Handle shooting
if (!bulletActive && digitalRead(BUTTON_SHOOT) == LOW) {
bulletActive = true;
bulletX = playerX + 5;
bulletY = playerY - 2;
}
// Move bullet
if (bulletActive) {
bulletY -= 4;
if (bulletY < 0) {
bulletActive = false;
}
}
// Move enemies
static int enemyMoveCounter = 0;
enemyMoveCounter++;
if (enemyMoveCounter >= enemySpeed) {
enemyX += enemyDirection;
enemyMoveCounter = 0;
if (enemyX <= 0 || enemyX + (enemyCols * 16) >= SCREEN_WIDTH) {
enemyDirection *= -1;
enemyY += 4;
}
}
// Check for collisions
for (int row = 0; row < enemyRows; row++) {
for (int col = 0; col < enemyCols; col++) {
if (enemies[row][col]) {
int ex = enemyX + col * 16;
int ey = enemyY + row * 8;
if (bulletActive && bulletX >= ex && bulletX <= ex + 12 && bulletY >= ey && bulletY <= ey + 8) {
enemies[row][col] = false;
bulletActive = false;
score++; // Increment score
}
if (ey + 8 >= playerY) {
gameOver();
return;
}
}
}
}
// Check if all enemies are defeated
if (areAllEnemiesDefeated()) {
nextRound();
return;
}
// Render the screen
display.clearDisplay();
renderPlayer();
renderBullet();
renderEnemies();
renderScore();
display.display();
}
void renderPlayer() {
display.fillRect(playerX, playerY, 12, 4, SSD1306_WHITE); // Draw spaceship
}
void renderBullet() {
if (bulletActive) {
display.fillRect(bulletX, bulletY, 2, 4, SSD1306_WHITE); // Draw bullet
}
}
void renderEnemies() {
for (int row = 0; row < enemyRows; row++) {
for (int col = 0; col < enemyCols; col++) {
if (enemies[row][col]) {
int ex = enemyX + col * 16;
int ey = enemyY + row * 8;
display.fillRect(ex, ey, 12, 8, SSD1306_WHITE); // Draw enemy
}
}
}
}
void renderScore() {
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Score: ");
display.print(score);
display.setCursor(80, 0);
display.print("Round: ");
display.print(roundNumber);
}
bool areAllEnemiesDefeated() {
for (int row = 0; row < enemyRows; row++) {
for (int col = 0; col < enemyCols; col++) {
if (enemies[row][col]) {
return false;
}
}
}
return true;
}
void nextRound() {
roundNumber++;
resetGame();
}
void gameOver() {
gameRunning = false;
roundNumber = 1; // Reset to first round
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 20);
display.println("GAME OVER");
display.setCursor(15, 40);
display.println("Press START to Retry");
display.display();
}