Hra HAD je jednoduchá hra, ve které hráč ovládá hada, který se pohybuje po hrací ploše (tedy 8x8 matice). Cílem je sbírat jídlo a tím had roste. Hráč se musí vyhýbat kolizím s vlastním tělem. Hra končí, když do sebe narazí.
Pro tento projekt potřebujete Arduino, které bude sloužit jako hlavní řídící jednotka. Dále budete potřebovat 8x8 LED matici, PS2 joystick a potenciometr.
Budete potřebovat knihovnu LedControl.h .
Tento projekt představuje jednoduchou hru Snake na LED matici 8x8, kterou lze ovládat joystickem a potenciometrem. Joystick slouží k řízení směru pohybu hada, zatímco potenciometr nastavuje rychlost. Hra generuje "jídlo" na náhodné pozici a pokaždé, když ho had "sní," se prodlouží. Cílem je zvětšit délku hada na maximum, aniž by narazil do vlastního těla, což by způsobilo konec hry.
Zapojení:
Kód pro Arduino:
//from: https://github.com/fyemane/Arduino-snake-game #include "LedControl.h" // Knihovna LedControl se používá pro ovládání LED matice. Najdete ji pomocí správce knihoven nebo si ji stáhněte jako zip zde: https://github.com/wayoda/LedControl #define joystickX A2 // pin osy X joysticku #define joystickY A1 // pin osy Y joysticku #define potentiometer A3 // potenciometr pro ovládání rychlosti hada #define CLK 2 // hodiny pro LED matici #define CS 3 // chip-select pro LED matici #define DIN 4 // data-in pro LED matici // Jas LED matice: mezi 0 (nejtmavší) a 15 (nejjasnější) const short intensity = 1; // nižší = rychlejší scrollování zprávy const short messageSpeed = 10; // počáteční délka hada (1...63, doporučeno 3) const short initialSnakeLength = 3; void setup() { Serial.begin(115200); // nastavte stejnou baudovou rychlost na vašem sériovém monitoru initialize(); // inicializace pinů a LED matice calibrateJoystick(); // kalibrace domácí pozice joysticku (nechte jej nepohnutý) showSnakeMessage(); // posunuje zprávu 'snake' kolem matice } void loop() { generateFood(); scanJoystick(); // zabraňuje generátoru jídla, aby běžel, v tomto případě by běžel navždy, protože nebude schopen najít pixel bez hada calculateSnake(); // vypočítá parametry hada handleGameStates(); // odkomentujte, pokud chcete, aby se aktuální herní plán vytiskl do seriálu (trochu zpomalí hru) dumpGameBoard(); } // --------------------------------------------------------------- // // -------------------- podpůrné proměnné --------------------- // // --------------------------------------------------------------- // LedControl matrix(DIN, CLK, CS, 1); struct Point { int row = 0, col = 0; Point(int row = 0, int col = 0): row(row), col(col) {} }; struct Coordinate { int x = 0, y = 0; Coordinate(int x = 0, int y = 0): x(x), y(y) {} }; bool win = false; bool gameOver = false; // primární souřadnice hadí hlavy (hadí hlava), budou vygenerovány náhodně Point snake; // jídlo zatím nikde není Point food(-1, -1); // vytvořit s výchozími hodnotami v případě, že uživatel vypne kalibraci Coordinate joystickHome(500, 500); // hadí parametry int snakeLength = initialSnakeLength; // zvolené uživatelem v sekci konfigurace int snakeSpeed = 1; // bude nastaveno podle hodnoty potenciometru, nemůže být 0 int snakeDirection = 0; // pokud je 0, had se nepohybuje // směrové konstanty const short up = 1; const short right = 2; const short down = 3; // 'down - 2' musí být 'up' const short left = 4; // 'left - 2' musí být 'right' // práh, kde bude akceptován pohyb joysticku const int joystickThreshold = 160; // umělá logaritmičnost (strmost) potenciometru (-1 = lineární, 1 = přirozená, větší = strmější (doporučeno 0...1)) const float logarithmity = 0.4; // uložení segmentů hadího těla int gameboard[8][8] = {}; // ------------------------------------------------------------ // // -------------------------- funkce -------------------------- // // ------------------------------------------------------------ // // pokud není jídlo, vygenerujte si ho a také zkontrolujte vítězství void generateFood() { if (food.row == -1 || food.col == -1) { if (snakeLength >= 64) { win = true; return; // zabránit spuštění generátoru jídla, v tomto případě by běžel navždy, protože nebude schopen najít pixel bez hada } // generujte jídlo, dokud nebude ve správné poloze do { food.col = random(8); food.row = random(8); } while (gameboard[food.row][food.col] > 0); } } // sleduje pohyby joysticku a bliká s jídlem void scanJoystick() { int previousDirection = snakeDirection; // uložit poslední směr long timestamp = millis(); while (millis() < timestamp + snakeSpeed) { // vypočítat rychlost hada exponenciálně (10...1000 ms) float raw = mapf(analogRead(potentiometer), 0, 1023, 0, 1); snakeSpeed = mapf(pow(raw, 3.5), 0, 1, 10, 1000); // měnit rychlost exponenciálně if (snakeSpeed == 0) snakeSpeed = 1; // bezpečnost: rychlost nemůže být 0 // určit směr hada analogRead(joystickY) < joystickHome.y - joystickThreshold ? snakeDirection = right : 0; analogRead(joystickY) > joystickHome.y + joystickThreshold ? snakeDirection = left : 0; analogRead(joystickX) < joystickHome.x - joystickThreshold ? snakeDirection = up : 0; analogRead(joystickX) > joystickHome.x + joystickThreshold ? snakeDirection = down : 0; // ignorovat změnu směru o 180 stupňů (žádný efekt pro nepohybujícího se hada) snakeDirection + 2 == previousDirection & previousDirection != 0 ? snakeDirection = previousDirection : 0; snakeDirection - 2 == previousDirection & previousDirection != 0 ? snakeDirection = previousDirection : 0; // inteligentně blikat s jídlem matrix.setLed(0, food.row, food.col, millis() % 100 < 50 ? 1 : 0); } } // vypočítat údaje o pohybu hada void calculateSnake() { switch (snakeDirection) { case up: snake.row--; fixEdge(); matrix.setLed(0, snake.row, snake.col, 1); break; case right: snake.col++; fixEdge(); matrix.setLed(0, snake.row, snake.col, 1); break; case down: snake.row++; fixEdge(); matrix.setLed(0, snake.row, snake.col, 1); break; case left: snake.col--; fixEdge(); matrix.setLed(0, snake.row, snake.col, 1); break; default: // pokud se had nepohybuje, odejděte return; } // pokud existuje segment hadího těla, způsobí to konec hry (had se musí pohybovat) if (gameboard[snake.row][snake.col] > 1 & snakeDirection != 0) { gameOver = true; return; } // zkontrolujte, zda bylo jídlo snědeno if (snake.row == food.row & snake.col == food.col) { food.row = -1; // reset food food.col = -1; // přírůstek délky hada snakeLength++; // zvětšit všechny segmenty hadího těla for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { if (gameboard[row][col] > 0 ) { gameboard[row][col]++; } } } } // přidat nový segment na umístění hadí hlavy gameboard[snake.row][snake.col] = snakeLength + 1; // se za chvíli sníží // snižte všechny segmenty hadího těla, pokud je segment 0, vypněte odpovídající LED for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { // pokud existuje segment těla, snižte jeho hodnotu if (gameboard[row][col] > 0 ) { gameboard[row][col]--; } // zobrazit aktuální pixel matrix.setLed(0, row, col, gameboard[row][col] == 0 ? 0 : 1); } } } // způsobí, že se had objeví na druhé straně obrazovky, pokud se dostane z okraje void fixEdge() { snake.col < 0 ? snake.col += 8 : 0; snake.col > 7 ? snake.col -= 8 : 0; snake.row < 0 ? snake.row += 8 : 0; snake.row > 7 ? snake.row -= 8 : 0; } void handleGameStates() { if (gameOver || win) { unrollSnake(); showScoreMessage(snakeLength - initialSnakeLength); if (gameOver) showGameOverMessage(); else if (win) showWinMessage(); // znovu spustit hru win = false; gameOver = false; snake.row = random(8); snake.col = random(8); food.row = -1; food.col = -1; snakeLength = initialSnakeLength; snakeDirection = 0; memset(gameboard, 0, sizeof(gameboard[0][0]) * 8 * 8); matrix.clearDisplay(0); } } void unrollSnake() { // vypněte LED kontrolku jídla matrix.setLed(0, food.row, food.col, 0); delay(800); // 5x zablikat na obrazovce for (int i = 0; i < 5; i++) { // převrátit obrazovku for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { matrix.setLed(0, row, col, gameboard[row][col] == 0 ? 1 : 0); } } delay(20); // převrátit zpět for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { matrix.setLed(0, row, col, gameboard[row][col] == 0 ? 0 : 1); } } delay(50); } delay(600); for (int i = 1; i <= snakeLength; i++) { for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { if (gameboard[row][col] == i) { matrix.setLed(0, row, col, 0); delay(100); } } } } } // 10krát zkalibrujte joystick domů void calibrateJoystick() { Coordinate values; for (int i = 0; i < 10; i++) { values.x += analogRead(joystickX); values.y += analogRead(joystickY); } joystickHome.x = values.x / 10; joystickHome.y = values.y / 10; } void initialize(){ matrix.shutdown(0, false); matrix.setIntensity(0, intensity); matrix.clearDisplay(0); randomSeed(analogRead(A5)); snake.row = random(8); snake.col = random(8); } void dumpGameBoard() { String buff = "nnn"; for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { if (gameboard[row][col] < 10) buff += " "; if (gameboard[row][col] != 0) buff += gameboard[row][col]; else if (col == food.col & row == food.row) buff += "@"; else buff += "-"; buff += " "; } buff += "n"; } Serial.println(buff); } // ------------------------------------------------------------- // // -------------------------- zprávy --------------------------- // // ------------------------------------------------------------- // const PROGMEM bool snakeMessage[8][56] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; const PROGMEM bool gameOverMessage[8][90] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; const PROGMEM bool scoreMessage[8][58] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; const PROGMEM bool digits[][8][8] = { { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 1, 1, 1, 0}, {0, 1, 1, 1, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} }, { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 0} }, { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 0, 0, 0, 1, 1, 0}, {0, 0, 0, 0, 1, 1, 0, 0}, {0, 0, 1, 1, 0, 0, 0, 0}, {0, 1, 1, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 0} }, { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 0, 0, 0, 1, 1, 0}, {0, 0, 0, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} }, { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0}, {0, 0, 1, 0, 1, 1, 0, 0}, {0, 1, 0, 0, 1, 1, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 0, 1, 1, 0, 0}, {0, 0, 0, 0, 1, 1, 0, 0} }, { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 0}, {0, 1, 1, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 1, 1, 0}, {0, 0, 0, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} }, { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} }, { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 0, 0, 1, 1, 0, 0}, {0, 0, 0, 0, 1, 1, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0} }, { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} }, { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} } }; // posouvá zprávu „snake“ po matrici void showSnakeMessage() { [&] { for (int d = 0; d < sizeof(snakeMessage[0]) - 7; d++) { for (int col = 0; col < 8; col++) { delay(messageSpeed); for (int row = 0; row < 8; row++) { // toto přečte bajt z PROGMEM a zobrazí jej na obrazovce matrix.setLed(0, row, col, pgm_read_byte(&(snakeMessage[row][col + d]))); } } // pokud je joystick posunut, opusťte zprávu if (analogRead(joystickY) < joystickHome.y - joystickThreshold || analogRead(joystickY) > joystickHome.y + joystickThreshold || analogRead(joystickX) < joystickHome.x - joystickThreshold || analogRead(joystickX) > joystickHome.x + joystickThreshold) { return; // vrátit funkci lambda } } }(); matrix.clearDisplay(0); // počkejte, až se joystick vrátí while (analogRead(joystickY) < joystickHome.y - joystickThreshold || analogRead(joystickY) > joystickHome.y + joystickThreshold || analogRead(joystickX) < joystickHome.x - joystickThreshold || analogRead(joystickX) > joystickHome.x + joystickThreshold) {} } // posouvá zprávu „game over“ po matrici void showGameOverMessage() { [&] { for (int d = 0; d < sizeof(gameOverMessage[0]) - 7; d++) { for (int col = 0; col < 8; col++) { delay(messageSpeed); for (int row = 0; row < 8; row++) { // toto přečte bajt z PROGMEM a zobrazí jej na obrazovce matrix.setLed(0, row, col, pgm_read_byte(&(gameOverMessage[row][col + d]))); } } // pokud je joystick posunut, opusťte zprávu if (analogRead(joystickY) < joystickHome.y - joystickThreshold || analogRead(joystickY) > joystickHome.y + joystickThreshold || analogRead(joystickX) < joystickHome.x - joystickThreshold || analogRead(joystickX) > joystickHome.x + joystickThreshold) { return; // vrátit funkci lambda } } }(); matrix.clearDisplay(0); // počkejte, až se joystick vrátí while (analogRead(joystickY) < joystickHome.y - joystickThreshold || analogRead(joystickY) > joystickHome.y + joystickThreshold || analogRead(joystickX) < joystickHome.x - joystickThreshold || analogRead(joystickX) > joystickHome.x + joystickThreshold) {} } // posouvá zprávu „win“ po matrici void showWinMessage() { // dosud neimplementováno // implementujte to } // posouvá zprávu „score“ po matrici void showScoreMessage(int score) { if (score < 0 || score > 99) return; // určete číslice skóre int second = score % 10; int first = (score / 10) % 10; [&] { for (int d = 0; d < sizeof(scoreMessage[0]) + 2 * sizeof(digits[0][0]); d++) { for (int col = 0; col < 8; col++) { delay(messageSpeed); for (int row = 0; row < 8; row++) { if (d <= sizeof(scoreMessage[0]) - 8) { matrix.setLed(0, row, col, pgm_read_byte(&(scoreMessage[row][col + d]))); } int c = col + d - sizeof(scoreMessage[0]) + 6; // posunout o 6 px před předchozí zprávu // pokud je skóre < 10, posuňte první číslici (nulu) if (score < 10) c += 8; if (c >= 0 & c < 8) { if (first > 0) matrix.setLed(0, row, col, pgm_read_byte(&(digits[first][row][c]))); // zobrazit, pouze pokud je skóre >= 10 (viz výše) } else { c -= 8; if (c >= 0 & c < 8) { matrix.setLed(0, row, col, pgm_read_byte(&(digits[second][row][c]))); // ukázat vždy } } } } // pokud je joystick posunut, opusťte zprávu if (analogRead(joystickY) < joystickHome.y - joystickThreshold || analogRead(joystickY) > joystickHome.y + joystickThreshold || analogRead(joystickX) < joystickHome.x - joystickThreshold || analogRead(joystickX) > joystickHome.x + joystickThreshold) { return; // vrátit funkci lambda } } }(); matrix.clearDisplay(0); } // standardní mapová funkce, ale s plováky float mapf(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; }