Snake Game Tutorial using Python and Pygame

Posted by Marta on November 22, 2021 Viewed 8497 times

Card image cap

In this tutorial you will learn to program the snake game in python using the Pygame library. You will build a game like the one you can see below:

I have simplified the game and break down the code in small functions so this tutorial is easy to follow. Additionally we build the game step by step starting with the simplest logic and adding complexity gradually.

Before We Start

Before starting, make sure you have Python 3 installed, and the Pygame library. You can install the library by running the following command from your terminal:

>>> pip install pygame

You can double check the library is installed by executing the following:

>>> pip freeze

This command will list all Python library installed, therefore if Pygame is correctly installed, it should be in the list.

Watch the tutorial on Youtube

#1: Create Game Window

In this step we are gonna create the game window for our snake game using Python and some Pygame methods.

To do so, create a file named snake_game.py and place the following code inside:

import pygame

SNAKE_SQUARE_DIMENSIONS = 10

TOTAL_COLS = 60
TOTAL_ROWS = 40
surface_width = TOTAL_COLS * SNAKE_SQUARE_DIMENSIONS # 60 columns
surface_height = TOTAL_ROWS * SNAKE_SQUARE_DIMENSIONS # 40 rows

pygame.init()

surface = pygame.display.set_mode((surface_width, surface_height))
pygame.display.set_caption('SNAKE GAME')

clock = pygame.time.Clock()


def gameLoop():
    game_over = False

    while not game_over:

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

        surface.fill((0,0,0)

        pygame.display.update()

        clock.tick(15)

    pygame.quit()

gameLoop()
pygame.quit()                     

After running this script a black window should pop up with the title “Snake Game”. Perfect, the window of our python snake game using pygame is ready.

#2: Moving a Single Block around the Window

Next step we will draw the snake head. This basically means drawing a green square approximately in the middle of the black canvas.

We will represent the game board as a matrix. The main reason is that it’s much easier to deal with rows and columns in a matrix, than dealing directly with the pixels.

To draw a square in the middle, firstly we will define the cell where we want to place the same, which is gonna be row 20 and column 30. This means we will add the following at line 20 of the previous script:

    # Snake Starting point
    x1 = 30
    y1 = 20

Then I will add a function to draw an square of dimensions 10×10 in given cell of the matrix:

def draw_single_block(snake_block,color):
    vertical_position = snake_block[0] * 10
    horizontal_position = snake_block[1] * 10
    pygame.draw.rect(surface, color, (vertical_position, horizontal_position, 10, 10)) # origin position and dimensions

The key line in the above snippet is line #4 which will draw the rectangle in the canvas. The first parameter is the window surface where the rectangle will be drawn. Then the rectangle colour, and last parameter is the rectangle dimensions which include the origin( pixel distance from the left, pixel distance from the top, width and height of the rectangle. See Documentation here.

pygame.draw.rect(surface, color, (vertical_position, horizontal_position, 10, 10))

After adding the new function to your script, we will need to call it from the gameLoop to draw and square every time the canvas gets updated. Therefore we need to add the following at line 28 of the previous script:

 draw_single_block([x1,y1],(0, 255, 0))

Once the square is displayed in the canvas, next thing we should do is moving the square as we press the arrow keys. For this purpose, We will introduce the variable direction, which will save the direction in which the square is moving. The possible values for this variable are UP, DOWN, LEFT and RIGHT.

So inside the gameLoop function, before the while loop we will add the direction variable:

    direction = "UP"

And we will add a function to pick up when a key is pressed, and change direction according to the arrow key press. The function will look as follows:

def detect_direction(direction, event):
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT:
            return "LEFT"
        elif event.key == pygame.K_RIGHT:
            return "RIGHT"
        elif event.key == pygame.K_UP:
            return "UP"
        elif event.key == pygame.K_DOWN:
            return "DOWN"
    return direction

And after adding the function, we will call it from inside the while loop. Specifically we will the following code piece at line 26, within the for loop:

direction = detect_direction(direction, event)

So now we know the direction in which the square block should move, so let’s move the square. All necessary to move the block is drawing it in the next matrix cell. Meaning updating the matrix cell where the block is gonna be drawn is enough. So let’s add a function to update the block matrix position, based on the current block position and the direction:

def move_block(col, row , direction):
    if direction == "LEFT":
        col = col -1
    if direction == "RIGHT":
        col = col +1
    if direction == "UP":
        row = row - 1
    if direction == "DOWN":
        row = row + 1

    return [col,row]

This function will return the new position where the block should be placed. So after adding the function to our script, next we will need to use it from the game loop. How? by adding the following line inside the gameLoop function right after the for loop:

x1,y1 = move_block(x1,y1,direction)

This means in every loop iteration, the block will be drawn in the next cell, creating the movement illusion.

CHECK THE SOURCE CODE HERE

OUTPUT:

#3: Build an Snake with Several Blocks

So far we have seen how to create the game window, and learn how to move a snake made up of one single block. Next I will show you how to expand our snake so it has several blocks.

Our snake is gonna be four blocks long.To achieve this, we are gonna use a list to keep track of the position of the different blocks. Therefore you will need to add the following to your script, inside the gameLoop function, before the while loop:

snake_list = [[30,23],[30,22],[30,21],[30,20]]

These are the cells where the snake will start. Next we need to update our code, to draw a square in every cell. See below the new function that will draw all blocks. This function will reuse the function draw_single_block() created earlier.

def draw_snake(snake_list):
    for snake_block in snake_list:
        draw_single_block(snake_block,green)

After adding this function, we need to call it from the game loop. To do so, you need to replace the line to draw a single block:

draw_single_block([x1,y1],green)

By:

draw_snake(snake_list)

At this point the snake and its four blocks will show up, however the snake doesn’t move. To fix that, let’s add another small code snippet inside the while loop, after filling the canvas with black.

snake_list.append([x1,y1])
if(len(snake_list)>=4):
	del snake_list[0]

The code above will make the snake move, by adding a new block in one side, and removing one block on the other side, over and over, creating the moving effect.

CHECK THE SOURCE CODE HERE

OUTPUT:

#4: Add Food and Make the Snake Grow

We got our snake moving. Next step is getting the snake to grow as it eats food. In this instance, the food blocks will be red.

To draw a food block in our canvas we need to select a random cell and then draw a red square inside. See below the function to pick a random cell to place the food:

import random
...
def create_food_block():
    foodx = round(random.randrange(0, 59))
    foody = round(random.randrange(0, 39))
    return [foodx,foody]

After adding this function, we will need to call it from within the game loop. Therefore I will add the following line, inside the gameLoop function, before the while loop:

food_block = create_food_block()

This food variable will save the position of the food piece. Next step is drawing the food block. To do so, we should add add the following line right after surface.fill(black):

draw_single_block(food_block,(213, 50, 80))

At this point you can run the Python Pygame snake game script again. If everything went well, you should see the food piece somewhere in the canvas, however when the snake reaches the food nothing. The food piece is not reallocated.

To fix that, we should add the following code snippet, right after pygame.display.update():

if x1 == food_block[0] and y1 == food_block[1]:
	food_block = create_food_block()
    snake_length += 1

The code above will do three things. Check if the snake reached the food and if so it will eat, which means the snake will grow, and also we will place the food piece in a new cell.

And since we introduce the new variable snake_length, you will need to add the following as well:

snake_list = [[30,21],[30,20]] 
snake_length = 2

The above will set the initial size of the snake to 2 blocks, which means replacing the snake_list with a list of only two blocks, and add the new variable snake_length.

And last bit. In the previous part we added the below piece of code to make the snake move keeping always the same size, which was 4.

snake_list.append([x1,y1])
if(len(snake_list)>=4):
	del snake_list[0]

Now because the size will vary as the snake eats food, we will replace the 4 with the variable snake_length as follows:

snake_list.append([x1,y1])
if(len(snake_list)>=snake_length):
	del snake_list[0]

OUTPUT:

#5: Game Over when Hitting the Game Boundaries

Finally the last step. Our snake game is nearly completed. All left to do is slightly modifying our script so the game ends if the snake hits the window boundaries.

To achieve this, we will check of the snake head, which position is saved in x1 and y1 got out of the matrix boundaries, and if you will flag the game as over.

 if x1 >= TOTAL_COLS or x1 < 0 or y1 >= TOTAL_ROWS or y1 < 0:
  	game_over = True

Plus after the while loop, we will add the following code to display a message offering the user to start again.

while not game_close:
	surface.fill(black)
    draw_message("Please press Enter to play again, or Q to QUIT",green)
    pygame.display.update()

    for event in pygame.event.get():
    	if event.type == pygame.KEYDOWN:
        	if event.key == pygame.K_q:
            	game_close = True
            else:
            	gameLoop()

Note for this to work you will need to add game_close = False at the start of the gameLoop function.

CHECK THE SOURCE CODE HERE

OUTPUT:

Conclusion

To summarise, in this tutorial I have covered how you can create the snake game in python using the Pygame library. We started creating a single block snake. Then we expand it to four blocks, and finally we make the snake grow as it eats food.

I hope you find the article useful and thanks for reading and supporting this blog. Happy coding! 🙂

Project-Based Programming Introduction

Steady pace book with lots of worked examples. Starting with the basics, and moving to projects, data visualisation, and web applications

100% Recommended book for Java Beginners

Unique lay-out and teaching programming style helping new concepts stick in your memory

90 Specific Ways to Write Better Python

Great guide for those who want to improve their skills when writing python code. Easy to understand. Many practical examples

Grow Your Java skills as a developer

Perfect Boook for anyone who has an alright knowledge of Java and wants to take it to the next level.

Write Code as a Professional Developer

Excellent read for anyone who already know how to program and want to learn Best Practices

Every Developer should read this

Perfect book for anyone transitioning into the mid/mid-senior developer level

Great preparation for interviews

Great book and probably the best way to practice for interview. Some really good information on how to perform an interview. Code Example in Java