Snake Game With Joystick

This code integrates a joystick with a simple Snake Game using the pygame library. It also utilizes the ACROME SMD platform to receive joystick inputs and provide feedback, like turning on a buzzer when food is consumed.

About Tools and Materials:

SMD Red (Purchase Here)

SMD USB Gateway (Purchase Here)

Buzzer Module (Purchase Here)

Joystick Module (Purchase Here)

Step 1: Hardware & Software Overview

Key Component:

  1. Buzzer Module Every time the snake eats the food Buzzer Module makes a sound.

  2. Joystick Module 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 Communicates with the joystick and handles joystick input as well as buzzer 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

Project Wiring Diagram

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 position controls the snake's movement. Moving the joystick 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 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 button

Codes

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()

Conclusion: This is a fun and interactive way to use the ACROME SMD joystick to control the classic Snake game, providing a hardware-based gaming experience.

Last updated