> For the complete documentation index, see [llms.txt](https://docs.acrome.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.acrome.net/smd-applications/interactive/snake-game-with-joystick.md).

# Snake Game With Joystick

This code integrates a [joystick ](/electronics/add-on-modules/joystick-module.md)with a simple Snake Game using the pygame library. It also utilizes the [ACROME SMD](/electronics/smd-red.md) platform to receive [joystick](/electronics/add-on-modules/joystick-module.md) inputs and provide feedback, like turning on a [buzzer](/electronics/add-on-modules/buzzer-module.md) when food is consumed.

**About Tools and Materials:**

[SMD Red](https://docs.acrome.net/electronics/smd-red) ([Purchase Here](https://www.robotshop.com/products/acrome-smd-red-smart-brushed-motor-driver-with-speed-position-and-current-control-modes))

[SMD USB Gateway](https://docs.acrome.net/electronics/gateway-modules/usb-gateway-module) ([Purchase Here](https://www.robotshop.com/products/acrome-usb-gateway-module-acrome-smd-products))

[Buzzer Module](/electronics/add-on-modules/buzzer-module.md) ([Purchase Here](https://www.robotshop.com/products/acrome-buzzer-sound-add-on-module-acrome-smd-products))

[Joystick Module](/electronics/add-on-modules/joystick-module.md) ([Purchase Here](https://www.robotshop.com/products/acrome-joystick-2-axis-add-on-module-acrome-smd-products))

## **Step 1: Hardware & Software Overview**

**Key Component:**

1. [Buzzer Module](/electronics/add-on-modules/buzzer-module.md)\
   Every time the snake eats the food[ Buzzer Module](/electronics/add-on-modules/buzzer-module.md) makes a sound.
2. [Joystick Module](/electronics/add-on-modules/joystick-module.md)\
   Handles snake movement.
3. pygame\
   Handles the graphics and user interface for the snake game. It displays the snake, food, score, and manages input events.
4. [ACROME SMD](/electronics/smd-red.md)\
   Communicates with the [joystick](/electronics/add-on-modules/joystick-module.md) and handles[ joystick ](/electronics/add-on-modules/joystick-module.md)input as well as [buzzer](/electronics/add-on-modules/buzzer-module.md) feedback.

**Project Key Features:**

1. Joystick Input: \
   The joystick connected via the ACROME SMD platform is used to control the snake's direction. The snake moves left, right, up, or down based on the joystick's X and Y-axis values. A button on the joystick can be used to pause and resume the game.
2. Start and Game Over Menus: \
   The game starts with a simple menu where you can choose to start the game or quit. If the game ends (snake hits a wall or itself), a game over menu is displayed, with options to retry or quit.
3. Game Logic: \
   The snake grows when it eats food, and the length is increased. The snake's movement speed is fixed but can be controlled by the joystick. A buzzer sound is triggered when the snake eats the food.
4. Pause Functionality: \
   A button on the joystick allows pausing and resuming the game.

## **Step 2: Assemble**

**Getting Started**

1. **Hardware Setup**
   * Connect the SMD to the PC or Arduino board using [USB Gateway Module](https://docs.acrome.net/electronics/gateway-modules/usb-gateway-module).
   * Connect the [Buzzer Module](/electronics/add-on-modules/buzzer-module.md) and the [Joystick Module](/electronics/add-on-modules/joystick-module.md) to the SMD using an RJ-45 cable.
   * Make sure that the SMD is powered and all connections are correct

#### Project Wiring Diagram

<figure><img src="/files/F0UzNskSCmUJQi3lf3eI" alt=""><figcaption></figcaption></figure>

## Step 3: Run & Test

Start Menu: \
When the program is run, the start menu is displayed. The user can click on "Start" to begin the game or "Quit" to exit.

Snake Movement: \
During the game, the [joystick's ](/electronics/add-on-modules/joystick-module.md)position controls the snake's movement. Moving the [joystick ](/electronics/add-on-modules/joystick-module.md)in any direction updates the snake’s position.

Eating Food: \
When the snake's head collides with the food, the snake grows, and a [buzzer ](/electronics/add-on-modules/buzzer-module.md)sound is triggered.

Game Over: \
The game ends when the snake hits the boundaries or itself. A "Game Over" menu is displayed with options to retry or quit.

Pausing the Game: \
The game can be paused and resumed using the [joystick's ](/electronics/add-on-modules/joystick-module.md)button<br>

## Codes

{% tabs %}
{% tab title="Python Code" %}
{% code lineNumbers="true" %}

```python
import pygame
import time
import random
from smd.red import *
from serial.tools.list_ports import comports
from platform import system

# SMD Module Settings
BAUDRATE = 115200       # Baud rate for communication
ID = 0                  # SMD module ID
JOYSTICK_ID = 5         # Joystick module ID
BUZZER_ID = 5           # Buzzer module ID

def detect_usb_port():
    """
    Scans and identifies a compatible USB port for the current operating system.

    Returns:
        str: The detected USB port or None if no suitable port is found.
    """
    ports = list(comports())
    usb_names = {
        "Windows": ["USB Serial Port"],
        "Linux": ["/dev/ttyUSB"],
        "Darwin": [
            "/dev/tty.usbserial", "/dev/tty.usbmodem",
            "/dev/tty.SLAB_USBtoUART", "/dev/tty.wchusbserial",
            "/dev/cu.usbserial", "/dev/cu.usbmodem",
            "/dev/cu.SLAB_USBtoUART", "/dev/cu.wchusbserial",
        ]
    }

    os_name = system()
    if ports:
        for port in ports:
            if any(name in port.device or name in port.description for name in usb_names.get(os_name, [])):
                return port.device
        print("No suitable USB device found.")
    else:
        print("No ports detected!")
    return None


# Initialize SMD module
serial_port = detect_usb_port()
if not serial_port:
    raise Exception("No compatible USB port found. Please check your connection.")

master = Master(serial_port, BAUDRATE)
master.attach(Red(ID))
print("Connected Modules:", master.scan_modules(ID))

# Initialize Pygame
pygame.init()

# Display Settings
WIDTH, HEIGHT = 600, 400
display = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Snake Game')

# Clock to control game speed
clock = pygame.time.Clock()

# Snake Settings
SNAKE_BLOCK = 10
SNAKE_SPEED = 15

# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (213, 50, 80)
GREEN = (0, 255, 0)

# Font styles
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)


def display_score(score):
    """ Displays the player's score on the screen. """
    value = score_font.render("Score: " + str(score), True, BLACK)
    display.blit(value, [0, 0])


def draw_snake(snake_block, snake_list):
    """ Draws the snake on the screen. """
    for x in snake_list:
        pygame.draw.rect(display, BLACK, [x[0], x[1], snake_block, snake_block])


def message(msg, color, y_displace=0):
    """ Displays a message on the screen. """
    mesg = font_style.render(msg, True, color)
    display.blit(mesg, [WIDTH / 6, HEIGHT / 3 + y_displace])


def buzzer_alert():
    """ Plays a short buzzer sound for feedback. """
    master.set_buzzer(ID, BUZZER_ID, 500, 100)  # 500Hz frequency, 100ms duration


def game_loop():
    """ Main game loop for Snake Game. """
    game_over = False
    close_game = False

    # Initial snake position and movement
    x1, y1 = WIDTH // 2, HEIGHT // 2
    x1_change, y1_change = 0, 0

    # Snake body and food
    snake_list = []
    snake_length = 1
    food_x = round(random.randrange(0, WIDTH - SNAKE_BLOCK) / 10.0) * 10.0
    food_y = round(random.randrange(0, HEIGHT - SNAKE_BLOCK) / 10.0) * 10.0

    while not game_over:
        while close_game:
            display.fill(RED)
            message("Game Over! Press Q to Quit or C to Restart", WHITE)
            display_score(snake_length - 1)
            pygame.display.update()

            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        game_over = True
                        close_game = False
                    if event.key == pygame.K_c:
                        game_loop()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True

        # Joystick control
        joystick = master.get_joystick(ID, JOYSTICK_ID)
        if joystick:
            x_axis, y_axis = joystick[0], joystick[1]
            if x_axis < -50:  # Left
                x1_change, y1_change = -SNAKE_BLOCK, 0
            elif x_axis > 50:  # Right
                x1_change, y1_change = SNAKE_BLOCK, 0
            elif y_axis < -50:  # Up
                x1_change, y1_change = 0, -SNAKE_BLOCK
            elif y_axis > 50:  # Down
                x1_change, y1_change = 0, SNAKE_BLOCK

        x1 += x1_change
        y1 += y1_change

        # Collision with boundaries
        if x1 >= WIDTH or x1 < 0 or y1 >= HEIGHT or y1 < 0:
            close_game = True
            buzzer_alert()  # Play buzzer when game over

        display.fill(WHITE)
        pygame.draw.rect(display, GREEN, [food_x, food_y, SNAKE_BLOCK, SNAKE_BLOCK])

        # Update snake position
        snake_head = [x1, y1]
        snake_list.append(snake_head)
        if len(snake_list) > snake_length:
            del snake_list[0]

        # Collision with itself
        for block in snake_list[:-1]:
            if block == snake_head:
                close_game = True
                buzzer_alert()  # Play buzzer when game over

        draw_snake(SNAKE_BLOCK, snake_list)
        display_score(snake_length - 1)

        # Food collision
        if x1 == food_x and y1 == food_y:
            food_x = round(random.randrange(0, WIDTH - SNAKE_BLOCK) / 10.0) * 10.0
            food_y = round(random.randrange(0, HEIGHT - SNAKE_BLOCK) / 10.0) * 10.0
            snake_length += 1
            master.set_buzzer(ID, BUZZER_ID, 1000, 100)  # Buzzer beep for eating food

        pygame.display.update()
        clock.tick(SNAKE_SPEED)

    pygame.quit()
    quit()


# Start the game loop
game_loop()
```

{% endcode %}
{% endtab %}
{% endtabs %}

**Conclusion:** \
This is a fun and interactive way to use the [ACROME SMD](/electronics/smd-red.md) [joystick ](/electronics/add-on-modules/joystick-module.md)to control the classic Snake game, providing a hardware-based gaming experience.
