• Home
  • >
  • GUI
  • >
  • Snake Game with OpenCV Python

Snake Game with OpenCV Python

In this post we will learn how to make the Snake Game using OpenCV Python.
Snake Game with OpenCV Python

In this post, we will create the Snake Game using Python and OpenCV as shown in the video above.

Snake Game

In the Snake Game, we have a digital snake that we control using the arrows keys.

An apple randomly appears on the screen and our goal is to move the snake so that it eats the apple. The snake grows in size after eating an apple and our objective is to make the snake as long as possible.

However, the game ends if the snake crashes into a wall or if it crashes into itself.

Now, let’s see how we can implement Snake in Python. Ha ha! See the joke?

Download Code To easily follow along this tutorial, please download code by clicking on the button below. It's FREE!

Implementing Snake Game with OpenCV

First, we will import some libraries for the display and for generating random positions for the apple.

import cv2
import numpy as np
from random import randint
from random import choice

Let’s make a few classes to represent the game.

  1. SnakePart : As shown in Figure 1, this represents the body of the snake (excluding the head).
  2. Head : This class represents the head of the snake (shown in blue in Figure 1).
Figure 1 : Parts of the Snake Game

The SnakePart class has x and y position coordinates, and a reference to another SnakePart or Head in front of it.

class SnakePart:
  def __init__(self, front, x, y):
    self.front = front
    self.x = x
    self.y = y

  def move(self):
    # Moves by following the part in front of it
    self.x = self.front.x
    self.y = self.front.y

The move() method simply copies the location of the part in front of it.

The Head class also has an x and y. In addition, it has a direction variable that specifies the direction of movement.

class Head:
  def __init__(self, direction, x, y):
    self.direction = direction
    self.x = x
    self.y = y

  def move(self):
    # Checks what its current direction is and moves accordingly
    if self.direction == 0:
        self.x += 1
    elif self.direction == 1:
        self.y += 1
    elif self.direction == 2:
        self.x -= 1
    elif self.direction == 3:
        self.y -= 1

Now, let’s move to the main function to see how the game is implemented. We first define a few constants that will come in handy.

CELL_SIZE specifies the width of each cell of the board in pixels.

BOARD_SIZE is the number of cells along the width of the board. In our example, CELL_SIZE is 20 and BOARD_SIZE is 45. So, the size of the display is 20 x 45 = 900 pixels.

SPEED dictates how fast or slow the snake is. Use a smaller number if the game is too fast for you.

GROWTH specifies the number of units by which the snake grows after eating one apple.

if __name__ == '__main__' : 

  # Size of each cell in the board game
  CELL_SIZE = 20
  # Number of cells along the width in the game
  BOARD_SIZE = 45
  # Change SPEED to make the game go faster
  SPEED = 12
  # After eating an apple the snake grows by GROWTH units
  GROWTH = 3

Next, we define some variables that will come in handy later on.

  # Variable to track if apple is eaten
  eaten = True
  # Variable to check if the game should quit
  quit = False
  # Variable to track growth. 
  grow = 0

Now, let’s create an empty array to store the head and snakeparts.

  # Array for storing snake
  snake = []  
  #snake's head starts at the center of the board. 
  head = Head(0, int((BOARD_SIZE - 1)/2), int((BOARD_SIZE - 1)/2))
  snake.append(head)

Before, we move on to the main while loop of the program, let’s look at the display function that displays the current game.

In the code below, we do the following.

  1. We first create a board and fill it with zeros (black)
  2. We color the cells occupied by the snake green.
  3. We color the single cell occupied by the apple red.
  4. If a key is pressed on the keyboard, return the id of the key.
def display():

  # Create a blank image
  board = np.zeros([BOARD_SIZE * CELL_SIZE, BOARD_SIZE * CELL_SIZE, 3])

  # Color the snake green
  for part in snake:
    x = part.x * CELL_SIZE
    y = part.y * CELL_SIZE
    board[y:y + CELL_SIZE, x:x + CELL_SIZE] = [0, 255, 0]
  
  # Color the apple red    
  x = applex * CELL_SIZE
  y = appley * CELL_SIZE
  board[y:y + CELL_SIZE, x:x + CELL_SIZE] = [0, 0, 255]
  
  # Display board
  cv2.imshow("Snake Game", np.uint8(board))
  key = cv2.waitKey(int(1000/SPEED))
  
  # Return the key pressed. It is -1 if no key is pressed. 
  return key

We are almost ready to enter the main while loop of the game. Before we do that we print some instructions.

  # Start the game by printing instructions
  print('w = top, a = left, s = down, d = right')
  # Ugly trick to bring the window in focus
  win_focus()

You will notice a function win_focus(). Depending on which windowing method OpenCV is using on your system, when you run this game, the display window may not be in focus. To fix that problem, we have used this ugly hack to bring our game window in focus so the user does not have to click on the window.

In the code below we are doing the following

  1. We open a window
  2. Display the game window
  3. Set the window to fullscreen. This brings the window in focus.
  4. We resize the window back to normal size.
def win_focus():
  # Ugly trick to get the window in focus.
  # Opens an image in fullscreen and then back to normal window
  cv2.namedWindow("Snake Game", cv2.WINDOW_AUTOSIZE);
  board = np.zeros([BOARD_SIZE * CELL_SIZE, BOARD_SIZE * CELL_SIZE, 3])
  cv2.imshow("Snake Game", board);
  cv2.setWindowProperty("Snake Game", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN);
  cv2.waitKey(2000)
  cv2.setWindowProperty("Snake Game", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_AUTOSIZE)

If you encounter any glitches, you can comment out win_focus() in the main function.

For the main part of the code, we will use a while loop where each iteration is one move for the snake. In the loop below, we accomplish two things

  1. Check if the apple has been eaten.
  2. If yes, generate a new apple. At the time of generating the apple, we make sure its position does not overlap the snake.
 while True:

    # Checks if the apple is eaten and generates a new one
    if eaten:
      # Create a list of all possible locations
      s = list(range(0, BOARD_SIZE ** 2))
      # Delete cells that are part of the snake
      for part in snake:
          s.remove(part.x * BOARD_SIZE + part.y)
      
      # Randomly pick from one of the remaining cells    
      a = choice(s)
      applex = int(a/BOARD_SIZE)
      appley = a % BOARD_SIZE
      
      eaten = False

Next, we display the board, and look for keyboard input.

The if/elif statement checks if ‘w’, ‘a’,’s’, ‘d’, escape, or delete keys have been pressed. Based on the keyboard input, the snake changes direction or we stop the program.

    # Makes and displays the board
    key = display()

    
    # Gets key presses and moves accordingly
    # 8 and 27 are delete and escape keys
    # Arrow keys are tricky in OpenCV. So we use
    # keys 'w', 'a','s','d' for movement. 
    # w = top, a = left, s = down, d = right


    if key == 8 or key == 27:
      break
    elif key == ord("d") :
      head.direction = 0
    elif key == ord("s") :
      head.direction = 1
    elif key == ord("a") :
      head.direction = 2
    elif key == ord("w") :
      head.direction = 3

Based on the keyboard input, we move the snake. As you may remember, the move method of SnakePart simply copies the location of the snake part in front of it.

    # Moving the snake
    for part in snake[::-1]:
        part.move()    

Next, we implement the check for collisions. The code below implements two rules

  1. If the head of the snake moves outside the board, the game ends.
  2. If the head of the snake collides with a snake part (i.e. body of the snake), the game ends.
    # Collision rules

    if head.x < 0 or head.x > BOARD_SIZE - 1 or head.y < 0 or head.y > BOARD_SIZE - 1:
      break
        
    for part in snake[1:]:
      if head.x == part.x and head.y == part.y:
        quit = True
        break
        
    if quit:
      break

Lastly, we code the rule for when the snake eats the apple and grows. The grow variable is incremented by the constant GROWTH when the apple is eaten, and the snake grows by one cell per frame until it is fully grown.

   # The snake grows gradually over multiple frames    
    if grow > 0:
      snake.append(SnakePart(snake[-1], subx, suby))
      grow -= 1
      
    # Grows the snake when it eats an apple
    if applex == head.x and appley == head.y:
      subx = snake[-1].x
      suby = snake[-1].y
      eaten = True
      grow += GROWTH

That is all! Give this a try and let me know how you like the game in the comments section.

Author’s Note

I am Rohan Nayak Mallick, and I am 10 years old.

I received help in writing this post from by dad Dr. Satya Mallick.

However, the idea of implementing the Snake Game was mine, and I wrote the code entirely by myself with minor inputs on style from my dad.

I have been programming in Python for a couple of years and started taking AI courses recently. Currently I am on week 6 on Computer Vision I and week 5 on Deep Learning with PyTorch.

If you like this post, please leave a comment. It will help me earn a chance to write more posts.



Read Next

VideoRAG: Redefining Long-Context Video Comprehension

VideoRAG: Redefining Long-Context Video Comprehension

Discover VideoRAG, a framework that fuses graph-based reasoning and multi-modal retrieval to enhance LLMs' ability to understand multi-hour videos efficiently.

AI Agent in Action: Automating Desktop Tasks with VLMs

AI Agent in Action: Automating Desktop Tasks with VLMs

Learn how to build AI agent from scratch using Moondream3 and Gemini. It is a generic task based agent free from…

The Ultimate Guide To VLM Evaluation Metrics, Datasets, And Benchmarks

The Ultimate Guide To VLM Evaluation Metrics, Datasets, And Benchmarks

Get a comprehensive overview of VLM Evaluation Metrics, Benchmarks and various datasets for tasks like VQA, OCR and Image Captioning.

Subscribe to our Newsletter

Subscribe to our email newsletter to get the latest posts delivered right to your email.

Subscribe to receive the download link, receive updates, and be notified of bug fixes

Which email should I send you the download link?

 

Get Started with OpenCV

Subscribe To Receive

We hate SPAM and promise to keep your email address safe.​