Build a Snake Game with Python
Tags: python, gamedev, programming
Published: 2021-01-03 07:07:42

Hello readers, let’s build a game using Python. Yes, you heard that right! We will be building a simple snake game using the pygame library.

Remember the old days, when everyone used to play the iconic snake game. Let’s revive those old days and build one on our own! So, in this tutorial, we will be building that iconic game.

So, let’s start building our game. We will do it step by step to get a clear understanding of every part of the game and what purpose it has in our game! So, let’s begin:

###Importing the libraries

First, of all, we need to import the libraries into our code which will be used to build the game. We will need the below-mentioned libraries to build and run our game.

```py
import pygame
import time
import random
```

**pygame:** This library will help us get all the graphical components to build the game.

**random:** This library will help us in spawning the food at random locations in the game.

**time:** This helps us with time-related functionalities in the game, as the speed of the snake.

###Starting the game and Setting the Graphics

Now, let’s begin building the actual part of the game. We will first initialise the game to have a window with us in which the game will be played.

```py
pygame.init()
```

Then we would love to define the colours we would be using in the game with the help of RGB notations. Get the RGB codes from the internet and put these as co-ordinates for the colour variables.

We have defined 6 colours in our game but you are free to use any colour of your choice. Make sure the colour combinations are good for playing the game.

```py
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
```

Next, we should define the size of the display in which our game would be running. So, in this case, we would define the height to be 600px and width to be 800px.

```py
width = 800
height = 600
```

Next, we will set our display with the defined width and height variables as input and we would describe the name of the game to be displayed as a caption for our game.
```py
dis = pygame.display.set_mode((width, height))
pygame.display.set_caption(‘Shubham Snake Game’)
```

###Defining the variables being used in the Game

Now, we will initialize our clock variable which will make use of the time package which we imported earlier. This variable ‘clock’ will take care of all time-related queries in our complete code.
```py
clock = pygame.time.Clock()
```
Now, let’s define the speed of our snake and also the size of the snake’s block i.e. the width of the snake. This is purely based on user choice and I have also chosen some numbers which I felt like a good fit for the game.
```py
snake_block = 10
snake_speed = 12
```
Next, we describe the font size and font style for score display and for the display of other information such as to notify that you lost the game or you want to play again.
```py
font_style = pygame.font.SysFont(“bahnschrift”, 25)
score_font = pygame.font.SysFont(“comicsansms”, 35)
```

###Defining helper functions

Here, we need to define three helper functions for the following purposes:- for displaying the score, for handling the snake and for handling the display of other relevant information in the game respectively.

So, at first, we define the function to help us with the score display. We will define the position where it would be displayed in the game and how will it render the score.

The below function takes in the score as a parameter which it displays. We will calculate the score later on in our program.
```py
def Your_score(score):
    value = score_font.render("Your Score: " + str(score), True, yellow)
    dis.blit(value, [0, 0]
```

Next, we will be defining our snake. Without the snake, our game has no significance. So, let’s make the most important part of our game, the snake. We will define the colour and position of the snake and its size i.e. *snake_block*.

The function below takes snake_block and snake_list as an input. We will be defining the snake_list after on in our program. So, don’t worry if you do not get anything properly now.
```py
def our_snake(snake_block, snake_list):
 for x in snake_list:
 pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
```
Next and our last helper function would be to display any sort of message we need to show to the user playing our game.

This helper function takes the msg and colour as an input parameter. We will set the font and then display the message in the required colour. We will need to specify the position where the message will be displayed in the game display.
```py
def message(msg, colour):
 mesg = font_style.render(msg, True, colour)
 dis.blit(mesg, [width / 6, height / 3])
```

###Building the Game Loop
Now, we start building out the components of the game which will make it run and respond to user inputs through the keyboard.
We start by defining two boolean variables: *game_over* and *game_close*. They will describe the states of the game.

The first one will tell the game whether it’s over or not. The next variable defines whether the game is closed and we need to play again or not. We define both as false.
```py
game_over = False
game_close = False
```
At the next step, we aim to define the other variables we would need in the game.

We will be defining *x1* and *y1* to denote the position of the snake in our game. We initialize them width/2 and height/2 respectively. Also, we will be defining the variables *x1_change* and *y1_change* which will be used to denote the changes in the position of the snake based on the input provided by the user.
```py
x1 = width / 2
y1 = height / 2
 
x1_change = 0
y1_change = 0
```
Also, we need to define the *snake_List* and snake_length variables to store all the head positions of the snake and the length of the snake respectively.
```py
snake_List = []
snake_length = 1
```
We also need to initialize the position where the food will spawn in our game each time after it is eaten by the snake. We will make use of the random library to help us in determining the position for the food.
```py
foodx = round(random.randrange(0, width — snake_block) / 10.0) * 10.0
foody = round(random.randrange(0, height — snake_block) / 10.0) * 10.0
```
Next, we would start a loop that would run until game_over turns to be True.

Inside that loop, we would first define the instructions to be performed in case the game_close variable is True.

Below is the code which would help us tackle this situation when game_close is equal to True.
```py
while game_close == True:
 dis.fill(blue)
 message(“Oops! Your snake died! Press P to play again or Q to quit”, red)
 Your_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
       game_close = False
     if event.key == pygame.K_p:
       gameLoop()
```
As you can see above, we have defined many things. We fill the display with Blue colour (you can surely choose yours). We then display a message showing that the person lost the game and we should ask whether the person wants to play it again or quit the game.

We also display the user’s score equal to the length of the snake minus 1. We update score by 1 each time our snake eats food.
Now, for taking user input regarding whether he wants to play again or quit it, we define a for-loop. As we asked the user for input regarding his decision we define our possibilities for the input.

If the user inputs a ‘p’ then we will just continue our game loop. If the user inputs ‘q’ then we need to quit the game.

Now, after handling the condition of game_close, we would next define all the required steps which will allow our snake to move by the user’s input. We will accept both W, A, S, D and the up, down, left and right key combos for playing the game. You are free to choose your choice of keys to play the game.

```py
for event in pygame.event.get():
 if event.type == pygame.QUIT:
   game_over = True
 if event.type == pygame.KEYDOWN:
   if event.key == pygame.K_LEFT or event.key == pygame.K_a:
     x1_change = -snake_block
     y1_change = 0
   elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
     x1_change = snake_block
     y1_change = 0
   elif event.key == pygame.K_UP or event.key == pygame.K_w:
     y1_change = -snake_block
     x1_change = 0
   elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
     y1_change = snake_block
     x1_change = 0
```

In the above code, we change the values of *x1_change* and *y1_change* according to inputs provided by the user. Also, we quit the game if the user wants to quit the game.

Next, we would define the condition for losing the game. Also, we update the values of x1 and y1 with help of x1_change and y1_change. We also fill the entire display with blue colour and we draw the snake and food by passing in the position of their appearance in the display.
```py
 if x1 >= width or x1 < 0 or y1 >= height or y1 < 0:
    game_close = True
 x1 += x1_change
 y1 += y1_change
 dis.fill(blue)
 pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
```
Next, we define a list known as snake_Head which will store the values of the head of the snake after each iteration. We append the values of x1 and y1 to it. Then, we append that snake_Head to the snake_List.

Then we check the condition check whether the length of the snake_List is greater than snake_length. If yes, delete the first element in the snake_List.

Then, we check whether that current snake_Head is equal to any of the elements of snake_List except the one which is added newly i.e. the snake_Head being checked. If yes, then we close the game and the player loses.

This is because the occurrence of snake_Head in snake_List means it has been added to the snake_List before and finding the same value again signifies that snake bites itself. So, the player should lose at that moment.

Then we call the function our_snake and Your_score (defined earlier) and pass the required parameters to these functions to display the updated snake and the score of the player.
```py
 snake_Head = []
 snake_Head.append(x1)
 snake_Head.append(y1)
 snake_List.append(snake_Head)
 if len(snake_List) > snake_length:
   del snake_List[0]
 
 for x in snake_List[:-1]:
   if x == snake_Head:
     game_close = True
 
 our_snake(snake_block, snake_List)
 Your_score(snake_length — 1)
 
 pygame.display.update()
```

Next, we will form a new food once the snake has eaten the previous one. So, for doing this, we need to find a new random position in the display to spawn the food. Also, we need to increase the length of the snake by 1 since it just ate the food.

Next, we give the snake speed as a parameter to the clock.tick which is to run the game loop.

```py
if x1 == foodx and y1 == foody:
  foodx = round(random.randrange(0, width — snake_block) / 10.0) * 10.0
  foody = round(random.randrange(0, height — snake_block) / 10.0) * 10.0
  snake_length += 1
 
clock.tick(snake_speed)
```

Our game is almost finished by now. One last step, we need to quit the game and call the game loop again.
```py
  pygame.quit()
  quit()
gameLoop()
```

So, we have completed our snake game. Here’s the complete code for the snake game:

```py
import pygame
import time
import random
 
pygame.init()
 
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
 
dis_width = 800
dis_height = 600
 
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('Shubham Snake Game')
 
clock = pygame.time.Clock()
 
snake_block = 10
snake_speed = 15

font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)
 
def Your_score(score):
    value = score_font.render("Your Score: " + str(score), True, yellow)
    dis.blit(value, [0, 0])
 
def our_snake(snake_block, snake_list):
    for x in snake_list:
        pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
 
def message(msg, color):
    mesg = font_style.render(msg, True, color)
    dis.blit(mesg, [dis_width / 6, dis_height / 3])
 
def gameLoop():
    game_over = False
    game_close = False
 
    x1 = dis_width / 2
    y1 = dis_height / 2
 
    x1_change = 0
    y1_change = 0
 
    snake_List = []
    Length_of_snake = 1
 
    foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
    foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
 
    while not game_over:
 
        while game_close == True:
            dis.fill(blue)
            message("You Lost! Press C-Play Again or Q-Quit", red)
            Your_score(Length_of_snake - 1)
            pygame.display.update()
 
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        game_over = True
                        game_close = False
                    if event.key == pygame.K_c:
                        gameLoop()
 
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x1_change = -snake_block
                    y1_change = 0
                elif event.key == pygame.K_RIGHT:
                    x1_change = snake_block
                    y1_change = 0
                elif event.key == pygame.K_UP:
                    y1_change = -snake_block
                    x1_change = 0
                elif event.key == pygame.K_DOWN:
                    y1_change = snake_block
                    x1_change = 0
 
        if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
            game_close = True
        x1 += x1_change
        y1 += y1_change
        dis.fill(blue)
        pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
        snake_Head = []
        snake_Head.append(x1)
        snake_Head.append(y1)
        snake_List.append(snake_Head)
        if len(snake_List) > Length_of_snake:
            del snake_List[0]
 
        for x in snake_List[:-1]:
            if x == snake_Head:
                game_close = True
 
        our_snake(snake_block, snake_List)
        Your_score(Length_of_snake - 1)
 
        pygame.display.update()
 
        if x1 == foodx and y1 == foody:
            foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
            foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
            Length_of_snake += 1
 
        clock.tick(snake_speed)
 
    pygame.quit()
    quit()
 
gameLoop()
```

So, hope you enjoyed reading this article. I hope you learnt something new from this article. Do try it on your own and try to modify the features and implement a better model of this. Some examples of improvements could be to have various levels of difficulty with varying snake speeds and width. It can be made more interactive and beautiful.

Go, try it out and make something new out of it. Visit the [Github Repository of this project](https://github.com/shubham1710/snake-game-python) for more updates on this.

Thank you for reading it. Hope you loved it!

*Originally published [at Medium](https://medium.com/datadriveninvestor/building-a-snake-game-with-python-4d9e4a8dd4ad)*