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;
}