• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer

Learn OpenCV

OpenCV, PyTorch, Keras, Tensorflow examples and tutorials

  • Home
  • Getting Started
    • Installation
    • PyTorch
    • Keras & Tensorflow
    • Resource Guide
  • Courses
    • Opencv Courses
    • CV4Faces (Old)
  • Resources
  • AI Consulting
  • About

Snake Game with OpenCV Python

Rohan Nayak Mallick
October 22, 2020 Leave a Comment
Application GUI Tutorial UI

October 22, 2020 By Leave a Comment

In this blog 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?

I've partnered with OpenCV.org to bring you official courses in Computer Vision, Machine Learning, and AI! Sign up now and take your skills to the next level!

Official Courses by OpenCV.org

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 on this blog.

Subscribe & Download Code

If you liked this article and would like to download code (C++ and Python) and example images used in this post, please subscribe to our newsletter. You will also receive a free Computer Vision Resource Guide. In our newsletter, we share OpenCV tutorials and examples written in C++/Python, and Computer Vision and Machine Learning algorithms and news.

Subscribe Now


Tags: highgui snake game

Filed Under: Application, GUI, Tutorial, UI

About

I am an entrepreneur with a love for Computer Vision and Machine Learning with a dozen years of experience (and a Ph.D.) in the field.

In 2007, right after finishing my Ph.D., I co-founded TAAZ Inc. with my advisor Dr. David Kriegman and Kevin Barnes. The scalability, and robustness of our computer vision and machine learning algorithms have been put to rigorous test by more than 100M users who have tried our products. Read More…

Getting Started

  • Installation
  • PyTorch
  • Keras & Tensorflow
  • Resource Guide

Resources

Download Code (C++ / Python)

ENROLL IN OFFICIAL OPENCV COURSES

I've partnered with OpenCV.org to bring you official courses in Computer Vision, Machine Learning, and AI.
Learn More

Recent Posts

  • RAFT: Optical Flow estimation using Deep Learning
  • Making A Low-Cost Stereo Camera Using OpenCV
  • Optical Flow in OpenCV (C++/Python)
  • Introduction to Epipolar Geometry and Stereo Vision
  • Depth Estimation using Stereo matching

Disclaimer

All views expressed on this site are my own and do not represent the opinions of OpenCV.org or any entity whatsoever with which I have been, am now, or will be affiliated.

GETTING STARTED

  • Installation
  • PyTorch
  • Keras & Tensorflow
  • Resource Guide

COURSES

  • Opencv Courses
  • CV4Faces (Old)

COPYRIGHT © 2020 - BIG VISION LLC

Privacy Policy | Terms & Conditions

We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.AcceptPrivacy policy