Isn’t it interesting to create a snake game using OpenCV-Python? And what if I tell you that you only gonna need
- cv2.imshow()
- cv2.waitKey()
- cv2.putText()
- cv2.rectangle()
So, let’s get started.
Import Libraries
For this we only need four libraries
1 2 3 4 |
import numpy as np import cv2 import random import time |
Displaying Game Objects
- Game Window: Here, I have used a 500×500 image as my game window.
1 |
img = np.zeros((500,500,3),dtype='uint8') |
- Snake and Apple: I have used green squares for displaying a snake and a red square for an apple. Each square has a size of 10 units.
1 2 3 4 |
# Displaying the snake (Green rectangles) snake_position = [[250,250],[240,250],[230,250]] for position in snake_position: cv2.rectangle(img,(position[0],position[1]),(position[0]+10,position[1]+10),(0,255,0),3) |
1 2 3 |
# Display apple (Red rectangles) apple_position = [random.randrange(1,50)*10,random.randrange(1,50)*10] cv2.rectangle(img,(apple_position[0],apple_position[1]),(apple_position[0]+10,apple_position[1]+10),(0,0,255),3) |
Game Rules
Now, let’s define some game rules
- Collision with boundaries: If the snake collides with the boundaries, it dies.
1 2 3 4 5 |
def collision_with_boundaries(snake_head): if snake_head[0]>=500 or snake_head[0]<=0 or snake_head[1]>=500 or snake_head[1]<=0 : return 1 else: return 0 |
- Collision with self: If the snake collides with itself, it should die. For this, we only need to check whether the snake’s head is in snake body or not.
1 2 3 4 5 6 |
def collision_with_self(snake_position): snake_head = snake_position[0] if snake_head in snake_position[1:]: return 1 else: return 0 |
- Collision with apple: If the snake collides with the apple, the score is increased and the apple is moved to a new location.
1 2 3 4 |
def collision_with_apple(apple_position, score): apple_position = [random.randrange(1,50)*10,random.randrange(1,50)*10] score += 1 return apple_position, score |
Also, on eating apple snake length should increase. Otherwise, snake moves as it is.
1 2 3 4 5 6 7 |
if snake_head == apple_position: apple_position, score = collision_with_apple(apple_position, score) snake_position.insert(0,list(snake_head)) else: snake_position.insert(0,list(snake_head)) snake_position.pop() |
- Snake game has a fixed time for a keypress. If you press any button in that time, the snake should move in that direction otherwise continue moving in the previous direction. Sadly, with OpenCV cv2.waitKey() function, if you hold down the left direction button, the snake starts moving fast in that direction. So, to make the snake movement uniform,
i did something like this.
1 2 3 4 5 6 7 |
t_end = time.time() + 0.2 k = -1 while time.time() < t_end: if k == -1: k = cv2.waitKey(125) else: continue |
Because cv2.waitKey() returns -1 when no key is pressed, so this ‘k’ stores the first key pressed in that time. Because the while loop is for a fixed time, so it doesn’t matter how fast you pressed a key. It will always wait a fixed time.
- Snake cannot move backward: Here, I have used the w, a, s, d controls for moving the snake. If the snake was moving right and we pressed the left button, it will continue moving right or in short snake cannot directly move
backwards .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 0-Left, 1-Right, 3-Up, 2-Down, q-Break # a-Left, d-Right, w-Up, s-Down if k == ord('a') and prev_button_direction != 1: button_direction = 0 elif k == ord('d') and prev_button_direction != 0: button_direction = 1 elif k == ord('w') and prev_button_direction != 2: button_direction = 3 elif k == ord('s') and prev_button_direction != 3: button_direction = 2 elif k == ord('q'): break else: button_direction = button_direction |
After seeing which direction button is pressed, we change our head position
1 2 3 4 5 6 7 8 |
if button_direction == 1: snake_head[0] += 10 elif button_direction == 0: snake_head[0] -= 10 elif button_direction == 2: snake_head[1] += 10 elif button_direction == 3: snake_head[1] -= 10 |
Displaying the final Score
For displaying the final score, i have used cv2.putText() function.
1 2 3 4 5 6 7 |
if collision_with_boundaries(snake_head) == 1 or collision_with_self(snake_position) == 1: font = cv2.FONT_HERSHEY_SIMPLEX img = np.zeros((500,500,3),dtype='uint8') cv2.putText(img,'Your Score is {}'.format(score),(140,250), font, 1,(255,255,255),2,cv2.LINE_AA) cv2.imshow('a',img) cv2.waitKey(0) break |
Finally, our snake game is ready and looks like this
The full code can be found here.
Hope you enjoy reading.
If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.