Building a Simple Snake Game with Pygame in Python

Kumuthu Athukorala
4 min readFeb 5, 2024

--

One of the most exciting milestones for any beginner in developing is creating their first game. It’s a fun way to apply the concepts you’ve learned and see them interactively come to life. Today, we’ll dive into creating a classic Snake game, using Python and the Pygame library. We’ll call it PySnake.

Following are the features of the game;

The snake is controlled using the W, A, S, and D keys for up, left, down, and right movements, respectively.

An apple appears randomly within the screen which the snake can eat to grow longer.

The game ends and resets if the snake hits the screen border or itself.

The player’s score is displayed on the screen, reflecting the length of the snake.

Setting the Stage

We’re using Pygame, a set of Python modules designed for writing video games. It provides us with the tools we need to create windowed applications, handle user input, and manage our game state.

import pygame

# Constants
SCREEN_WIDTH = 800
PIXEL_WIDTH = 50
SOUND = True

# Pygame setup
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_WIDTH))
clock = pygame.time.Clock()

The Snake and the Apple

The main characters in our game are the snake and the apple. The snake is represented as a list of rectangles, where each rectangle is a segment of the snake. The apple is also a rectangle, randomly placed within the screen bounds.

# Snake setup
snake_bit = pygame.rect.Rect([0, 0, PIXEL_WIDTH - 2, PIXEL_WIDTH - 2])
snake_bit.center = random_starting_position()
snake = [snake_bit.copy()]
snake_direction = (0, 0)
snake_length = 1

# Apple setup
apple = pygame.rect.Rect([0, 0, PIXEL_WIDTH - 2, PIXEL_WIDTH - 2])
apple.center = random_starting_position()

random_starting_position() function generates a random starting position for the snake and the apple within the screen. It returns a list of two random numbers, each representing the x and y coordinates.

def random_starting_position():
"""Generate a random starting position within the screen."""
random_range = (PIXEL_WIDTH // 2, SCREEN_WIDTH - PIXEL_WIDTH // 2, PIXEL_WIDTH)
return [random.randrange(*random_range), random.randrange(*random_range)]

The Game Loop

The heart of any game is its game loop. This is where we handle events, update the game state, and render the game to the screen.

This section contains the main logic of the game. It checks if the snake has hit the boundary or itself, in which case the game resets. If the snake has eaten an apple, the apple is moved to a new random position, and the length of the snake increases.

while running:
# Event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

# Game logic comes here

# Display update
pygame.display.flip()
clock.tick(10)

The game window is set up using Pygame, and rectangles are drawn to represent the snake and apple.

for snake_part in snake:
pygame.draw.rect(screen, "blue", snake_part)
pygame.draw.rect(screen, "red", apple)

The snake is controlled using the W, A, S, and D keys for up, left, down, and right movements.

keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
snake_direction = (0, -PIXEL_WIDTH)
if keys[pygame.K_s]:
snake_direction = (0, PIXEL_WIDTH)
if keys[pygame.K_a]:
snake_direction = (-PIXEL_WIDTH, 0)
if keys[pygame.K_d]:
snake_direction = (PIXEL_WIDTH, 0)

snake_bit.move_ip(snake_direction)
snake.append(snake_bit.copy())
snake = snake[-snake_length:]

If the snake goes out of bounds or collides with itself, the game resets. is_out_of_bound(rect) function checks if the snake is out of the screen bounds.

def is_out_of_bound(rect):
"""Check if a rectangle is out of the screen bounds."""
return rect.bottom > SCREEN_WIDTH or rect.top < 0 or rect.right > SCREEN_WIDTH or rect.left < 0
if is_out_of_bound(snake_bit) or snake_bit.collidelist(snake[:-1]) != -1:
SOUND = True
snake_length = 1
apple.center = random_starting_position()
snake_bit.center = random_starting_position()
snake = [snake_bit.copy()]

The snake grows in length when it consumes the apple.

if snake_bit.center == apple.center:
apple.center = random_starting_position()
snake_length += 1
snake.append(snake_bit.copy())

display_score(score) function displays the current score on the screen. It creates a text surface object, with the score and some additional text, and then it draws this text surface object (blit) onto the surface object (screen).

def display_score(score):
"""Display the current score on the screen."""
score_text = font.render(f'score: {score}', False, (64, 64, 64))
screen.blit(score_text, (20, 20))

display_score(snake_length)

Further background music is played when the game starts.

if SOUND:
pygame.mixer.music.play()
SOUND = False

The game loop runs continuously until the game ends, updating the game state and rendering the game to the screen.

Conclusion

Building PySnake is a fun and rewarding project that helps you understand the basics of game development with Python and Pygame. It’s a great starting point for anyone interested in game development, and it’s a project that you can easily expand on. So why not give it a try?

Happy coding!

--

--