Creating a Simple Snake Game in Python with Pygame

Adriel VinuyaAdriel Vinuya
4 min read

Introduction

In this tutorial, we will build a classic Snake game using Python and the Pygame library. The game involves controlling a snake to eat food and grow longer, while avoiding collisions with itself and the boundaries of the game screen.

Prerequisites

Before getting started, ensure you have Python installed on your computer along with the Pygame library. You can install Pygame using pip:

pip install pygame

Step-by-Step Guide

Setting up the Environment

Begin by importing the necessary modules and initializing Pygame:


import pygame
import sys
import random

pygame.init()

# Constants
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 400
GRID_SIZE = 20
GRID_WIDTH = SCREEN_WIDTH // GRID_SIZE
GRID_HEIGHT = SCREEN_HEIGHT // GRID_SIZE

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

# Create the screen
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Snake Game')

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

Defining the Snake and Food Classes

Define the Snake and Food classes along with helper functions for game logic:


class Snake:
    def __init__(self):
        self.body = [(GRID_WIDTH // 2, GRID_HEIGHT // 2)]
        self.direction = (1, 0)  # Initial direction: right

    def move(self, food):
        # Move the snake based on its current direction
        head_x, head_y = self.body[0]
        dx, dy = self.direction
        new_head = ((head_x + dx) % GRID_WIDTH, (head_y + dy) % GRID_HEIGHT)

        # Check for collisions with itself or boundaries
        if new_head in self.body[1:] or new_head[0] < 0 or new_head[0] >= GRID_WIDTH or new_head[1] < 0 or new_head[1] >= GRID_HEIGHT:
            return False

        # Insert new head position and check for food collision
        self.body.insert(0, new_head)
        if new_head == food.position:
            food.spawn()  # Respawn food at a new position
        else:
            self.body.pop()  # Remove the tail segment if no food eaten
        return True

    def draw(self):
        # Draw the snake on the screen
        for segment in self.body:
            pygame.draw.rect(screen, GREEN, (segment[0] * GRID_SIZE, segment[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE))

    def change_direction(self, direction):
        # Change the snake's direction, ensuring it doesn't reverse
        if (direction[0] * -1, direction[1] * -1) != self.direction:
            self.direction = direction


class Food:
    def __init__(self):
        # Initialize food at a random position within the grid
        self.position = (random.randint(0, GRID_WIDTH - 1), random.randint(0, GRID_HEIGHT - 1))

    def spawn(self):
        # Respawn food at a new random position within the grid
        self.position = (random.randint(0, GRID_WIDTH - 1), random.randint(0, GRID_HEIGHT - 1))

    def draw(self):
        # Draw the food on the screen
        pygame.draw.rect(screen, RED, (self.position[0] * GRID_SIZE, self.position[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE))

Game Loop and Event Handling

Implement the main game loop and handle events such as key presses for changing the snake's direction:


def main():
    snake = Snake()
    food = Food()
    running = True

    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    snake.change_direction((0, -1))  # Move snake up
                elif event.key == pygame.K_DOWN:
                    snake.change_direction((0, 1))   # Move snake down
                elif event.key == pygame.K_LEFT:
                    snake.change_direction((-1, 0))  # Move snake left
                elif event.key == pygame.K_RIGHT:
                    snake.change_direction((1, 0))   # Move snake right

        screen.fill(WHITE)  # Clear the screen with white
        draw_grid()         # Draw grid lines

        snake_move_result = snake.move(food)  # Move snake and handle collisions
        if not snake_move_result:
            running = False  # End game if snake collides

        snake.draw()  # Draw the snake on the screen
        food.draw()   # Draw the food on the screen

        pygame.display.flip()  # Update the display
        clock.tick(10)         # Control the game speed

    pygame.quit()  # Quit Pygame
    sys.exit()     # Exit the program

if __name__ == '__main__':
    main()

Explanation

  • Initialization: Set up the Pygame environment, define constants, and create the game screen.

  • Snake and Food Classes: Define the Snake and Food classes with methods for movement, drawing, and collision handling.

  • Game Loop: Implement the main loop where user input is processed, the game state is updated (snake movement and food spawning), and the screen is refreshed.

  • Event Handling: Manage events such as key presses to change the snake's direction.

  • Drawing: Use Pygame's drawing functions to visually represent the snake and food on the screen.

Conclusion

You’ve now successfully created a simple Snake game in Python using Pygame! This tutorial covered essential aspects such as game initialization, class design for game objects, event handling, and drawing on the screen. Feel free to expand this game by adding features like score tracking, increasing difficulty levels, or implementing more complex game mechanics. Enjoy coding and exploring the world of game development with Python!

0
Subscribe to my newsletter

Read articles from Adriel Vinuya directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Adriel Vinuya
Adriel Vinuya

I specialize in technical writing with a focus on Python programming and game development using Pygame. My work primarily involves creating clear and concise guides, tutorials, and documentation that help beginners and enthusiasts alike learn and explore Python's capabilities in game development. With a passion for coding and a knack for explaining complex concepts in a straightforward manner, I enjoy empowering others to dive into the exciting world of game development using Python and Pygame.