#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define GRAVITY 1
#define JUMP_STRENGTH 10
// Initialize the display
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Button pins
const int BUTTON_LEFT_PIN = 15;
const int BUTTON_RIGHT_PIN = 4;
const int BUTTON_JUMP_PIN = 27;
// Mario properties
const int MARIO_WIDTH = 8;
const int MARIO_HEIGHT = 8;
int marioX = 10;
int marioY = SCREEN_HEIGHT - MARIO_HEIGHT - 10;
int marioSpeedX = 2;
int marioSpeedY = 0;
bool isJumping = false;
// Platform properties
const int PLATFORM_WIDTH = 50;
const int PLATFORM_HEIGHT = 10;
int platforms[3][2] = {
{20, SCREEN_HEIGHT - 30},
{60, SCREEN_HEIGHT - 50},
{100, SCREEN_HEIGHT - 20}
};
// Coin properties
const int COIN_SIZE = 6; // Size of the coin
const int COIN_COUNT = 5;
int coins[COIN_COUNT][2] = {
{30, SCREEN_HEIGHT - 40},
{70, SCREEN_HEIGHT - 40},
{110, SCREEN_HEIGHT - 40},
{40, SCREEN_HEIGHT - 60},
{80, SCREEN_HEIGHT - 60}
};
// Obstacle properties
const int OBSTACLE_SIZE = 10; // Size of the obstacle
const int OBSTACLE_COUNT = 2;
int obstacles[OBSTACLE_COUNT][2] = {
{50, SCREEN_HEIGHT - 20},
{90, SCREEN_HEIGHT - 30}
};
// Score
int score = 0;
void setup() {
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
pinMode(BUTTON_LEFT_PIN, INPUT_PULLUP);
pinMode(BUTTON_RIGHT_PIN, INPUT_PULLUP);
pinMode(BUTTON_JUMP_PIN, INPUT_PULLUP);
}
void loop() {
int readingLeft = digitalRead(BUTTON_LEFT_PIN);
int readingRight = digitalRead(BUTTON_RIGHT_PIN);
int readingJump = digitalRead(BUTTON_JUMP_PIN);
// Handle Mario movement
if (readingLeft == LOW) {
marioX -= marioSpeedX;
delay(50); // Simple debounce delay
}
if (readingRight == LOW) {
marioX += marioSpeedX;
delay(50); // Simple debounce delay
}
if (readingJump == LOW && !isJumping) {
marioSpeedY = -JUMP_STRENGTH;
isJumping = true;
delay(50); // Simple debounce delay
}
// Apply gravity
marioSpeedY += GRAVITY;
marioY += marioSpeedY;
// Collision with platforms
bool onPlatform = false;
for (int i = 0; i < 3; i++) {
if (marioY + MARIO_HEIGHT >= platforms[i][1] && marioX + MARIO_WIDTH > platforms[i][0] && marioX < platforms[i][0] + PLATFORM_WIDTH) {
marioY = platforms[i][1] - MARIO_HEIGHT;
marioSpeedY = 0;
isJumping = false;
onPlatform = true;
break;
}
}
if (!onPlatform) {
marioSpeedY += GRAVITY; // Apply gravity if not on a platform
}
// Collision with obstacles
for (int i = 0; i < OBSTACLE_COUNT; i++) {
if (marioY + MARIO_HEIGHT > obstacles[i][1] && marioX + MARIO_WIDTH > obstacles[i][0] && marioX < obstacles[i][0] + OBSTACLE_SIZE) {
// Reset Mario's position if collides with obstacle
marioX = 10;
marioY = SCREEN_HEIGHT - MARIO_HEIGHT - 10;
marioSpeedY = 0;
score = 0; // Reset score on collision
break; // Break the loop to avoid multiple resets
}
}
// Collision with screen edges
if (marioX < 0) marioX = 0;
if (marioX > SCREEN_WIDTH - MARIO_WIDTH) marioX = SCREEN_WIDTH - MARIO_WIDTH;
if (marioY > SCREEN_HEIGHT - MARIO_HEIGHT) marioY = SCREEN_HEIGHT - MARIO_HEIGHT;
// Check if Mario collects coins
for (int i = 0; i < COIN_COUNT; i++) {
if (coins[i][0] >= 0 && marioY + MARIO_HEIGHT > coins[i][1] && marioX + MARIO_WIDTH > coins[i][0] && marioX < coins[i][0] + COIN_SIZE) {
// Coin collected
coins[i][0] = -10; // Move coin off screen
score += 10; // Increase score
}
}
// Clear the display
display.clearDisplay();
// Draw platforms
for (int i = 0; i < 3; i++) {
display.fillRect(platforms[i][0], platforms[i][1], PLATFORM_WIDTH, PLATFORM_HEIGHT, SSD1306_WHITE);
}
// Draw obstacles
for (int i = 0; i < OBSTACLE_COUNT; i++) {
display.fillRect(obstacles[i][0], obstacles[i][1], OBSTACLE_SIZE, OBSTACLE_SIZE, SSD1306_WHITE);
}
// Draw coins
for (int i = 0; i < COIN_COUNT; i++) {
if (coins[i][0] >= 0) { // Only draw coins that are on screen
display.fillRect(coins[i][0], coins[i][1], COIN_SIZE, COIN_SIZE, SSD1306_WHITE); // Use white for coins
}
}
// Draw Mario
display.fillRect(marioX, marioY, MARIO_WIDTH, MARIO_HEIGHT, SSD1306_WHITE); // Use white for Mario
// Display the score
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Score: ");
display.println(score);
// Update the display
display.display();
// Delay to control game speed
delay(20);
}