Making a simple Snake game in python (part 2)

Arpit Omprakash
Byte-Sized-Code
Published in
5 min readFeb 2, 2020

In part 1, we have covered the basics of pygame and written classes for the objects in our game (food and the snake). So the plan for part 2 is to write some essential functions related to the scoring, and then we will put everything together into a final program and play the game!

Without further ado, here is the final piece of code:

Let’s go through it step by step. The first function here

# Draw the score on the screen
def draw_score(surface):
global high_score
font_name = pg.font.match_font('arial')
if score > high_score:
high_score = score
# writing the score
font = pg.font.Font(font_name, 18)
text_surface = font.render('Score: {} High Score: {}'.format(score, high_score), True, white)
text_rect = text_surface.get_rect()
text_rect.midtop = (200 , 10)
surface.blit(text_surface, text_rect)

is used to write scores on the screen. First, we declare global to access and modify the high_score variable. We set the high score as the current score if it is higher than the current high score. Next, we choose a font (the first line, font_name = pg.font.match_font('arial') ensures that we find a font that is either ‘arial’ or whose name has an ‘arial’ in it. The next three lines create a rectangle to display the score, font.render(‘Score: {} High Score: {}'.format(score, high_score), True, white) tells the program to write ‘Score: score High Score: high_score’ in white. The other parameter which is set as True is anti-aliasing. It smoothens the text. Next, we get the rectangle on which the text is drawn via get_rect() and place its mid-top position at (200,10) in the next line. The final line writes the score in the text_rect object.

Next up, we have the game over function:

# What to do when the game is over
def game_over():
global score
# writing game over
gameOverFont = pg.font.Font('freesansbold.ttf', 24)
gameOverSurf = gameOverFont.render('Game Over', True, white)
gameOverRect = gameOverSurf.get_rect()
gameOverRect.midtop = (200, 50)
wn.blit(gameOverSurf, gameOverRect)
# reset score
score = 0
pg.display.flip()
time.sleep(2)
# re-initialize game
run = True
fd = Food()
p = Player()
play_game(fd, p)

The function first writes the word “Game Over” on the screen (the first 6–7 lines). Then it resets the score to 0. pg.display.flip() is used to update the screen so that the changes made above are visible. Next, we call the time.sleep() function from the time module, which makes the screen unresponsive for 2 seconds. Finally, we re-initialize the whole game by creating new food and player objects and initializing the game environment using the play_game function.

Next, we have a look at the play_game function:

# The game
def play_game(fd, p):
global score
run = True
while run:
# FPS
clock.tick(30)
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
# draw food, snake, score
wn.fill(black)
fd.draw_food(wn)
p.draw_player(wn)
draw_score(wn)
# user input
pressed = pg.key.get_pressed()
if pressed[pg.K_UP]:
p.change_direction('up')
if pressed[pg.K_LEFT]:
p.change_direction('left')
if pressed[pg.K_DOWN]:
p.change_direction('down')
if pressed[pg.K_RIGHT]:
p.change_direction('right')
# move snake
p.move()
# eating
if fd.is_eaten(p.head):
fd.new_pos()
p.add_unit()
score += 10
# collision
if p.is_collision():
run = False
game_over()
pg.display.update()

The play_game function takes the two objects (food and player) as the input and makes them play the game. In part 1, we had seen pretty much half of the code written here, so I am not explaining that part in detail. I’ll be talking about the changes from the code we encountered in the first post. After we fill the screen with a black color, in the next three lines, we draw the food, the player, and the score. pressed = pg.key.get_pressed() Makes a note of all the keys that are pressed on the keyboard by the user. The next segment of code checks if the user pressed a key and then calls an appropriate function in response, e.g., the line if pressed[pg.K_UP] checks if the user pressed the Up arrow, then it changes the direction of snake to upwards in the next line, p.change_direction('up'). The very next line moves the snake in the direction of its head. The last two blocks of code check if the snake has eaten the food or if the snake has collided with itself or the game boundaries. When the snake eats the food, the block if fd.is_eaten(p.head): is executed and (a.) the food moves to a new position (b.) the snake body length is increased by one unit (c.) the score is increased by 10. Similarly, when a collision occurs, the if p.is_collision(): block is executed, the game loop is stopped, and the game_over function is called. The last line pg.display.update() Updates the screen from time to time so that we can see the snake, the food, and the scores. The very first line of the function is clock.tick(30) this may seem puzzling, and we haven’t talked about it yet, but we are going to now. Comment out that line and run the whole code.

When you run the whole code without the clock.tick() line, everything happens fast. The game moves at the fastest rate that your computer can run the program, and nothing is visible to us, and the snake dies by colliding with the wall. So, to make time for the user to interact with the game, we need to slow down the speed at which everything progresses. The slowdown is achieved by the clock.tick() function. clock = pg.time.Clock() is an object of pygame that is used to regulate the FPS or Frames Per Second of the game. A value of 30 (as in the code above) implies that the calculations and the images of the final product (snake, the score, and the food) are drawn about 30 times in a second, which is an incredibly fast rate. Changing the values will slow down or speed up the whole game and can thus be used to regulate the difficulty of the game.

This is the final piece of code:

pg.init()wn = pg.display.set_mode((screen_width, screen_height))
pg.display.set_caption('A simple game of Snake')
fd = Food()
p = Player()
play_game(fd,p)
pg.quit()

This makes a screen object and calls the required functions to initialize the game. The whole code compiled is present here for reference. I hope you enjoyed the tutorial, and it made you learn some new things. Here are a few screenshots of the game:

Screenshots from the game

Comment below if you enjoyed making your own game of snake and how did others (friends and family) feel when you showed it to them.

--

--

Arpit Omprakash
Byte-Sized-Code

I'm a Programming and Statistics enthusiast studying Biology. To find out if we have common interests, have a look at my thoughts: https://aceking007.github.io/