Game Over!

Game over if snake hits edge of game window (51:03)

Now we have to check if our snake hits the edge of the game window. Now this is very easy.

All we have to do is to check if the position of the head of the snake is out of the grid at the x and y axis. Let’s create another method for this check in the Game class.

def check_collision_with_edges(): 
    if self.snake.body[0]

That's the head of the snake, a Vector2 object.

First let’s check if the snake is outside of the grid at the x axis, so we need to access the .x attribute of the head of the snake.

if self.snake.body[0] .x == number_of_cells or self.snake.body[0].x == -1 

Here if the x position of the head of the snake is equal to the number of cells (meaning it has gone past the right edge of the grid) or equal to -1 (meaning it has gone past the left edge of the grid). If either of these conditions are true, it means the snake has hit the edge of the grid and a collision has occurred so they have to end the game.

Call game_over method (52:15)

Let’s call a game_over method.

self.game_over()

We haven’t created this method yet, we will do so in a minute.

Before that, let’s check if the snake moved outside of the game window from the top or the bottom of the screen.

If self.snake.body[0].y == number_of_cells or self.snake.body[0].y ==-1: 

self.game_over() Now let’s call this method in the update method of the game class like this.

self.check_collision_with_edges()

Game over method (52:52)

It is now time to create the game_over() method.

def game_over():

At first let’s just print a message to see if the collision with the edges of the game window works. print(“Game Over”). Let’s now run the game to see if it works.

OK, the game works and when we move outside of the game window a “Game Over” message is printed at the console. Cool, our collisions work. Now inside the game_over method we add the behavior we want when the game ends.

I will keep it very simple in this video, but you can add any behavior you want in your version of the game. When the game is over, I will just return the snake to its starting position, move the food object to a new position and pause the game until the player presses any key on the keyboard. First of all let’s remove this print statement and let’s move the snake to its original position. Let’s create a reset method to the snake object to be responsible for that.

Let’s call this method and implement it at once.

def game_over():
    self.snake.reset()

Now let’s implement this reset method in the Snake class...

def reset(self): 
    self.body = [Vector2(6,9),  Vector2(5,9), Vector2(4,9)]
    self.direction = Vector2(1, 0)

We just recreate the original body list and direction attributes.

The new method is ready. Now we have to move the food object to a new position. Again we are going to call the generate_random_pos method of the food object.

def game_over():
    self.snake.reset()
    self.food.generate_random_pos(self.snake.body) 

Now we have to pause the game until the player presses any key on the keyboard. For this we are going to need to add another attribute to the Game class.

Let’s call this attribute state. self.state = The state attribute can only have two possible values, let’s call them “RUNNING” if the game runs, and “STOPPED” if the game is stopped. Let’s add a state, “RUNNING”.

Now, when the game ends we have to change the game’s state to STOPPED. So we type:

self.state = “STOPPED”. Now we have to make the game stop when the state is “STOPPED”.

We can do that easily inside the update method of the Game class. We need to execute all this stuff, only when the game is “RUNNING”.

So we add an if statement If self.state == “RUNNING”: and now we enter all these calls inside the if statement like this. Let’s test the game. The game runs, and when we hit the end of the game window, the game resets and stops running. The game won’t restart because we haven’t yet defined how the game will restart.

That’s what we are going to do now. We need to restart the game when the user has pressed any key on the keyboard.

The solution to this is very easy. In the game loop we already check if some keys are pressed.

This if statement checks if any key is pressed and with the other if statements below we check if some specific keys are pressed. So, inside the first if statement we have to type:

If game.state == “STOPPED”: game.state = “RUNNING”

The last two lines of code define the restart behavior for the game. The if statement checks if the current game state is "STOPPED".

If it is, the state of the game is changed to "RUNNING". This means that when the game is stopped, if any key is pressed, the state of the game

will change to "RUNNING" and the game will restart. Let’s test it. As you can see, when I move the snake outside of the game window, the game ends and it waits for a key press. When I press any key on the keyboard the game restarts. Very cool!

Check for collision snake head and tail

The next condition we need to implement is checking for a collision between the snake's head and its tail. If the snake's head hits its tail, the game should end.

To check for this collision, we need to check if the position of the head is equal to the position of any of the segments in the body. To implement this, we can add another method in the game class called check_collision_with_tail

def check_collision_with_tail(self): 
headless_body = self.snake.body[1:] If self.snake.body[0] in headless_body 
self.game_over() 

The method "check_collision_with_tail" first creates a new list called "headless_body" which contains all segments of the snake's body except the head. This is because we don't want to check if the head is colliding with itself.

Next, we use an if statement to check if the position of the head is in the"headless_body" list.

(self.snake.body[0])

If it is, it means that the head has collided with the tail, and the game is over.

We call the game_over method to end the game. Of course we also have to call this method in the update method of the game class.

self.check_collision_with_tail()

Let's test the game again to see if the collision with the tail works as expected.

As you can see, we have to eat a few food objects to increase the snake size.

When the snake is big enough and when the snake's head collides with its tail, the game ends and waits for a key press to restart. With this, we have implemented all the necessary behavior for our snake game.