Note

Hello, welcome to the SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community on Facebook! Dive deeper into Raspberry Pi, Arduino, and ESP32 with fellow enthusiasts.

Why Join?

  • Expert Support: Solve post-sale issues and technical challenges with help from our community and team.

  • Learn & Share: Exchange tips and tutorials to enhance your skills.

  • Exclusive Previews: Get early access to new product announcements and sneak peeks.

  • Special Discounts: Enjoy exclusive discounts on our newest products.

  • Festive Promotions and Giveaways: Take part in giveaways and holiday promotions.

👉 Ready to explore and create with us? Click [here] and join today!

GAME - Snake

This example implements the classic Snake game on an 8x12 LED matrix using the R4 Wifi board. Players control the snake’s direction using a dual-axis joystick.

Required Components

In this project, we need the following components.

It’s definitely convenient to buy a whole kit, here’s the link:

Name

ITEMS IN THIS KIT

LINK

Elite Explorer Kit

300+

Elite Explorer Kit

You can also buy them separately from the links below.

COMPONENT INTRODUCTION

PURCHASE LINK

Arduino Uno R4 WiFi

-

Jumper Wires

BUY

Joystick Module

BUY

Wiring

../_images/13_snake_bb.png

Schematic

../_images/13_snake_schematic.png

Code

Note

  • You can open the file 13_snake.ino under the path of elite-explorer-kit-main\fun_project\13_snake directly.

  • Or copy this code into Arduino IDE.

13_snake.ino
  1/*
  2  This code implements a simple Snake game using an Arduino Uno R4 and a 
  3  Joystick Module. The Snake moves based on joystick input, and the 
  4  objective is to eat randomly generated food without colliding with 
  5  the snake's body. The game ends if the snake collides with itself.
  6
  7  Board: Arduino Uno R4 
  8  Component: Joystick Module
  9*/
 10
 11
 12#include "Arduino_LED_Matrix.h"
 13
 14ArduinoLEDMatrix matrix;
 15byte frame[8][12];
 16byte flatFrame[8 * 12];  // Flattened frame for matrix.loadPixels()
 17
 18// Snake variables
 19struct Point {
 20  byte x;
 21  byte y;
 22};
 23
 24Point snake[100];
 25int snakeLength = 3;
 26Point food;
 27int direction = 0;  // 0=up, 1=right, 2=down, 3=left
 28
 29void setup() {
 30  pinMode(A0, INPUT);  // joystick X-axis
 31  pinMode(A1, INPUT);  // joystick Y-axis
 32
 33  // Initialize LED matrix
 34  matrix.begin();
 35
 36  // Initialize snake at middle of screen
 37  snake[0] = { 6, 4 };
 38  snake[1] = { 6, 5 };
 39  snake[2] = { 6, 6 };
 40
 41  // Generate initial food
 42  generateFood();
 43}
 44
 45void loop() {
 46  // Read joystick input
 47  int x = analogRead(A0);
 48  int y = analogRead(A1);
 49
 50  // Determine new direction based on joystick
 51  if (x > 600 && direction != 3) direction = 1;
 52  else if (x < 400 && direction != 1) direction = 3;
 53  else if (y > 600 && direction != 0) direction = 2;
 54  else if (y < 400 && direction != 2) direction = 0;
 55
 56  // Move snake
 57  moveSnake();
 58
 59  // Check for collision with food
 60  if (snake[0].x == food.x && snake[0].y == food.y) {
 61    snake[snakeLength] = snake[snakeLength - 1];  // Initialize the new segment
 62    snakeLength++;
 63    generateFood();
 64  }
 65
 66  // Check for collision with self
 67  for (int i = 1; i < snakeLength; i++) {
 68    if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
 69      // Reset game (or end game)
 70      snakeLength = 3;
 71      snake[0] = { 6, 4 };
 72      snake[1] = { 6, 5 };
 73      snake[2] = { 6, 6 };
 74      direction = 0;
 75      generateFood();
 76    }
 77  }
 78
 79  // Draw to LED matrix
 80  drawFrame();
 81
 82  // Delay to control speed
 83  delay(200);
 84}
 85
 86void moveSnake() {
 87  for (int i = snakeLength - 1; i > 0; i--) {
 88    snake[i] = snake[i - 1];
 89  }
 90
 91  // Move the head of the snake based on the direction
 92  switch (direction) {
 93    case 0:
 94      snake[0].y = (snake[0].y - 1 + 8) % 8;  // Wrap around at the top and bottom edges
 95      break;
 96    case 1:
 97      snake[0].x = (snake[0].x + 1) % 12;  // Wrap around at the right and left edges
 98      break;
 99    case 2:
100      snake[0].y = (snake[0].y + 1) % 8;  // Wrap around at the bottom and top edges
101      break;
102    case 3:
103      snake[0].x = (snake[0].x - 1 + 12) % 12;  // Wrap around at the left and right edges
104      break;
105  }
106}
107
108void generateFood() {
109  Point possibleLocations[8 * 12];
110  int idx = 0;
111
112  // Generate all possible locations for the food
113  for (int y = 0; y < 8; y++) {
114    for (int x = 0; x < 12; x++) {
115      bool overlap = false;
116
117      // Check for overlap with the snake
118      for (int i = 0; i < snakeLength; i++) {
119        if (snake[i].x == x && snake[i].y == y) {
120          overlap = true;
121          break;
122        }
123      }
124
125      if (!overlap) {
126        possibleLocations[idx++] = { x, y };
127      }
128    }
129  }
130
131  // Randomly choose a location for the food from the possible locations
132  int choice = random(0, idx);
133  food = possibleLocations[choice];
134}
135
136void drawFrame() {
137  // Clear frame
138  for (int y = 0; y < 8; y++) {
139    for (int x = 0; x < 12; x++) {
140      frame[y][x] = 0;
141    }
142  }
143
144  // Draw snake
145  for (int i = 0; i < snakeLength; i++) {
146    frame[snake[i].y][snake[i].x] = 1;
147  }
148
149  // Draw food
150  frame[food.y][food.x] = 1;
151
152  // Flatten frame array and load into LED matrix
153  int idx = 0;
154  for (int y = 0; y < 8; y++) {
155    for (int x = 0; x < 12; x++) {
156      flatFrame[idx++] = frame[y][x];
157    }
158  }
159  matrix.loadPixels(flatFrame, 8 * 12);
160  matrix.renderFrame(0);
161}

How it works?

Here’s a detailed explanation of the code:

  1. Variable Definition and Initialization

    Import the Arduino_LED_Matrix library for LED matrix operations. matrix is an instance of the LED matrix. frame and flatFrame are arrays used to store and process pixel information on the screen. The snake is represented as an array of Point structures, where each point has an x and y coordinate. food represents the position of the food. direction is the current movement direction of the snake.

  2. setup()

    Initialize the X and Y axes of the joystick as inputs. Start the LED matrix. Initialize the snake’s starting position in the center of the screen. Generate the initial position of the food randomly.

  3. loop()

    Determine the snake’s direction based on the readings from the joystick. Move the snake. Check if the snake’s head collides with the food. If it does, the snake grows, and new food is generated at a new location. Check if the snake collides with itself. If it does, reset the game. Draw the current game state (snake and food positions) on the LED matrix. Add a delay to control the game’s speed.

  4. moveSnake()

    Move each part of the snake to the position of the previous part, starting from the tail and moving to the head. Move the snake’s head based on its direction.

  5. generateFood()

    Generate all possible food positions. Check if each position overlaps with any part of the snake. If it doesn’t overlap, the position is considered a possible food location. Randomly select a possible food location.

  6. drawFrame()

    Clear the current frame. Draw the snake and food on the frame. Flatten the two-dimensional frame array into a one-dimensional array (flatFrame) and load it onto the LED matrix.