#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
int pinCS = 5;
int numberOfHorizontalDisplays = 4;
int numberOfVerticalDisplays = 4;
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
#define SIZE 32
#define ADVANCE_DELAY 20
int snake[SIZE * SIZE][2];
int length;
int food[2], v[2];
bool is_game_over = false;
long current_time;
long prev_advance;
int blink_count;
const short messageSpeed = 1;
void init_game() {
prev_advance = current_time = 0;
blink_count = 3;
int half = SIZE / 2;
length = SIZE / 5;
for (int i = 0; i < length; i++) {
snake[i][0] = half - 1;
snake[i][1] = half + i;
}
food[0] = half + 1;
food[1] = half - 1;
v[0] = 0;
v[1] = -1;
}
void render() {
for (int i = 0; i < length; i++) {
matrix.drawPixel(snake[i][1], snake[i][0], HIGH);
}
matrix.drawPixel(food[1], food[0], HIGH);
matrix.write();
}
void clearScreen() {
matrix.fillScreen(LOW);
matrix.write();
}
bool advance() {
int head[2] = {snake[0][0] + v[0], snake[0][1] + v[1]};
if (head[0] < 0 || head[0] >= SIZE) {
delay(1000);
showGameOverMessage();
return true;
}
if (head[1] < 0 || head[1] >= SIZE) {
delay(1000);
showGameOverMessage();
return true;
}
for (int i = 0; i < length; i++) {
if (snake[i][0] == head[0] && snake[i][1] == head[1]) {
delay(1000);
showGameOverMessage();
return true;
}
}
bool grow = (head[0] == food[0] && head[1] == food[1]);
if (grow) {
length++;
randomSeed(current_time);
food[0] = random(SIZE);
food[1] = random(SIZE);
}
for (int i = length - 1; i >= 0; i--) {
snake[i + 1][0] = snake[i][0];
snake[i + 1][1] = snake[i][1];
}
snake[0][0] += v[0];
snake[0][1] += v[1];
return false;
}
void setup() {
matrix.setIntensity(0);
matrix.setPosition(0, 3, 3);
matrix.setPosition(1, 2, 3);
matrix.setPosition(2, 1, 3);
matrix.setPosition(3, 0, 3);
matrix.setPosition(4, 0, 2);
matrix.setPosition(5, 1, 2);
matrix.setPosition(6, 2, 2);
matrix.setPosition(7, 3, 2);
matrix.setPosition(8, 3, 1);
matrix.setPosition(9, 2, 1);
matrix.setPosition(10, 1, 1);
matrix.setPosition(11, 0, 1);
matrix.setPosition(12, 0, 0);
matrix.setPosition(13, 1, 0);
matrix.setPosition(14, 2, 0);
matrix.setPosition(15, 3, 0);
matrix.setRotation(0, 1);
matrix.setRotation(1, 1);
matrix.setRotation(2, 1);
matrix.setRotation(3, 1);
matrix.setRotation(4, 3);
matrix.setRotation(5, 3);
matrix.setRotation(6, 3);
matrix.setRotation(7, 3);
matrix.setRotation(8, 1);
matrix.setRotation(9, 1);
matrix.setRotation(10, 1);
matrix.setRotation(11, 1);
matrix.setRotation(12, 3);
matrix.setRotation(13, 3);
matrix.setRotation(14, 3);
matrix.setRotation(15, 3);
init_game();
render();
}
void loop() {
if (!is_game_over) {
clearScreen();
render();
if (current_time - prev_advance > ADVANCE_DELAY) {
is_game_over = advance();
prev_advance = current_time;
}
} else {
while (blink_count > 0) {
clearScreen();
delay(300);
render();
delay(300);
blink_count--;
}
}
readControls();
current_time++;
}
void restart() {
init_game();
is_game_over = false;
}
void readControls() {
int dx;
int dy;
int a = analogRead(34);
if (a >= 0 && a <= 192) {
dx = 0;
dy = -1;
if (is_game_over) {
restart();
}
}
if (a >= 193 && a <= 762) {
dx = -1;
dy = 0;
if (is_game_over) {
restart();
}
}
if (a >= 763 && a <= 1478) {
dx = 1;
dy = 0;
if (is_game_over) {
restart();
}
}
if (a >= 1479 && a <= 2289) {
dx = 0;
dy = 1; if (is_game_over) {
restart();
}
}
if (a >= 2290 && a <= 3427) {
if (is_game_over) {
restart();
}
}
if (a >= 3428) {
dx = 0;
dy = 0;
}
if (dy != 0 && v[0] != 0) {
v[0] = 0;
v[1] = dy;
}
if (dx != 0 && v[1] != 0) {
v[0] = dx;
v[1] = 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}
};
void showGameOverMessage() {
for (int d = 0; d < sizeof(gameOverMessage[0]) - 7; d++) {
for (int col = 0; col < 32; col++) {
delay(messageSpeed);
for (int row = 0; row < 8; row++) {
matrix.drawPixel(col, row + 8, pgm_read_byte(&(gameOverMessage[row][col + d])));
}
}
matrix.write();
}
}