leafleafleafDocy banner shape 01Docy banner shape 02Man illustrationFlower illustration

Detailed Implementation of Python Pygame Snake Game (Part 1)

Estimated reading: 11 minutes 60 views

We introduced the concept of functions and the role of functions earlier. The program ultimately defines the functions to be executed through functions, and completes and implements these functions through function calls. The functions that need to be defined in the Snake game are introduced earlier. These functions are the core code of the game program. Next, let’s take a look at how these functions are implemented in turn.

main() function

The main() function is the entry point for program execution. Let’s take a look at the detailed code of the main() function first.

def main(): #Entry function, the program starts running from here
    pygame.init() # module initialization
    screen = pygame.display.set_mode((windowsWidth, windowsHeight))
    pygame.display.set_caption("Snake")
    screen.fill(WHITE)
    snakeSpeedClock = pygame.time.Clock()
    startGame(screen) #Game start
    while True:
        music=pygame.mixer.Sound("snake.wav")
        music.play(-1)
        runGame(screen, snakeSpeedClock)
        music.stop()
        gameOver(screen) #Game Over

First, initialize Pygame and call the pygame.init() function to initialize the module. The pygame.display.set_mode() function is then called, creating a display window 800 pixels wide and 600 pixels high, returning the pygame.Surface object for the window and storing it in a variable called screen.

Next, call the pygame.display.set_caption() function to set the title of the window, here the game window is named “Snake”. Call the screen.fill() function to fill the window with white. Then create a clock (Clock) object, assign it to snakeSpeedClock variable, use it to control the frame rate.

Then, call the custom function startGame, which is the function responsible for starting the game. The parameter passed to it is the variable screen, which will be described in detail later.

Next, to keep the Pygame event loop running, we use a while loop, and the loop condition is a boolean value of True, which means that the loop will continue and the only way to exit the loop is to terminate the program. In the previous examples, we usually use a variable as the loop condition, and when the program exits, modify this variable to end the loop. The effect of these two practices is the same, in contrast, the usage here is simpler.

In the body of the loop, we initialize the mixer, then load a piece of background music snake.wav into a Sound object and store it in the variable music. Next, call the play() function to play the music. The parameter -1 means it will be played in a loop.

Through the above code, we have added background music to the game. Then call the runGame function. The parameters passed to it are the variables screen and snakeSpeedClock. This function is responsible for running the game. This function will be described in detail later.

When this function finishes executing, it will call the music.stop() function to stop the background music playing. Then, call the gameOver function to end the game, and the parameter passed to it is the variable screen.

startGame() function

This function is responsible for controlling the startup of our program, and the parameter it receives is the pygame.Surface object of the window. Let’s take a look at the code for this function.

def startGame(screen):
    gameStart = pygame.image.load("gameStart.png")
    screen.blit(gameStart, (70, 30))
    font = pygame.font.SysFont("SimHei", 40)
    tip = font.render("Press any key to start the game", True, (65, 105, 225))  
    screen.blit(tip, (240, 550))
    pygame.display.update()
    while True: #Keyboard monitor events
        for event in pygame.event.get(): #Close the window
            if event.type == pygame.QUIT:
                terminate()   
            elif event.type == pygame.KEYDOWN:
                if (event.key == pygame.K_ESCAPE): #Press the ESC key
                    terminate()
                else:
                    return

First, call the image() function to load the “gameStart.png” image in the Pygame window and create a Surface object named gameStart. Then, call the blit() function to copy the pixels from one Surface to the other. It is to copy the gameStart object to the Surface of Screen. Copy gameStart to the specified location (70, 30) via blit().

Then, call the pygame.font.SysFont function to create a Font object and assign it to a variable named font, which allows us to draw on the Pygame Surface with the 40-point SimHei font.

Next, use the render() command on the created font object to draw the string “Press any key to start the game” onto the Surface. Then, call the blit() function to copy the pixels from one Surface to the other. screen.blit(tip, (240, 550)) is responsible for copying the tip object to the specified position on the surface of screen.

Call the pygame.display.update() function to display everything drawn to the Surface object to the window.

Next, to keep the Pygame event loop running, we use a while loop. In the event loop, if it is judged that the event type is QUIT (close the window), the terminate() function is called to terminate the program. We will introduce the terminate() function later. Otherwise, if the event type is KEYDOWN, then the event object will have a key property to identify which key was pressed.

If the key attribute is equal to K_ESCAPE, it means that the user pressed the Esc key, which means that the player wants to end the program, then the program is handled in the same way as clicking to close the window, and the terminate() function is called to terminate the program. Otherwise, it means that the user pressed another key, and exiting this function means that the game starts running.

When this function is executed, the game interface shown in Figure 1 will appear. At this time, the player can press the Esc key to close the program, and if any other key is pressed, the game will start.


figure 1

runGame() function

This function controls the running of the game program. The parameters it accepts are the pygame.Surface object of the window and the clock object of Pygame.

The code for the runGame() function looks like this:

def runGame(screen, snakeSpeedClock):    
    startX = random.randint(3, mapWidth - 8)
    startY = random.randint(3, mapHeight - 8)
    snakeCoords = [{"x": startX, "y": startY},
                   {"x": startX - 1, "y": startY},
                   {"x": startX - 2, "y": startY}]
    direction = RIGHT      
    food = {"x": random.randint(0, mapWidth - 1), "y": random.randint(0, mapHeight - 1)}   
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                terminate()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT and direction != RIGHT:
                    direction = LEFT                   
                elif event.key == pygame.K_RIGHT  and direction != LEFT:
                    direction = RIGHT                   
                elif event.key == pygame.K_UP and direction != DOWN:
                    direction = UP
                elif event.key == pygame.K_DOWN and direction != UP:
                    direction = DOWN     
                elif event.key == pygame.K_ESCAPE:
                    terminate()
        moveSnake(direction, snakeCoords)  #mobile snake
        isEattingFood(snakeCoords, food)   #Determine whether the greedy snake has eaten food
        ret = isAlive(snakeCoords)         #Determine if the greedy snake is still alive
        if not ret:
            break                          #Snake is dead, game over
        gameRun = pygame.image.load("background.png")
        screen.blit(gameRun, (0, 0))
        drawFood(screen, food)
        drawSnake(screen, snakeCoords)
        drawScore(screen, len(snakeCoords) - 3)
        pygame.display.update()
        snakeSpeedClock.tick(snakeSpeed)  #control frame rate

First, use the random.randint() function to select a random integer between 3 and mapWidth−8 and assign it to the variable startX, and select a random integer between 3 and mapHeight−8 to assign it to the variable startY. These two variables represent gluttony respectively. The snake’s initial x and y coordinates. The purpose of selecting random numbers is to make the position where the snake appears is not fixed, which increases the uncertainty of the game.

Then, the snake is represented by a list of nested dictionaries. Each dictionary represents a coordinate on the map, {‘x’: startX, ‘y’: startY} represents the position of the snake’s head, {‘x’: startX – 1, ‘y’: startY} and {‘x’: startX – 2, ‘y’: startY} represents the snake’s body. This is a horizontal snake with its head on the right and two sections of its body.

Set the direction to RIGHT, which means the direction is right. RIGHT is the direction variable we defined earlier.

Then use the random.randint() function to select a random integer between 0 and mapWidth−1 as the value of the x key in the dictionary, and select a random integer between 0 and mapHeight−1 as the value of the y key in the dictionary. Assigned to the variable food. Use this variable to represent the coordinate location of the food.

Next, to keep the Pygame event loop running, we use a while loop. In the event loop, determine the event type, and if it is QUIT, call the terminate() function to terminate the program. Otherwise, if the event type is KEYDOWN, then the event object will have a key property to identify which key was pressed.

If the key attribute is equal to K_LEFT, it means that the user pressed the left arrow key, and direction != RIGHT, then set the variable direction to LEFT, that is, set the direction to left. Here, direction != RIGHT means that the snake’s head is not to the right, because if the snake’s head is to the right, there is no way to set the direction to the left (because it is necessary to avoid the collision of the head and the body caused by the snake’s direct U-turn) , we can set the snake head direction to left only when the snake head is up, down or left.

If the key attribute equals K_RIGHT and direction != LEFT, then set the variable direction to RIGHT; if the key attribute equals K_UP and direction != DOWN, then set the variable direction to UP; if the key attribute equals K_DOWN and direction != UP, then set the variable direction to DOWN;

if the key attribute is equal to K_ESCAPE, it means that the user pressed the Esc key, which means that the player wants to end the program, then the processing method is the same as the player clicks to close the window, and the terminate() function is called to terminate program.

Then, call the moveSnake() function to move the snake. The parameters of this function are the variables direction and snakeCoords. We will introduce the moveSnake() function in detail later.

Next, call the isEattingFood() function to determine whether the snake has eaten food. The function parameters are the variables snakeCoords and food. We will introduce the isEattingFood() function in detail later.

Then call the isAlive() function to judge whether the snake is dead. The parameter of this function is the variable snakeCoords, and assign its return result to the variable ret. The isAlive() function will be described in detail later. Determine whether the variable ret is True, if not, jump out of the while loop, indicating that the snake is dead, and the game is over.

Call the image.load() function to load the game background image and create a Surface object named gameRun. Call the blit() function to copy the gameRun object to the screen Surface, and the specified position is the upper left corner.

Then call the drawFood() function to draw the food. The parameters of this function are the variables screen and food. We will introduce the drawFood() function later.

Then call the drawSnake() function to draw the snake. The parameters of this function are the variables screen and snakeCoords. We will introduce the drawFood() function in detail later.

The score is then drawn by calling the drawScore() function, which takes the variables screen and the result of len(snakeCoords) – 3. len(snakeCoords) is the length of the snake. Subtract 3, because Snake initially has a head and two bodies, that is, snakeCoords initially has 3 elements, and subtracting 3 is the new body part, which is the corresponding score.

Call the pygame.display.update() function to display everything drawn on the Surface object to the window. Call the tick() method of the clock object, indicating that the frame rate of the game running is snakeSpeed ​​FPS, that is, snakeSpeed ​​times per second.

When the runGame() function is executed, the game interface shown in Figure 2 will appear.

Python runGame() function

Leave a Comment

CONTENTS