A Hiss-terical Guide to Building the Snake Game with Python! ๐Ÿ๐Ÿ˜„

A Hiss-terical Guide to Building the Snake Game with Python! ๐Ÿ๐Ÿ˜„

Introduction

If you have ever wanted to create a project to add to your GitHub portfolio to showcase your Python OOP skills, well here is a chance for you!!

Welcome to the magical world of coding, where we'll embark on an exciting journey to create a timeless classic - the Snake Game - from scratch using Python. Whether you're an absolute beginner or a curious explorer, this step-by-step guide will take you through the process of crafting your very own game, without the need for any prior programming knowledge. So let's dive in and get ready to slither into fun!

This is exciting because we are going to be using OOP as well as the turtle module to build the famous snake game. Now this is the probably one of the most famous mobile games that ever was, and it is definately one of my favourite.

The history dates back to the first mobile phone my dad used back then in Lagos, the NOKIA 1100

NOKIA 1100

But the most exciting part about it was how I, my Dad and Mom would literally compete and see who would get the highest score and my dad always came out top. We would spend many hours a day playing the game for days and days. And compared to the games we play on our Android and iPhone of course, this was very very simple, but still it is still super addictive. And this is the exact game we are going to build.

The first step is to create a snake body, and we're going to do that by creating three squares on the screen, all lined up next to each other. And then we're going to figure out how to move the snake so that it continuously moves forward and all we have to do is tell it to change direction. Afterward, we're going to figure out how to control the snake using keyboard controls. So we're going to be using the up, left, down, and right arrow keys to move our snake across the screen.

And that is what we're aiming for by the end of today,

Genius!

Oh, wrong photo! But that's not me, I'm not that good in the game.

Here is the right one here

So we're going to split up this game into two parts and we're going to tackle them.

  1. The first step is to create a snake body, and we're going to do that by creating three squares on the screen, all lined up next to each other.

  2. And then we're going to figure out how to move the snake so that it continuously moves forward and all we have to do is tell it to change direction.

  3. Afterward, we're going to figure out how to control the snake using keyboard controls. So we're going to be using the up, left, down, and right arrow keys to move our snake across the screen.

  1. We'll need to start putting some food onto the screen and started to detect the collision with the food so that once the snake hits the food, then a new piece of food gets created randomly on the screen at some sort of random location.

  2. And then it's a matter of keeping track of the score and creating a scoreboard. So we're going to learn how to write text in our program so that once the snake hits a piece of food, the score automatically updates.

  3. And then next we're going to figure out when the game should end. So one of the cases when the game should end is when the snake has collided with the wall. And at this point we should see game over, show up on screen and the snake should no longer move.

  4. And then finally, the other reason why our game could end is when the snake has collided with its own tail. So the snake basically can't chase his own tail. And as the snake gets longer, this problem is more likely to occur. And when their head hits any part of the body of the snake, then it's again, game over.

    So these are the seven steps that it takes to create the snake game, So I'll see you there.

Once again this is the full documentation of the turtle module we would be using https://docs.python.org/3/library/turtle.html SO if you are ever confused you have an all-knowing genie you can consult with the click of a link.

We would have 5 files in our game.

main.py (where all main code goes)

food.py (where the food code goes)

scoreboard.py (where the scoreboard code goes)

snake.py (where our snake code goes)

background_image.gif (our background image, click here to download it)

To kickstart our Snake Game project, we need a captivating game window where the action unfolds. We'll use Python's turtle module to create our game window. Think of it as our game screen, where we'll bring our game world to life!

Once you are a little bit familiar then write this in your main.py file and run it. You should get a black 600 by 600 screen when you run it and that would be our game window

from turtle import Screen, Turtle

screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("My Snake Game")


screen.exitonclick()

In "main.py," as seen above we'll import the necessary modules: the "Screen" class and the "Turtle" class from the "turtle" module. These will enable us to create the window and draw our snake and food on the screen.

Next, we'll set up the game window dimensions and background color. We want our window to be 600x600 pixels, with a black background. Additionally, we'll set the title of the window to "My Snake Game" to add a personal touch.

To ensure the window doesn't disappear right away after running, we'll use the screen.exitonclick() method. This way, we can see the results of our code and admire our creation!

and you should see this

Go to your snake.py file and add the code below to our code

# snake.py
# Snake Class
# Represents the snake object in the Snake Game.

# Imports Turtle and Random
from turtle import Turtle
import random

# Constants
# Our snake would be made of 3 squares by default and
# these are the starting (x, y) positions of each of them
STARTING_POSITIONS = [(0, 0), (-20, 0), (-40, 0)]

# This is for how many pixels we want to meve our snake each time
MOVE_DISTANCE = 20

# These are the angle directions in degrees we want our snake to go on key press
UP = 90
DOWN = 270
RIGHT = 0
LEFT = 180

# This is a list of colors we want each segment square in our snake to be
COLORS = ["#f5f4e8", "#c50d66", "#f07810", "#eec60a", "#57D1C9",
          "#ED5485", "#FFFBCB", "#FFE869"]

class Snake:
    def __init__(self):
        """
        Initializes the Snake class.

        Attributes:
        segments (list): List of turtle segments that form the snake's body.
        starting_positions (list): List of starting positions for the segments.
        head (Turtle): Reference to the head segment of the snake.
        """
        # This is the list all the snake body segments would be stored
        self.segments = []
        self.starting_positions = STARTING_POSITIONS
        self.create_snake()

        # We need to know the head of the snake which is what we would controls
        # with our buttons and is also what we would use to perform actions like
        # eating food or buting ourselve
        self.head = self.segments[0]

    def create_snake(self):
        """
        Creates the initial snake body with three segments.
        """
        self.segments = []
        for position in self.starting_positions:
            self.add_segment(position)

    def add_segment(self, position):
        """
        Adds a new segment to the snake's body.

        Args:
        position (tuple): The (x, y) position for the new segment.
        """
        segment = Turtle()
        segment.penup() # lifts the drawing en up so we dont see tracks of movement
        segment.shape("square") # makes each segment a square
        segment.color(random.choice(COLORS)) #  makes segment have a random color from colors
        segment.goto(position) # Noves that segment to the best position on the screen
        self.segments.append(segment) # appends that new segment to the snake nody

    def move(self):
        """
        Moves the snake forward by one step as specified in MOVE_DISTANCE.
        """
        for seg in range(len(self.segments) - 1, 0, -1):
            x = self.segments[seg - 1].xcor()
            y = self.segments[seg - 1].ycor()
            self.segments[seg].goto(x=x, y=y)
        self.head.forward(MOVE_DISTANCE)

    def grow(self):
        """
        Makes the snake grow by adding a new segment to its body.
        """
        position = self.segments[-1].position()
        self.add_segment(position)

    # Each of the below functions are made so the snake cant switch in 
    # an opposite direction instantly, You would have to turn manually
    # and not just reverse like a car
    def up(self):
        """
        Changes the snake's direction to move upwards (up the screen).
        """
        if self.head.heading() != DOWN:
            self.head.setheading(UP)

    def down(self):
        """
        Changes the snake's direction to move downwards (down the screen).
        """
        if self.head.heading() != UP:
            self.head.setheading(DOWN)

    def right(self):
        """
        Changes the snake's direction to move rightwards (towards the right side of the screen).
        """
        if self.head.heading() != LEFT:
            self.head.setheading(RIGHT)

    def left(self):
        """
        Changes the snake's direction to move leftwards (towards the left side of the screen).
        """
        if self.head.heading() != RIGHT:
            self.head.setheading(LEFT)

and then edit your main.py file to look like the code below so that now it displays the snake and you can also control it.

# main.py
# Importing necessary modules and classes from the turtle module
from turtle import Screen
from snake import Snake
import time

# Creating the screen object
screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("My Snake Game")

# Creating the snake object
snake = Snake()

# Configuring key events for snake movement with the up, down, left and right keys
screen.listen()
screen.onkey(key="Up", fun=snake.up)
screen.onkey(key="Down", fun=snake.down)
screen.onkey(key="Right", fun=snake.right)
screen.onkey(key="Left", fun=snake.left)

# Game Loop
game_is_on = True
while game_is_on:
    # Update the screen to show the latest changes
    screen.update()

    # Adding a slight delay to control the snake's movement speed
    time.sleep(0.1)

    # Move the snake one step forward
    snake.move()

# The game loop continues until it's broken out of, which occurs when the game is over.

# Exit the game gracefully when the user clicks on the screen
screen.exitonclick()

VOILA!! Now run your code and test it with the arrow keys of your keyboard and

and there goes our beautiful snake moving around. But you'd realize something strange. Our snake has superpowers! It can pass through walls and vanish and come back through mental teleportation, you have to figure out how to call it back! Haha

so here is how it looks now

Open your food.py file and have it look like this

# food.py
# Importing the necessary module and class from the turtle module
from turtle import Turtle
import random

class Food(Turtle):
    def __init__(self):
        # we directly inherited from the turtle module here that was passed
        # as input to the class
        super().__init__()

        # Set the attributes for the food object
        self.color("yellow")                        # Set the color of the food to yellow
        self.shape("circle")                        # Set the shape of the food to a circle
        self.penup()                                # Lift the pen to avoid drawing lines while moving
        self.shapesize(stretch_wid=0.5, stretch_len=0.5)   # Stretch the circle to half its size
        self.speed("fastest")                      # Set the animation speed to the fastest possible

        # Move the food to a random position on the screen
        self.move()

    def move(self):
        # Generate random coordinates for the food's new position
        random_x = random.randint(-280, 280)
        random_y = random.randint(-280, 280)

        # Move the food to the newly generated random coordinates
        self.goto(x=random_x, y=random_y)

and then modify your main.py to look like this

# Importing necessary modules and classes from the turtle module
from turtle import Screen
from snake import Snake
from food import Food
import time

# Creating the screen object
screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("My Snake Game")
screen.tracer(0) #Turn off screen animations

# Creating the snake and food object
snake = Snake()
food = Food()

# Configuring key events for snake movement with the up, down, left and right keys
screen.listen()
screen.onkey(key="Up", fun=snake.up)
screen.onkey(key="Down", fun=snake.down)
screen.onkey(key="Right", fun=snake.right)
screen.onkey(key="Left", fun=snake.left)

# Game Loop
game_is_on = True
while game_is_on:
    # Update the screen to show the latest changes
    screen.update()

    # Adding a slight delay to control the snake's movement speed
    time.sleep(0.1)

    # Move the snake one step forward
    snake.move()

    # Check if the snake's head is close enough to the food (within 15 pixels)
    if snake.head.distance(food) < 15:
        # Move the food to a new random position on the screen
        food.move()

        # Make the snake grow by adding a new segment
        snake.grow()


    # Check if the snake's head has collided with the screen boundary which is half of the 600 by 600
    # minus a lil bit of space so our snake does not have to keave the screen before a game over
    if snake.head.xcor() > 290 or snake.head.xcor() < -290 or snake.head.ycor() > 290 or snake.head.ycor() < -290:
        # If the snake hits the boundary, end the game
        game_is_on = False


    # Check for collisions with the snake's own body
    for segment in snake.segments[1:]:
        if snake.head.distance(segment) < 10:
            # If the snake collides with its own body, end the game
            game_is_on = False



# The game loop continues until it's broken out of, which occurs when the game is over.

# Exit the game gracefully when the user clicks on the screen
screen.exitonclick()

Now when you hit run! You should see our beautiful snake and food that is randomly generated across the screen. Also, you realize that our game stops if we hit the edge of the screen or bite ourselves. So that brings us to the next step which is displaying our scoreboard and also showing the game over.

so here is our new look

create a scoreboard.py file and add the following code to it

# Importing the Turtle module for creating a custom Scoreboard class

# Constants for positioning and text formatting
POSITION = (0, 270)
ALIGNMENT = "center"
FONT = ("Courier", 20, "normal")
TEXT = "Score:"
GAMEOVER = "Game Over"

# Custom Scoreboard class, inheriting from Turtle
class Scoreboard(Turtle):
    def __init__(self):
        super().__init__()  # Initializing the base class (Turtle)
        self.score = 0      # Initializing the score to 0
        self.color("white") # Setting the color of the text to white
        self.penup()        # Lifting the pen to avoid drawing lines while positioning
        self.increase_score() # Calling the increase_score method to display the initial score
        self.hideturtle()   # Hiding the turtle icon for a cleaner appearance

    # Method to update the displayed score
    def increase_score(self):
        self.goto(POSITION)           # Positioning the turtle at the specified position
        self.clear()                  # Clearing any existing text
        self.write(arg=f"{TEXT} {self.score}", align=ALIGNMENT, move=True, font=FONT)
        # Writing the current score using the specified formatting

    # Method to display the "Game Over" message
    def game_over(self):
        self.goto(0,0)                 # Positioning the turtle at the center of the screen
        self.write(arg=f"{GAMEOVER}", align=ALIGNMENT, move=True, font=FONT)
        # Writing the "Game Over" message using the specified formatting

then edit your main.py file to look like this

# Importing necessary modules and classes from the turtle module
from turtle import Screen
from snake import Snake
from food import Food
from scoreboard import Scoreboard
import time

# Creating the screen object
screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("My Snake Game")
screen.tracer(0) #Turn off screen animations

# Creating the snake and food and scoreboard object
snake = Snake()
food = Food()
score_board = Scoreboard()

# Configuring key events for snake movement with the up, down, left and right keys
screen.listen()
screen.onkey(key="Up", fun=snake.up)
screen.onkey(key="Down", fun=snake.down)
screen.onkey(key="Right", fun=snake.right)
screen.onkey(key="Left", fun=snake.left)

# Game Loop
game_is_on = True
while game_is_on:
    # Update the screen to show the latest changes
    screen.update()

    # Adding a slight delay to control the snake's movement speed
    time.sleep(0.1)

    # Move the snake one step forward
    snake.move()

    # Check if the snake's head is close enough to the food (within 15 pixels)
    if snake.head.distance(food) < 15:
        # Move the food to a new random position on the screen
        food.move()

        # Make the snake grow by adding a new segment
        snake.grow()

        # Increase our score
        score_board.score += 1
        score_board.increase_score()


    # Check if the snake's head has collided with the screen boundary which is half of the 600 by 600
    # minus a lil bit of space so our snake does not have to keave the screen before a game over
    if snake.head.xcor() > 290 or snake.head.xcor() < -290 or snake.head.ycor() > 290 or snake.head.ycor() < -290:
        # If the snake hits the boundary, end the game
        game_is_on = False

        # Display Game over of we touch the edge pf screen
        score_board.game_over()


    # Check for collisions with the snake's own body
    for segment in snake.segments[1:]:
        if snake.head.distance(segment) < 10:
            # If the snake collides with its own body, end the game
            game_is_on = False

            # Display game over if we bite ourselves
            score_board.game_over()



# The game loop continues until it's broken out of, which occurs when the game is over.

# Exit the game gracefully when the user clicks on the screen
screen.exitonclick()

VOILA, our game is complete!!!! and here is how it looks now

Oh thanks for reminding me.

If you have downloaded the background_image.gif and then you can change the background image by going to the 10th line in your main.py and changing that line from

screen.bgcolor("black")

to

screen.bgpic("background_image.gif")

So technically we are no longer using a background color but now we use a background image and now it looks like this

Here is a zip file containing all our work

Congratulations! You've successfully created your very own Snake Game using the power of Python. From setting up the game window to controlling our slithering protagonist and keeping score, you've experienced the magic of coding come to life.

But remember, this is just the beginning of your coding journey. As you continue to explore the Python language and dive into new projects, the possibilities are endless. So keep on coding, keep on slithering, and most importantly, keep having fun along the way!

Thank you for joining us on this hiss-terical adventure. Until next time, happy coding and happy gaming!

Author's Note:

Hey there, fellow coder! I hope you had a blast building your very own Snake Game. Embrace the power of Python and continue exploring the vast world of coding. Remember, every step you take in this journey is a step toward growth and discovery.

If you have any questions, support, have issues with this code, want to hire me or need further assistance, feel free to reach out via email. Let's continue this adventure together, slithering through the wonders of programming!

Happy coding and hiss-terical fun! ๐Ÿ

Author: Ifedayo Akinsira-Olumide