221 lines
7.5 KiB
C++
221 lines
7.5 KiB
C++
#include <Wire.h>
|
|
#include <Adafruit_SSD1306.h>
|
|
|
|
// OLED display size
|
|
#define SCREEN_WIDTH 128
|
|
#define SCREEN_HEIGHT 64
|
|
|
|
// Create display object
|
|
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
|
|
|
|
// Pin assignments
|
|
#define FEED_BUTTON_PIN 2
|
|
#define POOP_BUTTON_PIN 3
|
|
|
|
// Game constants
|
|
#define MAX_FOOD 100
|
|
#define MAX_POOP 100
|
|
#define FOOD_BAR_Y 0
|
|
#define POOP_BAR_Y 8
|
|
#define BAR_HEIGHT 7
|
|
#define BAR_WIDTH 120
|
|
#define BAR_X 4
|
|
#define BAR_LABEL_X 0
|
|
#define BAR_LABEL_WIDTH 4
|
|
#define YELLOW_BAR_HEIGHT 16
|
|
|
|
// Game state
|
|
int food = MAX_FOOD / 2;
|
|
int poop = MAX_POOP / 2;
|
|
bool gameOver = false;
|
|
unsigned long lastUpdate = 0;
|
|
const unsigned long updateInterval = 200; // ms
|
|
|
|
void drawBars() {
|
|
// Draw yellow background for status area
|
|
display.fillRect(0, 0, SCREEN_WIDTH, YELLOW_BAR_HEIGHT, SSD1306_WHITE);
|
|
// Draw Food bar label
|
|
display.setTextColor(SSD1306_BLACK);
|
|
display.setTextSize(1);
|
|
display.setCursor(BAR_X, FOOD_BAR_Y);
|
|
display.print("FOOD");
|
|
// Draw Poop bar label
|
|
display.setCursor(BAR_X, POOP_BAR_Y);
|
|
display.print("POOP");
|
|
// Draw Food bar
|
|
int foodBarLen = (food * (BAR_WIDTH - 30)) / MAX_FOOD; // leave space for label
|
|
display.fillRect(BAR_X + 34, FOOD_BAR_Y, foodBarLen, BAR_HEIGHT, SSD1306_BLACK);
|
|
display.drawRect(BAR_X + 34, FOOD_BAR_Y, BAR_WIDTH - 30, BAR_HEIGHT, SSD1306_BLACK);
|
|
// Draw Poop bar
|
|
int poopBarLen = (poop * (BAR_WIDTH - 30)) / MAX_POOP;
|
|
display.fillRect(BAR_X + 34, POOP_BAR_Y, poopBarLen, BAR_HEIGHT, SSD1306_BLACK);
|
|
display.drawRect(BAR_X + 34, POOP_BAR_Y, BAR_WIDTH - 30, BAR_HEIGHT, SSD1306_BLACK);
|
|
display.setTextSize(1);
|
|
}
|
|
|
|
void drawStickFigure(int frame) {
|
|
// Draw a simple stick figure in the blue area (below yellow bar)
|
|
int baseY = 24;
|
|
int centerX = SCREEN_WIDTH / 2;
|
|
// Head
|
|
display.drawCircle(centerX, baseY, 6, SSD1306_WHITE);
|
|
// Body
|
|
display.drawLine(centerX, baseY + 6, centerX, baseY + 24, SSD1306_WHITE);
|
|
// Arms (simple animation)
|
|
if (frame % 2 == 0) {
|
|
display.drawLine(centerX, baseY + 10, centerX - 10, baseY + 18, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 10, centerX + 10, baseY + 18, SSD1306_WHITE);
|
|
} else {
|
|
display.drawLine(centerX, baseY + 10, centerX - 14, baseY + 14, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 10, centerX + 14, baseY + 14, SSD1306_WHITE);
|
|
}
|
|
// Legs
|
|
display.drawLine(centerX, baseY + 24, centerX - 10, baseY + 40, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 24, centerX + 10, baseY + 40, SSD1306_WHITE);
|
|
}
|
|
|
|
void drawStinkyPoop() {
|
|
// Draw a simple stinky poop in the blue area
|
|
int baseY = 32;
|
|
int centerX = SCREEN_WIDTH / 2;
|
|
// Poop base
|
|
display.fillCircle(centerX, baseY + 16, 8, SSD1306_WHITE);
|
|
display.fillCircle(centerX, baseY + 8, 6, SSD1306_WHITE);
|
|
display.fillCircle(centerX, baseY, 4, SSD1306_WHITE);
|
|
// Stink lines
|
|
display.drawLine(centerX - 6, baseY - 4, centerX - 6, baseY - 12, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY - 6, centerX, baseY - 16, SSD1306_WHITE);
|
|
display.drawLine(centerX + 6, baseY - 4, centerX + 6, baseY - 12, SSD1306_WHITE);
|
|
}
|
|
|
|
void drawGameOver(const char* message) {
|
|
display.clearDisplay();
|
|
// Draw yellow status bar with game over message
|
|
display.fillRect(0, 0, SCREEN_WIDTH, YELLOW_BAR_HEIGHT, SSD1306_WHITE);
|
|
display.setTextColor(SSD1306_BLACK);
|
|
display.setTextSize(1);
|
|
display.setCursor(2, 0);
|
|
display.print("GAME OVER!");
|
|
display.setCursor(2, 8);
|
|
display.print(message);
|
|
// Draw relevant icon in blue area
|
|
if (strcmp(message, "Poop explosion!") == 0) {
|
|
drawStinkyPoop();
|
|
} else if (strcmp(message, "Starved!") == 0) {
|
|
// Draw a sad stick figure
|
|
int baseY = 32;
|
|
int centerX = SCREEN_WIDTH / 2;
|
|
display.drawCircle(centerX, baseY, 6, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 6, centerX, baseY + 24, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 10, centerX - 10, baseY + 18, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 10, centerX + 10, baseY + 18, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 24, centerX - 10, baseY + 40, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 24, centerX + 10, baseY + 40, SSD1306_WHITE);
|
|
// Sad mouth (simple frown)
|
|
display.drawLine(centerX - 3, baseY + 6, centerX + 3, baseY + 6, SSD1306_WHITE);
|
|
} else if (strcmp(message, "Overate! Exploded!") == 0) {
|
|
// Draw a stick figure with a big belly
|
|
int baseY = 32;
|
|
int centerX = SCREEN_WIDTH / 2;
|
|
display.drawCircle(centerX, baseY, 6, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 6, centerX, baseY + 24, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 10, centerX - 10, baseY + 18, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 10, centerX + 10, baseY + 18, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 24, centerX - 10, baseY + 40, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 24, centerX + 10, baseY + 40, SSD1306_WHITE);
|
|
// Big belly
|
|
display.drawCircle(centerX, baseY + 18, 8, SSD1306_WHITE);
|
|
} else if (strcmp(message, "Constipation!") == 0) {
|
|
// Draw a stick figure with a pained face
|
|
int baseY = 32;
|
|
int centerX = SCREEN_WIDTH / 2;
|
|
display.drawCircle(centerX, baseY, 6, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 6, centerX, baseY + 24, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 10, centerX - 10, baseY + 18, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 10, centerX + 10, baseY + 18, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 24, centerX - 10, baseY + 40, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 24, centerX + 10, baseY + 40, SSD1306_WHITE);
|
|
// Pained mouth (zigzag)
|
|
display.drawLine(centerX - 2, baseY + 5, centerX, baseY + 7, SSD1306_WHITE);
|
|
display.drawLine(centerX, baseY + 7, centerX + 2, baseY + 5, SSD1306_WHITE);
|
|
}
|
|
display.display();
|
|
}
|
|
|
|
void setup() {
|
|
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
|
|
while (true); // Don't proceed, loop forever
|
|
}
|
|
pinMode(FEED_BUTTON_PIN, INPUT_PULLUP);
|
|
pinMode(POOP_BUTTON_PIN, INPUT_PULLUP);
|
|
display.clearDisplay();
|
|
drawBars();
|
|
display.display();
|
|
lastUpdate = millis();
|
|
}
|
|
|
|
void loop() {
|
|
if (gameOver) return;
|
|
// Handle buttons (active LOW)
|
|
bool feedPressed = digitalRead(FEED_BUTTON_PIN) == LOW;
|
|
bool poopPressed = digitalRead(POOP_BUTTON_PIN) == LOW;
|
|
static bool lastFeedPressed = false;
|
|
static bool lastPoopPressed = false;
|
|
|
|
// Feed button: increase food, increase poop a bit
|
|
if (feedPressed && !lastFeedPressed) {
|
|
food += 15;
|
|
if (food > MAX_FOOD) food = MAX_FOOD;
|
|
poop += 5;
|
|
if (poop > MAX_POOP) poop = MAX_POOP;
|
|
}
|
|
// Poop button: decrease poop
|
|
if (poopPressed && !lastPoopPressed) {
|
|
poop -= 20;
|
|
if (poop < 0) poop = 0;
|
|
}
|
|
lastFeedPressed = feedPressed;
|
|
lastPoopPressed = poopPressed;
|
|
|
|
// Food decreases, poop increases over time
|
|
if (millis() - lastUpdate > updateInterval) {
|
|
lastUpdate = millis();
|
|
food--;
|
|
if (food < 0) food = 0;
|
|
if (food > 0) poop++;
|
|
if (poop > MAX_POOP) poop = MAX_POOP;
|
|
}
|
|
|
|
// Check game over conditions
|
|
if (food == 0) {
|
|
gameOver = true;
|
|
drawGameOver("Starved!");
|
|
return;
|
|
}
|
|
if (food == MAX_FOOD) {
|
|
gameOver = true;
|
|
drawGameOver("Overate! Exploded!");
|
|
return;
|
|
}
|
|
if (poop == MAX_POOP) {
|
|
gameOver = true;
|
|
drawGameOver("Poop explosion!");
|
|
return;
|
|
}
|
|
if (poop == 0) {
|
|
gameOver = true;
|
|
drawGameOver("Constipation!");
|
|
return;
|
|
}
|
|
|
|
// Redraw bars
|
|
display.clearDisplay();
|
|
drawBars();
|
|
// Animate stick figure in blue area
|
|
static int frame = 0;
|
|
drawStickFigure(frame);
|
|
frame = (frame + 1) % 2;
|
|
display.display();
|
|
delay(100);
|
|
}
|