// https://forum.arduino.cc/t/why-my-program-doesnt-work/1372883/
#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_PIN 2
byte BUZZER = 0; // remove buzzer from runtime
// byte BUZZER = 1; // add buzzer to code
#define BUZZER_PIN 3
#define DINO_X 10
#define DINO_HEIGHT 10
#define GROUND_Y 54
#define MAX_OBSTACLES 3
#define MAX_POWERUPS 2
#define MAX_CLOUDS 5
// Dino sprite (10x10)
const uint8_t dinoSprite[] PROGMEM = {
0b00011000,
0b00111100,
0b01111110,
0b11111111,
0b11011011,
0b11111111,
0b01111110,
0b00100100,
0b00100100,
0b00100100
};
// Bird sprites (5x5)
const uint8_t birdWingUp[] PROGMEM = {
0b00100,
0b01110,
0b11111,
0b01110,
0b00100
};
const uint8_t birdWingDown[] PROGMEM = {
0b00100,
0b00100,
0b11111,
0b01110,
0b00100
};
// Zmienne gry
int dinoY = GROUND_Y - DINO_HEIGHT;
bool isJumping = false;
int jumpVelocity = 0;
int gravity = 1;
int obstaclesX[MAX_OBSTACLES];
int obstacleY[MAX_OBSTACLES];
int obstacleType[MAX_OBSTACLES];
int powerUpX[MAX_POWERUPS];
int powerUpY[MAX_POWERUPS];
int powerUpType[MAX_POWERUPS];
bool powerUpActive[MAX_POWERUPS];
bool shieldActive = false;
bool wingState = false;
unsigned long lastWingFlap = 0;
int difficulty = 1;
int obstacleSpeed = 2;
int points = 0;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
if (BUZZER) pinMode(BUZZER_PIN, OUTPUT);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
// EEPROM.get(0, difficulty);
if (difficulty < 0 || difficulty > 2) difficulty = 1;
showMenu();
initGame();
}
void showMenu() {
int selection = difficulty;
bool confirm = false;
unsigned long pressTime = 0;
// while (!confirm) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(20, 10);
display.print("Wybierz poziom:");
display.setCursor(20, 25);
display.print(selection == 0 ? "> Latwy" : " Latwy");
display.setCursor(20, 35);
display.print(selection == 1 ? "> Normalny" : " Normalny");
display.setCursor(20, 45);
display.print(selection == 2 ? "> Trudny" : " Trudny");
display.display();
if (digitalRead(BUTTON_PIN) == LOW) {
if (pressTime == 0) pressTime = millis();
if (millis() - pressTime > 800) {
confirm = true;
// EEPROM.put(0, selection);
difficulty = selection;
}
} else if (pressTime != 0) {
pressTime = 0;
selection = (selection + 1) % 3;
delay(200);
}
// }
obstacleSpeed = 2 + selection;
display.clearDisplay();
}
void initGame() {
for (int i = 0; i < MAX_OBSTACLES; i++) {
obstaclesX[i] = 128 + i * 40;
obstacleY[i] = GROUND_Y - 8;
obstacleType[i] = random(0, 2);
}
for (int i = 0; i < MAX_POWERUPS; i++) {
powerUpX[i] = 128 + i * 60;
powerUpY[i] = random(20, GROUND_Y);
powerUpType[i] = random(0, 3);
powerUpActive[i] = true;
}
}
void loop() {
unsigned long now = millis();
if (now - lastWingFlap > 200) {
wingState = !wingState;
lastWingFlap = now;
}
if (digitalRead(BUTTON_PIN) == LOW && !isJumping) {
isJumping = true;
jumpVelocity = -8;
if (BUZZER) tone(BUZZER_PIN, 800, 100);
}
// Skakanie
if (isJumping) {
dinoY += jumpVelocity;
jumpVelocity += gravity;
if (dinoY >= GROUND_Y - DINO_HEIGHT) {
dinoY = GROUND_Y - DINO_HEIGHT;
isJumping = false;
}
}
// Przeszkody
for (int i = 0; i < MAX_OBSTACLES; i++) {
obstaclesX[i] -= obstacleSpeed;
if (obstaclesX[i] < -10) {
obstaclesX[i] = 128 + random(30, 80);
obstacleType[i] = random(0, 2);
}
// Kolizje
if (obstaclesX[i] < DINO_X + 10 && obstaclesX[i] + 8 > DINO_X &&
dinoY + DINO_HEIGHT > obstacleY[i]) {
if (shieldActive) {
shieldActive = false;
} else {
gameOver();
}
}
}
// Power-upy
for (int i = 0; i < MAX_POWERUPS; i++) {
if (powerUpActive[i]) {
powerUpX[i] -= obstacleSpeed;
if (powerUpX[i] < -5) {
powerUpX[i] = 128 + random(50, 100);
powerUpY[i] = random(20, GROUND_Y - 5);
powerUpType[i] = random(0, 3);
powerUpActive[i] = true;
}
// Zbieranie
if (powerUpX[i] < DINO_X + 10 && powerUpX[i] + 5 > DINO_X &&
dinoY + 10 > powerUpY[i] && dinoY < powerUpY[i] + 5) {
switch (powerUpType[i]) {
case 0: shieldActive = true; break;
case 1: points += 500; break;
case 2: obstacleSpeed = max(1, obstacleSpeed - 1); break;
}
powerUpActive[i] = false;
if (BUZZER) tone(BUZZER_PIN, 1000, 150);
}
}
}
// Rysowanie
display.clearDisplay();
display.drawLine(0, GROUND_Y, SCREEN_WIDTH, GROUND_Y, SSD1306_WHITE);
// Dino
display.drawBitmap(DINO_X, dinoY, dinoSprite, 8, 10, SSD1306_WHITE);
// Przeszkody
for (int i = 0; i < MAX_OBSTACLES; i++) {
if (obstacleType[i] == 0) {
display.fillRect(obstaclesX[i], obstacleY[i], 8, 8, SSD1306_WHITE); // kaktus
} else {
display.drawBitmap(obstaclesX[i], obstacleY[i],
wingState ? birdWingUp : birdWingDown, 5, 5, SSD1306_WHITE);
}
}
// Power-upy
for (int i = 0; i < MAX_POWERUPS; i++) {
if (powerUpActive[i]) {
display.fillCircle(powerUpX[i], powerUpY[i], 2, SSD1306_WHITE);
}
}
// Punkty
points++;
display.setCursor(90, 0);
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.print("PTS:");
display.print(points);
// Ikonka tarczy
if (shieldActive) {
display.drawCircle(DINO_X + 4, dinoY + 5, 8, SSD1306_WHITE);
}
display.display();
delay(30);
}
void gameOver() {
display.clearDisplay();
display.setTextSize(2);
display.setCursor(10, 20);
display.print("Game Over");
display.setTextSize(1);
display.setCursor(20, 45);
display.print("Punkty: ");
display.print(points);
display.display();
if (BUZZER) {
tone(BUZZER_PIN, 300, 500);
delay(500);
noTone(BUZZER_PIN);
}
while (digitalRead(BUTTON_PIN) == HIGH); // Czekaj na przycisk
while (digitalRead(BUTTON_PIN) == LOW); // Zwolnienie
// Restart
points = 0;
shieldActive = false;
initGame();
}