#include <LiquidCrystal_I2C.h> // Knižnica na ovládanie LCD displeja s I2C rozhraním
LiquidCrystal_I2C lcd(0x27, 20, 4); // Inicializácia LCD displeja s adresou 0x27, 20 stĺpcami a 4 riadkami
int coinX, coinY; // Súradnice mince na obrazovke
int panacikX = 9, panacikY = 1; // Počiatočné súradnice hráča (panáčika)
int score = 0; // Počiatočné skóre hráča
bool isPaused = false, gameRunning = false; // Premenné na sledovanie stavu hry (pozastavená/bežiaca)
const int debounceTime = 50; // Čas odrátania (debounce) na zamedzenie falošných stlačení tlačidiel
const int btnUp = 2, btnDown = 4, btnLeft = 7, btnRight = 8, btnPause = 12; // Piny tlačidiel
// Definícia vlastných znakov pre LCD displej
byte panacik[8] = { B00100, B01010, B00100, B01110, B10101, B00100, B01010, B10001 }; // Ikona panáčika
byte animacia[8] = { B00100, B01010, B10101, B01110, B00100, B00100, B01010, B10001 }; // Alternatívna animácia panáčika
byte minca[8] = { B00000, B00000, B01110, B10001, B10001, B01110, B00000, B00000 }; // Ikona mince
byte bomba[8] = { B00100, B01110, B11111, B11011, B11111, B01110, B00100, B00000 }; // Ikona bomby
byte vybuch[8] = { B01010, B10101, B01010, B11111, B01010, B10101, B01010, B00000 }; // Ikona výbuchu
// Štruktúra reprezentujúca bombu v hre
struct Bomb {
int x, y; // Súradnice bomby
bool active; // Stav bomby (či je aktívna)
bool movingRight; // Smer pohybu bomby (true = doprava, false = doľava)
};
Bomb bombs[2]; // Pole dvoch bômb v hre
int bombCount = 1; // Počiatočný počet aktívnych bômb
unsigned long lastBombMove = 0; // Čas posledného pohybu bomby
unsigned long bombDelay = 300; // Časová medzera medzi pohybmi bômb v milisekundách
// Funkcia na kontrolu stlačenia tlačidla so zabránením falošným stlačeniam
bool isButtonPressed(int pin) {
if (!digitalRead(pin)) { // Ak je tlačidlo stlačené (LOW)
delay(debounceTime); // Počkáme debounce čas
return !digitalRead(pin); // Skontrolujeme, či je stále stlačené (aby sme predišli šumu)
}
return false; // Ak tlačidlo nebolo stlačené, vrátime false
}
// Funkcia na inicializáciu systému
void setup() {
pinMode(btnUp, INPUT_PULLUP); // Nastavenie tlačidla "hore" ako vstup s interným pull-up rezistorom
pinMode(btnDown, INPUT_PULLUP); // Nastavenie tlačidla "dole"
pinMode(btnLeft, INPUT_PULLUP); // Nastavenie tlačidla "doľava"
pinMode(btnRight, INPUT_PULLUP); // Nastavenie tlačidla "doprava"
pinMode(btnPause, INPUT_PULLUP); // Nastavenie tlačidla "pauza"
lcd.init(); // Inicializácia LCD displeja
lcd.backlight(); // Zapnutie podsvietenia displeja
// Vytvorenie vlastných znakov pre LCD displej
lcd.createChar(1, panacik); // Uloženie panáčika ako znak 1
lcd.createChar(2, minca); // Uloženie mince ako znak 2
lcd.createChar(3, animacia); // Uloženie animácie panáčika ako znak 3
lcd.createChar(4, bomba); // Uloženie bomby ako znak 4
lcd.createChar(5, vybuch); // Uloženie výbuchu ako znak 5
showStartScreen(); // Zobrazenie úvodnej obrazovky
startCoinGame(); // Spustenie hry so zbieraním mincí
}
void loop() {} // Hlavná slučka programu, ktorá sa opakuje donekonečna (zatiaľ prázdna)
// Funkcia zobrazujúca úvodnú obrazovku pred začiatkom hry
void showStartScreen() {
lcd.clear(); // Vyčistenie displeja
lcd.setCursor(2, 1); // Nastavenie kurzora na pozíciu (2,1)
lcd.print("Stlacte lubovolne"); // Zobrazenie textu na displeji
lcd.setCursor(6, 2); // Nastavenie kurzora na pozíciu (6,2)
lcd.print("tlacidlo"); // Zobrazenie textu na displeji
lcd.setCursor(2, 3); // Nastavenie kurzora na pozíciu (2,3)
lcd.print("na spustenie hry"); // Zobrazenie textu na displeji
// Čakanie na stlačenie ktoréhokoľvek tlačidla na spustenie hry
while (!isButtonPressed(btnUp) && !isButtonPressed(btnDown) && !isButtonPressed(btnLeft) && !isButtonPressed(btnRight) && !isButtonPressed(btnPause));
delay(200); // Krátka pauza na zabránenie opakovanému registru stlačenia
}
// Funkcia na spustenie hry so zbieraním mincí a pohybom bômb
void startCoinGame() {
lcd.clear(); // Vyčistenie displeja
score = 0; // Nulovanie skóre
panacikX = 9; // Nastavenie počiatočnej X súradnice hráča
panacikY = 1; // Nastavenie počiatočnej Y súradnice hráča
gameRunning = true; // Spustenie hry
bombCount = 1; // Počiatočný počet bômb
lcd.setCursor(0, 0); // Nastavenie kurzora na začiatok prvého riadka
lcd.print("Skore: 0"); // Zobrazenie skóre na displeji
lcd.setCursor(panacikX, panacikY); // Nastavenie kurzora na pozíciu hráča
lcd.write(byte(1)); // Zobrazenie hráča (panáčika)
generateCoin(); // Generovanie mince na náhodnej pozícii
generateBomb(0); // Generovanie prvej bomby
// Hlavná herná slučka
while (gameRunning) {
if (isButtonPressed(btnPause)) togglePause(); // Ak je stlačené tlačidlo "pauza", prepni stav hry
if (isPaused) continue; // Ak je hra pozastavená, preskoč zvyšok cyklu
// Kontrola stlačenia tlačidiel a pohyb hráča v príslušnom smere
if (isButtonPressed(btnUp) && panacikY > 1) movePanacik(0, -1); // Pohyb hore
if (isButtonPressed(btnDown) && panacikY < 3) movePanacik(0, 1); // Pohyb dole
if (isButtonPressed(btnLeft) && panacikX > 0) movePanacik(-1, 0); // Pohyb doľava
if (isButtonPressed(btnRight) && panacikX < 19) movePanacik(1, 0); // Pohyb doprava
moveBombs(); // Posunutie bômb na ich nové pozície
}
endGame(); // Ak sa hra skončí, zavolá sa táto funkcia
}
// Funkcia na pohyb hráča (panáčika)
void movePanacik(int x, int y) {
lcd.setCursor(panacikX, panacikY); // Nastavenie kurzora na starú pozíciu hráča
lcd.print(" "); // Vymazanie starého panáčika z displeja
panacikX += x; // Aktualizácia X súradnice hráča
panacikY += y; // Aktualizácia Y súradnice hráča
lcd.setCursor(panacikX, panacikY); // Nastavenie kurzora na novú pozíciu hráča
lcd.write(byte(1)); // Zobrazenie panáčika na novej pozícii
delay(50);
// Kontrola, či hráč našiel mincu
if (panacikX == coinX && panacikY == coinY) {
score++; // Zvýšenie skóre o 1
lcd.setCursor(7, 0); // Nastavenie kurzora na miesto skóre
lcd.print(score); // Aktualizácia zobrazenia skóre
lcd.setCursor(panacikX, panacikY); // Nastavenie kurzora na pozíciu hráča
lcd.write(byte(3)); // Zobrazenie animácie zbierania mince
delay(200); // Krátka pauza na zobrazenie animácie
lcd.setCursor(panacikX, panacikY); // Obnovenie pozície hráča
lcd.write(byte(1)); // Opätovné zobrazenie hráča
generateCoin(); // Vygenerovanie novej mince na náhodnej pozícii
updateBombCount(score); // Zvýšenie počtu bômb na základe skóre
}
// Kontrola, či hráč narazil na bombu
for (int i = 0; i < bombCount; i++) {
if (bombs[i].active && panacikX == bombs[i].x && panacikY == bombs[i].y) {
gameRunning = false; // Ukončenie hry, ak hráč narazil na bombu
}
}
}
// Funkcia na vygenerovanie novej mince na náhodnej pozícii
void generateCoin() {
coinX = random(0, 20); // Náhodná X súradnica mince v rozmedzí 0-19
coinY = random(1, 4); // Náhodná Y súradnica mince v rozmedzí 1-3
lcd.setCursor(coinX, coinY); // Nastavenie kurzora na pozíciu mince
lcd.write(byte(2)); // Zobrazenie mince na LCD displeji
}
// Funkcia na pohyb bômb na hracej ploche
void moveBombs() {
if (millis() - lastBombMove < bombDelay) return; // Ak neubehol dostatočný čas od posledného pohybu, nič nerobíme
lastBombMove = millis(); // Aktualizujeme čas posledného pohybu
for (int i = 0; i < bombCount; i++) { // Prechádzame všetky bomby
if (!bombs[i].active) continue; // Ak bomba nie je aktívna, preskočíme ju
lcd.setCursor(bombs[i].x, bombs[i].y); // Nastavenie kurzora na starú pozíciu bomby
lcd.print(" "); // Vymazanie starej pozície bomby z displeja
bombs[i].x += (bombs[i].movingRight) ? 1 : -1; // Posunutie bomby v smere pohybu (vpravo alebo vľavo)
// Ak bomba vyjde mimo obrazovku, deaktivujeme ju a vygenerujeme novú
if (bombs[i].x < 0 || bombs[i].x > 19) {
bombs[i].active = false;
generateBomb(i);
} else {
// Ak bomba narazí na mincu, vygenerujeme novú mincu na inej pozícii
if (bombs[i].x == coinX && bombs[i].y == coinY) {
generateCoin();
}
// Ak bomba narazí na hráča, hra sa končí
if (bombs[i].x == panacikX && bombs[i].y == panacikY) {
gameRunning = false;
}
// Kontrola kolízie dvoch bômb na rovnakej pozícii
for (int j = 0; j < bombCount; j++) {
if (i != j && bombs[i].x == bombs[j].x && bombs[i].y == bombs[j].y) {
lcd.setCursor(bombs[i].x, bombs[i].y); // Nastavenie kurzora na miesto kolízie
lcd.write(byte(5)); // Zobrazenie výbuchu
delay(200); // Krátka pauza na efekt výbuchu
lcd.setCursor(bombs[i].x, bombs[i].y);
lcd.print(" "); // Vymazanie výbuchu
generateBomb(i); // Vygenerovanie novej bomby na inom mieste
generateBomb(j);
}
}
lcd.setCursor(bombs[i].x, bombs[i].y); // Nastavenie kurzora na novú pozíciu bomby
lcd.write(byte(4)); // Zobrazenie bomby na novej pozícii
}
}
}
// Funkcia na vygenerovanie novej bomby na určenom indexe
void generateBomb(int index) {
bombs[index].y = random(1, 4); // Náhodná Y súradnica bomby v rozmedzí 1-3
bombs[index].x = (random(0, 2) == 0) ? 19 : 0; // Náhodné určenie, či sa bomba objaví vľavo (0) alebo vpravo (19)
bombs[index].movingRight = (bombs[index].x == 0); // Ak je X = 0, bomba sa bude pohybovať doprava
bombs[index].active = true; // Aktivujeme bombu
lcd.setCursor(bombs[index].x, bombs[index].y); // Nastavenie kurzora na pozíciu bomby
lcd.write(byte(4)); // Zobrazenie bomby na LCD displeji
}
// Funkcia na aktualizáciu počtu bômb na základe skóre hráča
void updateBombCount(int score) {
if (score >= 12 && bombCount < 2) { // Ak hráč dosiahol skóre 12 a je len jedna bomba, pridáme druhú
bombCount = 2;
generateBomb(1); // Vygenerujeme druhú bombu
}
if (score >= 31) { // Ak skóre dosiahne 31, zrýchlime pohyb bômb
bombDelay = 200;
}
}
// Funkcia na ukončenie hry a zobrazenie konečného skóre
void endGame() {
lcd.clear(); // Vyčistenie displeja
lcd.setCursor(5, 0); // Nastavenie kurzora na riadok 0, stĺpec 5
lcd.print("Skore: "); // Zobrazenie textu "Skore: "
lcd.print(score); // Zobrazenie skóre hráča
lcd.setCursor(2, 1); // Nastavenie kurzora na pozíciu (2,1)
lcd.print("Stlacte lubovolne"); // Zobrazenie textu na displeji
lcd.setCursor(6, 2); // Nastavenie kurzora na pozíciu (6,2)
lcd.print("Tlacidlo"); // Zobrazenie textu na displeji
lcd.setCursor(2, 3); // Nastavenie kurzora na pozíciu (2,3)
lcd.print("Pre restart hry"); // Zobrazenie textu na displeji
while (!isButtonPressed(btnUp) && !isButtonPressed(btnDown) && !isButtonPressed(btnLeft) && !isButtonPressed(btnRight) && !isButtonPressed(btnPause));
delay(200); // Krátka pauza na zabránenie okamžitého opakovania
startCoinGame(); // Reštart hry
}
// Funkcia na prepínanie medzi pozastavením a pokračovaním hry
void togglePause() {
isPaused = !isPaused; // Zmeníme stav premenné isPaused (true/false)
lcd.setCursor(12, 0); // Nastavenie kurzora na miesto, kde sa zobrazí nápis "PAUZA"
lcd.print(isPaused ? "PAUZA" : " "); // Ak je hra pozastavená, zobrazíme "PAUZA", inak vymažeme text
delay(200); // Pridáme oneskorenie 500 ms na zabránenie rýchlemu opakovaniu stlačení
}