Snake Game with XIAO ESP32-S3 and LED Matrix MAX7219 4-in-1

This project brings the classic Snake game to life using the XIAO ESP32-S3 and a MAX7219 4-in-1 8x8 LED Matrix (32x8 pixels).

BeginnerProtip1 hour255
Snake Game with XIAO ESP32-S3 and LED Matrix MAX7219 4-in-1

Things used in this project

Hardware components

Seeed Studio XIAO ESP32S3
Seeed Studio XIAO ESP32S3
×1
LED Dot Matrix Display, Red
LED Dot Matrix Display, Red
×4
Female/Female Jumper Wires
Female/Female Jumper Wires
×1
USB Cable, USB Type C Plug
USB Cable, USB Type C Plug
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Scematics Snake Game with XIAO ESP32-S3 Code

Code

Snake Game with XIAO ESP32-S3 Code

Arduino
#include <MD_MAX72xx.h>
#include <SPI.h>

// Pin Configuration for MAX7219
#define DATA_PIN  6  // DIN
#define CLK_PIN   7  // CLK
#define CS_PIN    5  // CS

// Game Settings
#define GRID_SIZE 8
#define INITIAL_DELAY 200
#define MAX_SNAKE_LENGTH 64

// Initialize LED Matrix (4 modules in a row)
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// Snake Game Variables
int snakeX[MAX_SNAKE_LENGTH], snakeY[MAX_SNAKE_LENGTH];
int snakeLength = 3;
int foodX, foodY;
int direction = 0; // 0=right, 1=up, 2=left, 3=down
int newDirection = 0;
bool gameOver = false;
bool gameStarted = false;
int score = 0;
unsigned long lastUpdate = 0;
int gameSpeed = INITIAL_DELAY;

void setup() {
  Serial.begin(115200);
  Serial.println("Snake Game - Control with Keyboard");
  Serial.println("W = Up, A = Left, S = Down, D = Right");
  Serial.println("Space = Start/Restart");
  
  // Initialize LED Matrix
  mx.begin();
  mx.control(MD_MAX72XX::INTENSITY, 5);
  mx.clear();
  
  // Display Start Screen
  displayStartScreen();
  
  // Initialize Snake
  resetGame();
}

void loop() {
  if (!gameStarted) {
    if (Serial.available() > 0 && Serial.read() == ' ') {
      gameStarted = true;
      mx.clear();
    }
    return;
  }
  
  if (gameOver) {
    displayGameOver();
    
    if (Serial.available() > 0 && Serial.read() == ' ') {
      resetGame();
      gameOver = false;
    }
    return;
  }
  
  // Handle Keyboard Input
  readInput();
  
  // Update Game State
  if (millis() - lastUpdate > gameSpeed) {
    updateGame();
    lastUpdate = millis();
  }
  
  // Render Game
  drawGame();
}

void readInput() {
  if (Serial.available() > 0) {
    char key = Serial.read();
    
    switch (tolower(key)) {
      case 'w': if (direction != 3) newDirection = 1; break; // Up
      case 's': if (direction != 1) newDirection = 3; break; // Down
      case 'a': if (direction != 0) newDirection = 2; break; // Left
      case 'd': if (direction != 2) newDirection = 0; break; // Right
    }
  }
}

void updateGame() {
  // Update direction
  direction = newDirection;
  
  // Move snake body (from tail to head)
  for (int i = snakeLength-1; i > 0; i--) {
    snakeX[i] = snakeX[i-1];
    snakeY[i] = snakeY[i-1];
  }
  
  // Move head based on direction
  switch (direction) {
    case 0: snakeX[0]++; break; // Right
    case 1: snakeY[0]--; break; // Up 
    case 2: snakeX[0]--; break; // Left
    case 3: snakeY[0]++; break; // Down
  }
  
  // Wall collision check
  if (snakeX[0] < 0 || snakeX[0] >= GRID_SIZE*MAX_DEVICES || 
      snakeY[0] < 0 || snakeY[0] >= GRID_SIZE) {
    gameOver = true;
    return;
  }
  
  // Self collision check
  for (int i = 1; i < snakeLength; i++) {
    if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
      gameOver = true;
      return;
    }
  }
  
  // Food collision check
  if (snakeX[0] == foodX && snakeY[0] == foodY) {
    snakeLength++;
    score++;
    
    // Increase speed every 3 foods
    if (score % 3 == 0 && gameSpeed > 50) {
      gameSpeed -= 20;
    }
    
    generateFood();
  }
}

void drawGame() {
  mx.clear();
  
  // Draw Snake
  for (int i = 0; i < snakeLength; i++) {
    int module = snakeX[i] / GRID_SIZE;
    int x = snakeX[i] % GRID_SIZE;
    // Set point with correct module addressing
    mx.setPoint(snakeY[i], module * GRID_SIZE + x, true);
  }
  
  // Draw Food
  int foodModule = foodX / GRID_SIZE;
  int foodPixelX = foodX % GRID_SIZE;
  mx.setPoint(foodY, foodModule * GRID_SIZE + foodPixelX, true);
}

void generateFood() {
  bool validPosition = false;
  
  while (!validPosition) {
    foodX = random(GRID_SIZE * MAX_DEVICES);
    foodY = random(GRID_SIZE);
    
    validPosition = true;
    for (int i = 0; i < snakeLength; i++) {
      if (snakeX[i] == foodX && snakeY[i] == foodY) {
        validPosition = false;
        break;
      }
    }
  }
}

void resetGame() {
  // Reset snake position (centered)
  snakeLength = 3;
  int startX = (GRID_SIZE * MAX_DEVICES) / 2;
  snakeX[0] = startX;
  snakeY[0] = GRID_SIZE/2;
  snakeX[1] = startX-1;
  snakeY[1] = GRID_SIZE/2;
  snakeX[2] = startX-2;
  snakeY[2] = GRID_SIZE/2;
  
  // Reset direction
  direction = 0;
  newDirection = 0;
  
  // Reset score and speed
  score = 0;
  gameSpeed = INITIAL_DELAY;
  
  // Generate first food
  generateFood();
  
  Serial.print("Game Started! Score: ");
  Serial.println(score);
}

void displayStartScreen() {
  // Snake pattern
  byte snakePattern[8] = {
    B00111100,
    B01000010,
    B10000001,
    B10000001,
    B10011001,
    B10100101,
    B01000010,
    B00111100
  };
  
  // Display on all modules
  for (int m = 0; m < MAX_DEVICES; m++) {
    for (int row = 0; row < 8; row++) {
      mx.setRow(m, row, snakePattern[row]);
    }
  }
  delay(2000);
  mx.clear();
}

void displayGameOver() {
  // Game Over pattern
  byte gameOverPattern[8] = {
    B01111110,
    B10000001,
    B10000001,
    B10000001,
    B01111110,
    B00000000,
    B01111110,
    B01111110
  };
  
  // Display on all modules
  for (int m = 0; m < MAX_DEVICES; m++) {
    for (int row = 0; row < 8; row++) {
      mx.setRow(m, row, gameOverPattern[row]);
    }
  }
  
  Serial.print("Game Over! Final Score: ");
  Serial.println(score);
}

Credits

Sulistyo
4 projects • 3 followers
Rafli Surya Saputra 77039
1 project • 0 followers
Hendra Kusumah
49 projects • 163 followers
Love hacking and making new things from IoT to robotics
Muhammad Fauzan UR
2 projects • 3 followers
Anggiat Sitinjak
1 project • 0 followers
Student & IoT enthusiast

Comments