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.
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.
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.
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.
Pause Functionality:
A button on the joystick allows pausing and resuming the game.
Make sure that the SMD is powered and all connections are correct
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
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 # ID of the joystick module
button_id = 5 # ID of the button module
rgb_led_id = 5 # ID of the RGB LED module
def 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
SerialPort = USB_Port()
if not SerialPort:
raise Exception("No compatible USB port found. Please check your connection.")
master = Master(SerialPort, baudrate)
master.attach(Red(ID))
print("Connected Modules:", master.scan_modules(ID))
# Initialize Pygame
pygame.init()
# Define colors
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
# Set display dimensions
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
# 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.
Args:
snake_block (int): The size of each block in the snake.
snake_list (list): List of snake body parts' positions.
"""
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.
Args:
msg (str): The message to display.
color (tuple): The color of the message text.
y_displace (int): Vertical displacement of the message.
"""
mesg = font_style.render(msg, True, color)
display.blit(mesg, [width / 6, height / 3 + y_displace])
def game_loop():
"""
Main game loop for the Snake Game.
"""
game_over = False
close_game = False
paused = False # Pause state
# 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(blue)
message("You Lost! Press Q to Quit or C to Play Again", red)
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()
# Check for button input to pause the game
button_pressed = master.get_button(ID, button_id)
if button_pressed == 1:
paused = not paused
time.sleep(0.5) # Debounce delay
while paused:
# Display paused message
display.fill(blue)
message("Game Paused. Press Button to Resume", yellow)
pygame.display.update()
# Wait for button press to resume
button_pressed = master.get_button(ID, button_id)
if button_pressed == 1:
paused = False
time.sleep(0.5) # Debounce delay
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
# LED feedback
if x1_change != 0 or y1_change != 0:
master.set_rgb(ID, rgb_led_id, 0, 255, 0) # Green LED for movement
else:
master.set_rgb(ID, rgb_led_id, 255, 0, 0) # Red LED for no movement
# Check for collision with boundaries
if x1 >= width or x1 < 0 or y1 >= height or y1 < 0:
close_game = True
master.set_rgb(ID, rgb_led_id, 255, 0, 0) # Red LED for 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]
# Check if the snake collides with itself
for block in snake_list[:-1]:
if block == snake_head:
close_game = True
master.set_rgb(ID, rgb_led_id, 255, 0, 0) # Red LED for game over
draw_snake(snake_block, snake_list)
display_score(snake_length - 1)
# Check if food is eaten
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_rgb(ID, rgb_led_id, 0, 0, 255) # Blue LED for eating
time.sleep(0.2) # Delay for visual effect
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 SMDjoystick to control the classic Snake game, providing a hardware-based gaming experience.