Introduction: MATRIX MAX7219 SNAKE GAME ON ARDUINO 31-8-2019
INTRODUCTION
This Tutorial will help you make a game called the snake game the snake game is usually on old phones the snake game is a game of a snake that go and eat the dot (food) then the snake will get longer the way to lose is by touching the snake tail. So i thought i could make a game of it using Arduino UNO.
Supplies
1-Arduino UNO
2-Mini Breadboard
3- 8x8 dot matrix MAX1219
4-Joystick
5- Jumper Wires Male/Male and Male/Female
6-USB Cable
Step 1: -WIRING
MATRIX WIRES
VCC To 5V on arduino
GND To GND on arduino
OIN To I/O 12 on arduino
CS To I/O 11 on arduino
CLK To I/O 10 on arduino
JOYSTICK WIRES
GND To GND on arduino
+5V To 5V on arduino
VRX To A2 on arduino
VRY To A3 on arduino
--------------------------------
SW Will Not Use
Step 2: Code
#include "LedControl.h" // LedControl library is used for controlling a LED matrix. Find it using Library Manager or download zip here: https://github.com/wayoda/LedControl
// --------------------------------------------------------------- // // ------------------------- user config ------------------------- // // --------------------------------------------------------------- /
/ there are defined all the pins struct Pin { static const short joystickX = A2; // joystick X axis pin static const short joystickY = A3; // joystick Y axis pin static const short joystickVCC = 15; // virtual VCC for the joystick (Analog 1) (to make the joystick connectable right next to the arduino nano) static const short joystickGND = 14; // virtual GND for the joystick (Analog 0) (to make the joystick connectable right next to the arduino nano)
static const short potentiometer = A7; // potentiometer for snake speed control
static const short CLK = 10; // clock for LED matrix static const short CS = 11; // chip-select for LED matrix static const short DIN = 12; // data-in for LED matrix };
// LED matrix brightness: between 0(darkest) and 15(brightest) const short intensity = 8;
// lower = faster message scrolling const short messageSpeed = 5;
// initial snake length (1...63, recommended 3) const short initialSnakeLength = 3;
void setup() { Serial.begin(115200); // set the same baud rate on your Serial Monitor initialize(); // initialize pins & LED matrix calibrateJoystick(); // calibrate the joystick home (do not touch it) showSnakeMessage(); // scrolls the 'snake' message around the matrix }
void loop() { generateFood(); // if there is no food, generate one scanJoystick(); // watches joystick movements & blinks with food calculateSnake(); // calculates snake parameters handleGameStates();
// uncomment this if you want the current game board to be printed to the serial (slows down the game a bit) // dumpGameBoard(); }
// --------------------------------------------------------------- // // -------------------- supporting variables --------------------- // // --------------------------------------------------------------- //
LedControl matrix(Pin::DIN, Pin::CLK, Pin::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;
// primary snake head coordinates (snake head), it will be randomly generated Point snake;
// food is not anywhere yet Point food(-1, -1);
// construct with default values in case the user turns off the calibration Coordinate joystickHome(500, 500);
// snake parameters int snakeLength = initialSnakeLength; // choosed by the user in the config section int snakeSpeed = 1; // will be set according to potentiometer value, cannot be 0 int snakeDirection = 0; // if it is 0, the snake does not move
// direction constants const short up = 1; const short right = 2; const short down = 3; // 'down - 2' must be 'up' const short left = 4; // 'left - 2' must be 'right'
// threshold where movement of the joystick will be accepted const int joystickThreshold = 160;
// artificial logarithmity (steepness) of the potentiometer (-1 = linear, 1 = natural, bigger = steeper (recommended 0...1)) const float logarithmity = 0.4;
// snake body segments storage int gameboard[8][8] = {};
// --------------------------------------------------------------- // // -------------------------- functions -------------------------- // // --------------------------------------------------------------- /
/ if there is no food, generate one, also check for victory void generateFood() { if (food.row == -1 || food.col == -1) { // self-explanatory if (snakeLength >= 64) { win = true; return; // prevent the food generator from running, in this case it would run forever, because it will not be able to find a pixel without a snake }
// generate food until it is in the right position do { food.col = random(8); food.row = random(8); } while (gameboard[food.row][food.col] > 0); } }
// watches joystick movements & blinks with food void scanJoystick() { int previousDirection = snakeDirection; // save the last direction long timestamp = millis();
while (millis() < timestamp + snakeSpeed) { // calculate snake speed exponentially (10...1000ms) float raw = mapf(analogRead(Pin::potentiometer), 0, 1023, 0, 1); snakeSpeed = mapf(pow(raw, 3.5), 0, 1, 10, 1000); // change the speed exponentially if (snakeSpeed == 0) snakeSpeed = 1; // safety: speed can not be 0
// determine the direction of the snake analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold ? snakeDirection = up : 0; analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold ? snakeDirection = down : 0; analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold ? snakeDirection = left : 0; analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold ? snakeDirection = right : 0;
// ignore directional change by 180 degrees (no effect for non-moving snake) snakeDirection + 2 == previousDirection && previousDirection != 0 ? snakeDirection = previousDirection : 0; snakeDirection - 2 == previousDirection && previousDirection != 0 ? snakeDirection = previousDirection : 0;
// intelligently blink with the food matrix.setLed(0, food.row, food.col, millis() % 100 < 50 ? 1 : 0); } }
// calculate snake movement data 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: // if the snake is not moving, exit return; }
// if there is a snake body segment, this will cause the end of the game (snake must be moving) if (gameboard[snake.row][snake.col] > 1 && snakeDirection != 0) { gameOver = true; return; }
// check if the food was eaten if (snake.row == food.row && snake.col == food.col) { food.row = -1; // reset food food.col = -1;
// increment snake length snakeLength++;
// increment all the snake body segments for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { if (gameboard[row][col] > 0 ) { gameboard[row][col]++; } } } }
// add new segment at the snake head location gameboard[snake.row][snake.col] = snakeLength + 1; // will be decremented in a moment
// decrement all the snake body segments, if segment is 0, turn the corresponding led off for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { // if there is a body segment, decrement it's value if (gameboard[row][col] > 0 ) { gameboard[row][col]--; }
// display the current pixel matrix.setLed(0, row, col, gameboard[row][col] == 0 ? 0 : 1); } } }
// causes the snake to appear on the other side of the screen if it gets out of the edge 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();
// re-init the game 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() { // switch off the food LED matrix.setLed(0, food.row, food.col, 0);
delay(800);
// flash the screen 5 times for (int i = 0; i < 5; i++) { // invert the screen 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);
// invert it back 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); } } } } }
// calibrate the joystick home for 10 times void calibrateJoystick() { Coordinate values;
for (int i = 0; i < 10; i++) { values.x += analogRead(Pin::joystickX); values.y += analogRead(Pin::joystickY); }
joystickHome.x = values.x / 10; joystickHome.y = values.y / 10; }
void initialize() { pinMode(Pin::joystickVCC, OUTPUT); digitalWrite(Pin::joystickVCC, HIGH);
pinMode(Pin::joystickGND, OUTPUT); digitalWrite(Pin::joystickGND, LOW);
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 = "\n\n\n"; 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); }
// --------------------------------------------------------------- // // -------------------------- messages --------------------------- // // --------------------------------------------------------------- //
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} } };
// scrolls the 'snake' message around the matrix 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++) { // this reads the byte from the PROGMEM and displays it on the screen matrix.setLed(0, row, col, pgm_read_byte(&(snakeMessage[row][col + d]))); } }
// if the joystick is moved, exit the message if (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) { return; // return the lambda function } } }();
matrix.clearDisplay(0);
// wait for joystick co come back while (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) {}
}
// scrolls the 'game over' message around the matrix 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++) { // this reads the byte from the PROGMEM and displays it on the screen matrix.setLed(0, row, col, pgm_read_byte(&(gameOverMessage[row][col + d]))); } }
// if the joystick is moved, exit the message if (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) { return; // return the lambda function } } }();
matrix.clearDisplay(0);
// wait for joystick co come back while (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) {}
}
// scrolls the 'win' message around the matrix void showWinMessage() { // not implemented yet // TODO: implement it }
// scrolls the 'score' message with numbers around the matrix void showScoreMessage(int score) { if (score < 0 || score > 99) return;
// specify score digits 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; // move 6 px in front of the previous message
// if the score is < 10, shift out the first digit (zero) 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]))); // show only if score is >= 10 (see above) } else { c -= 8; if (c >= 0 && c < 8) { matrix.setLed(0, row, col, pgm_read_byte(&(digits[second][row][c]))); // show always } } } }
// if the joystick is moved, exit the message if (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) { return; // return the lambda function } } }();
matrix.clearDisplay(0);
//// wait for joystick co come back //while (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold // || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold // || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold // || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) {}
}
// standard map function, but with floats 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; }
Comments
Question 3 years ago on Step 1