Use pygame to make a snake game

Basic idea of ​​development

1. Make a window, insert audio and pictures
2. Draw snakes and fruits
3. Button control
4. Generate food
5. End judgment

Show results

Insert picture description here

Specific implementation steps

(This program is written based on Python 3.9.1)

Create windows, insert audio and pictures

First, import the required modules.

import pygame
import sys
import random
from pygame.locals import *

After that, the initialization is carried out, and the initialization of the mixer is to prepare for adding background music.

#初始化
pygame.init()        #初始化pygame
pygame.mixer.init()  #初始化混音器

Next we will make the game window. First define the size of the window you need, and then give the window a title.

#制作窗口
playSurface = pygame.display.set_mode((800,800))  #定义窗口大小
pygame.display.set_caption("贪吃蛇")  #定义标题

At this point, a window is set up!
Insert picture description here

Then we will add appropriate background music to the game, where (-1) means let the background music play in a loop.

#添加音乐
pygame.mixer.music.load("贪吃蛇背景音乐.mp3")
pygame.mixer.music.play(-1)

Then define a function to end the game to pave the way for later judging the end conditions of the game.

#结束游戏
def gameover():
    pygame.quit()   #退出pygame窗口
    sys.exit()      #退出程序

Finally, let’s set the color of the snake and food

#颜色设置
snakeBody_color = pygame.Color(0,255,0) #绿色
food_color = pygame.Color(255,0,0) #红色

Next we enter the main function

Draw snake and fruit

First set the initial position of the fruit and the initial position of the snake's head. This snake initially has several segments of body. We set each segment of the snake's body and fruit as a small square of 20*20 pixels.

def main():
 	#绘制蛇与果实
    snakePosition = [200,200]                       #蛇头位置
    snakeBodys = [[200,200],[180,200],[160,200]]    #蛇身位置
    foodPosition = [500,500]        #果实位置

After that, variables such as the number of fruits, the speed of the snake, and the initial direction are set. In the code behind, you can see that foodTotal becomes 0 after the fruit is eaten, which is used to generate new fruit. The foodNumber is used to control the speed of the snake later. Every time a certain amount of fruit is eaten, the snake increases its speed and the foodNumber value returns to 1.

	time_clock = pygame.time.Clock() #定义一个变量来控制速度
	foodTotal = 1                   #果实数量
	foodNumber = 1                  #用于增加速度的变量
    direction = 'right'             #初始方向向右
    changeDirection = direction     #定义一个改变方向的变量,按键

    speed = 4  #定义初始速度

Let's write an infinite loop. Except for passively triggering the death condition or actively closing the game window, the program will always run in the loop.

Button control

In the loop, two events must be acquired first, one is to actively exit the event. When the program is running, click the cross in the upper right corner, it will jump out of the loop to end the game. If there is no exit event, everyone will find that it is impossible to actively exit.

	while True:
        for event in pygame.event.get():   #从队列中获取事件

            #退出事件
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

The second event is a key press event, which is used to control the direction of the snake's movement. Press the up, down, left, and right keys or WSAD key to realize the snake's turning. Press the esc key to exit the program.

            #按键事件
            elif event.type == KEYDOWN:
                if event.key == K_RIGHT or event.key == K_d:
                    changeDirection = 'right'

                if event.key == K_LEFT or event.key == K_a:
                    changeDirection = 'left'
                    
                if event.key == K_UP or event.key == K_w:
                    changeDirection = 'up'
                    
                if event.key == K_DOWN or event.key == K_s:
                    changeDirection = 'down'

                if event.key == K_ESCAPE:
                    pygame.event.post(pygame.event.Event(QUIT))

But we should pay attention that in the snake game, you cannot make a 180-degree turn. If you want to move in the opposite direction, you need to press the same opposite direction key twice.

        #防止蛇反方向移动
        if changeDirection == 'right' and not direction == 'left':
            direction = changeDirection
            
        if changeDirection == 'left' and not direction == 'right':
            direction = changeDirection
            
        if changeDirection == 'up' and not direction == 'down':
            direction = changeDirection
            
        if changeDirection == 'down' and not direction == 'up':
            direction = changeDirection

After pressing the arrow keys, it is natural to adjust the moving direction of the snake head according to the corresponding direction.

        #根据方向移动蛇头
        if direction == 'right':
            snakePosition[0] += 20
            
        if direction == 'left':
            snakePosition[0] -= 20
            
        if direction == 'up':
            snakePosition[1] -= 20
            
        if direction == 'down':
            snakePosition[1] += 20

Generate food

Next, let's set the snake's body to increase by one for every square that it walks, and to decrease by one if it doesn't eat food.

        snakeBodys.insert(0, list(snakePosition))  #增加蛇的长度
        
        #判断是否吃到食物
        if snakePosition[0] == foodPosition[0] and snakePosition[1] == foodPosition[1]:
            foodTotal = 0
        else:
            snakeBodys.pop()  #每次将最后一个单位的蛇身去除列表

When the food is eaten, new food is regenerated, but at the same time, code must be written to prevent the food from being generated on the snake. Here, random is called to realize the random generation of food.

        #重新生成食物
        if foodTotal == 0:
            x = random.randrange(1,40)
            y = random.randrange(1,40)
            foodPosition = [int(x*20), int(y*20)]
            foodTotal = 1
            foodNumber += 1    
            
        #防止食物生成在蛇身上
        for body in snakeBodys[1:]:
            if foodPosition[0] == body[0] and foodPosition[1] == body[1]:
                foodTotal = 0
                foodNumber -=1

Death setting

There are two methods of passive death for snakes. One is that the head of the snake touches the edge of the window, and the other is that the head of the snake touches the body of the snake. Here we use the game ending function defined at the beginning.

        #超出边框结束游戏
        if snakePosition[0] > 800 or snakePosition[0] < 0:
            gameover()
            
        elif snakePosition[1] > 800 or snakePosition[1] < 0:
            gameover()
            
        #碰到身体结束游戏
        for body in snakeBodys[1:]:
            if snakePosition[0] == body[0] and snakePosition[1] == body[1]:
                gameover()

The above is the main part, the other settings are to be completed in the while loop below.

other settings

First, fill in a nice background picture for the set window. Some people may wonder why I didn't fill in the background when setting the window. In fact, Aqi did that in the beginning, but there was a bug. Since the background is not constantly refreshed in the while loop, the tail will elongate indefinitely when the snake moves, which is very scary. So we set the background here and draw the snake and fruit.

        #绘制游戏背景
        background = pygame.image.load("河海大学校标.jpg")
        playSurface.blit(background,(0,0))
        pygame.display.update()

        #画出蛇与果实
        for position in snakeBodys:
            pygame.draw.rect(playSurface,snakeBody_color, Rect(position[0], position[1], 20, 20))
            pygame.draw.rect(playSurface, food_color, Rect(foodPosition[0], foodPosition[1], 20, 20))
            
            pygame.display.flip()  #更新显示到屏幕表面

The following is the speed setting. Every time the snake eats 4 fruits, the speed is +1, and the initial speed has been set to 4 before.

        #设置递增速度
        if foodNumber % 5 ==0:
            speed += 1
            foodNumber = 1
            
        # 控制游戏速度
        time_clock.tick(speed)

Finally, we set another entry function, and the whole program is now complete.

#入口函数
if __name__ == "__main__":
    main()

Overall code

import pygame
import sys
import random
from pygame.locals import *

#初始化
pygame.init()        #初始化pygame
pygame.mixer.init()  #初始化混音器

#制作窗口
playSurface = pygame.display.set_mode((800,800))  #定义窗口大小
pygame.display.set_caption("贪吃蛇")  #定义标题

#添加音乐
pygame.mixer.music.load("贪吃蛇背景音乐.mp3")
pygame.mixer.music.play(-1)

    
#结束游戏
def gameover():
    pygame.quit()   #退出pygame窗口
    sys.exit()      #退出程序
    

#颜色设置
snakeBody_color = pygame.Color(0,255,0) #绿色
food_color = pygame.Color(255,0,0) #红色


def main():

    time_clock = pygame.time.Clock() #定义一个变量来控制速度
    
    #绘制蛇与果实
    snakePosition = [200,200]                       #蛇头位置
    snakeBodys = [[200,200],[180,200],[160,200]]    #蛇身位置
    foodPosition = [500,500]        #果实位置
    foodTotal = 1                   #果实数量
    foodNumber = 1                  #用于增加速度的变量
    direction = 'right'             #初始方向向右
    changeDirection = direction     #定义一个改变方向的变量,按键

    speed = 4  #定义初始速度

    while True:
        for event in pygame.event.get():   #从队列中获取事件

            #退出事件
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

            #按键事件
            elif event.type == KEYDOWN:
                if event.key == K_RIGHT or event.key == K_d:
                    changeDirection = 'right'

                if event.key == K_LEFT or event.key == K_a:
                    changeDirection = 'left'
                    
                if event.key == K_UP or event.key == K_w:
                    changeDirection = 'up'
                    
                if event.key == K_DOWN or event.key == K_s:
                    changeDirection = 'down'

                if event.key == K_ESCAPE:
                    pygame.event.post(pygame.event.Event(QUIT))

        #防止蛇反方向移动
        if changeDirection == 'right' and not direction == 'left':
            direction = changeDirection
            
        if changeDirection == 'left' and not direction == 'right':
            direction = changeDirection
            
        if changeDirection == 'up' and not direction == 'down':
            direction = changeDirection
            
        if changeDirection == 'down' and not direction == 'up':
            direction = changeDirection

        #根据方向移动蛇头
        if direction == 'right':
            snakePosition[0] += 20
            
        if direction == 'left':
            snakePosition[0] -= 20
            
        if direction == 'up':
            snakePosition[1] -= 20
            
        if direction == 'down':
            snakePosition[1] += 20

        snakeBodys.insert(0, list(snakePosition))  #增加蛇的长度
        
        #判断是否吃到食物
        if snakePosition[0] == foodPosition[0] and snakePosition[1] == foodPosition[1]:
            foodTotal = 0
        else:
            snakeBodys.pop()  #每次将最后一个单位的蛇身去除列表

        #重新生成食物
        if foodTotal == 0:
            x = random.randrange(1,40)
            y = random.randrange(1,40)
            foodPosition = [int(x*20), int(y*20)]
            foodTotal = 1
            foodNumber += 1    
            
        #防止食物生成在蛇身上
        for body in snakeBodys[1:]:
            if foodPosition[0] == body[0] and foodPosition[1] == body[1]:
                foodTotal = 0
                foodNumber -=1

        #设置递增速度
        if foodNumber % 5 ==0:
            speed += 1
            foodNumber = 1
            
        #绘制游戏背景
        background = pygame.image.load("河海大学校标.jpg")
        playSurface.blit(background,(0,0))
        pygame.display.update()

        #画出蛇与果实
        for position in snakeBodys:
            pygame.draw.rect(playSurface,snakeBody_color, Rect(position[0], position[1], 20, 20))
            pygame.draw.rect(playSurface, food_color, Rect(foodPosition[0], foodPosition[1], 20, 20))

        pygame.display.flip()  #更新显示到屏幕表面

        #超出边框结束游戏
        if snakePosition[0] > 800 or snakePosition[0] < 0:
            gameover()
            
        elif snakePosition[1] > 800 or snakePosition[1] < 0:
            gameover()
            
        #碰到身体结束游戏
        for body in snakeBodys[1:]:
            if snakePosition[0] == body[0] and snakePosition[1] == body[1]:
                gameover()

        # 控制游戏速度
        time_clock.tick(speed)

        
#入口函数
if __name__ == "__main__":
    main()

It should be noted that the background music and background pictures selected by the friends should be placed in the same folder as this program, and this folder should be placed on the c drive! So there is no need to find the path to call the picture or audio.

My favorite friends, remember to support Aqi!

Guess you like

Origin blog.csdn.net/qq_54831779/article/details/114943623