// Constants for 32x32 matrix
#define X_SEGMENTS 4
#define Y_SEGMENTS 4
#define NUM_SEGMENTS (X_SEGMENTS * Y_SEGMENTS)
#define MAX_X 31
#define MAX_Y 31
#include <MD_MAX72xx.h>
#include <Servo.h>
// Snake game variables
int snakeX[100], snakeY[100]; // Snake position
int snakeLength = 3; // Initial snake length
int snakeDir = 0; // Snake direction (0: right, 1: down, 2: left, 3: up)
int foodX, foodY; // Food position
#define CLK 13
#define DIN 11
#define CS 10
byte fb[8 * NUM_SEGMENTS];
void setup() {
// Initialization code for 32x32 matrix
pinMode(CLK, OUTPUT);
pinMode(DIN, OUTPUT);
pinMode(CS, OUTPUT);
shiftAll(0x0f, 0x00); // Display test register - test mode off
shiftAll(0x0b, 0x07); // Scan limit register - display digits 0 thru 7
shiftAll(0x0c, 0x01); // Shutdown register - normal operation
shiftAll(0x0a, 0x0f); // Intensity register - max brightness
shiftAll(0x09, 0x00); // Decode mode register - No decode
// Initialize snake and food
resetGame();
}
void loop() {
moveSnake();
show();
delay(100); // Adjust snake speed
}
void show() {
for (byte row = 0; row < 8; row++) {
digitalWrite(CS, LOW);
for (byte segment = 0; segment < NUM_SEGMENTS; segment++) {
byte x = segment % X_SEGMENTS;
byte y = segment / X_SEGMENTS * 8;
byte addr = (row + y) * X_SEGMENTS;
if (segment & X_SEGMENTS) { // Odd rows of segments
shiftOut(DIN, CLK, MSBFIRST, 8 - row);
shiftOut(DIN, CLK, LSBFIRST, fb[addr + x]);
} else { // Even rows of segments
shiftOut(DIN, CLK, MSBFIRST, 1 + row);
shiftOut(DIN, CLK, MSBFIRST, fb[addr - x + X_SEGMENTS - 1]);
}
}
digitalWrite(CS, HIGH);
}
}
void moveSnake() {
// Move the body of the snake
for (int i = snakeLength - 1; i > 0; --i) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
// Move the head of the snake based on the current direction
switch (snakeDir) {
case 0: // Right
snakeX[0]++;
break;
case 1: // Down
snakeY[0]++;
break;
case 2: // Left
snakeX[0]--;
break;
case 3: // Up
snakeY[0]--;
break;
}
// Check if the snake eats the food, increase length and respawn food
if (snakeX[0] == foodX && snakeY[0] == foodY) {
snakeLength++;
spawnFood();
}
// Check if the snake hits the boundary, reset the game
if (snakeX[0] < 0 || snakeX[0] > MAX_X || snakeY[0] < 0 || snakeY[0] > MAX_Y) {
resetGame();
}
}
void spawnFood() {
// Randomly generate food position
foodX = random(0, MAX_X + 1);
foodY = random(0, MAX_Y + 1);
}
void resetGame() {
// Reset game parameters
snakeLength = 3;
snakeX[0] = 0;
snakeY[0] = 0;
snakeX[1] = 1;
snakeY[1] = 0;
snakeX[2] = 2;
snakeY[2] = 0;
snakeDir = 0;
spawnFood(); // Respawn food
}
void shiftAll(byte send_to_address, byte send_this_data) {
digitalWrite(CS, LOW);
for (int i = 0; i < NUM_SEGMENTS; i++) {
shiftOut(DIN, CLK, MSBFIRST, send_to_address);
shiftOut(DIN, CLK, MSBFIRST, send_this_data);
}
digitalWrite(CS, HIGH);
}
void set_pixel(uint8_t x, uint8_t y, uint8_t mode) {
byte *addr = &fb[x / 8 + y * X_SEGMENTS];
byte mask = 128 >> (x % 8);
switch (mode) {
case 0: // Clear pixel
*addr &= ~mask;
break;
case 1: // Plot pixel
*addr |= mask;
break;
case 2: // XOR pixel
*addr ^= mask;
break;
}
}