[Courseware] Use Python to write a snake game (pygame)

Use Python to write a snake game (pygame)

Courseware address: https://blog.csdn.net/a772304419/article/details/130087202

local path:

cd /D/Workspace/Python/teach-demo/03-snake-demo

We want to use Python to write the snake game, we need to use the pygame module, that is, enter in the PyCharm terminal

pip install pygame

The installation is complete. There are three important objects
in pygame , which are pygame.display—set scene display, including page size, page title, page update (refresh), etc.; pygame.time—set all time-related settings, game frame rate, game Duration, etc.; pygame.event – ​​set event-related processing, such as mouse click event, keyboard press event, etc.; pygame.draw – draw graphics to the interface.



1. Build the initial framework

To make the Snake game, the first step is to build an initial interface, including setting the size of the interface, setting the closing interface event, setting the frame rate, rendering the page background and updating the page, etc. The specific code is as follows:

import pygame
# 定义显示窗口的W(宽) H(高)
W = 960
H = 800
size = (960, 600)
pygame.init() # 初始化界面
window = pygame.display.set_mode(size)
pygame.display.set_caption("贪吃蛇大作战")
showWindow = True
clock = pygame.time.Clock() #时钟控制
while showWindow:
    # 处理事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            showWindow = False

    # 页面渲染
    pygame.draw.rect(window, (255, 255, 255), (0, 0, W, H))
    pygame.display.flip() #更新整个待显示的Surface对象到屏幕上
    clock.tick(30)# 设置帧频

At this time, running the program can display a normal interface, click close in the upper right corner to close the program! Not only that, but also a simple rendering of the page, that is, changing the background color of the interface to white;

2. Draw the scene and the snake head

We can divide the entire interface according to row and column col, so each block on the page corresponds to a coordinate (row, col), so we only need to set the corresponding row and column col to draw the snake head and food;
the specific code is as follows:

class Point:#使用Point类来接受row col
    def __init__(self, row=0, col=0):
        self.row = row
        self.col = col
    def copy(self):
        return Point(self.row, self.col)

ROW = 40 #行数
COL = 30 #列数
def rect(point, color):
    cell_width = W/COL
    cell_height = H/ROW
    left = point.col*cell_width
    top = point.row*cell_height
    pygame.draw.rect(
        window, color,
        (left, top, cell_width, cell_height)
    )

Next, draw the snake head and food in the game loop , as shown below:

	# 定义蛇头
	head = Point(row=int(ROW/2), col=int(COL/2))# 在页面中心定义蛇头
	head_color = (0, 128, 128) # 用RGB表示颜色
	# 定义食物
	food = ge_food() #ge_food()是随机产生食物的函数 防止食物与蛇重合
	food_color = (255, 255, 0)
    # 画蛇头
    rect(head, head_color)
    # 画食物
    rect(food, food_color)

3. Move the snake head

We need to know that the snake body moves with the snake head. Therefore, first of all, we need to make the snake head move, and the snake head is uniquely positioned using row and col in the interface. We only need to understand the moving logic, as follows:

left-->head.col-1,row不变
right-->head.col+1,row不变
top-->head.row-1,col不变
down-->head.row+1,col不变

At the same time, you need to know that when the snake head moves to the right, it cannot change the direct direction to move to the left, which is unreasonable; when it moves upward, it cannot directly change the direction and move downward; other directions are similar; although the number of rows and columns we change each
time It is 1, but we write the above changes in the game loop, so we can see the snake head moving constantly on the interface.

# 处理事件
direct = 'left' #默认移动方向为left
While showWindow:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            showWindow = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                if direct=='left' or direct=='right':
                    direct = "top"
            elif event.key == pygame.K_DOWN:
                if direct == 'left' or direct == 'right':
                    direct = "down"
            elif event.key == pygame.K_LEFT:
                if direct=='top' or direct=='down':
                    direct = 'left'
            elif event.key == pygame.K_RIGHT:
                if direct == 'top' or direct == 'down':
                    direct = 'right'
      # 移动蛇头
    if direct == 'left':
        head.col-=1  # 注意 direct = 'left'与head.col-=1不能写在一起 因为蛇头要一直移动
    elif direct == 'right':
        head.col+=1
    elif direct == 'top':
        head.row-=1
    else:
        head.row+=1

4. Draw the snake body

Drawing the snake body is also very simple. We only need to store the coordinates of the snake body in a snakes list. When the snake head moves, we only need to move the snake body in the direction of the snake head and discard the last element in the list. To put it simply, when we write a program, we need to insert the snake head coordinates into the snake body list snakes before the snake head moves, and discard the last coordinate in the snakes.

	snake_color = (128, 128, 128)
	snakes = [] #定义蛇身列表
    # 将蛇头插入到snakes列表中
    snakes.insert(0, head.copy())
    # 将最后一个元素删除
    snakes.pop()
    # 画蛇身
    for snake in snakes:
        rect(snake, snake_color)

5. Solve related deficiencies

Here, our snake game still has many deficiencies, that is, to solve the problem of the snake hitting the wall, the problem of the snake eating the body of the snake, and the problem of the growth of the snake after eating food, which will be solved one by one here; the specific code is as
follows :

	# 判断蛇是否吃到东西
    eat = False
    if head.row == food.row and head.col == food.col:# 蛇吃到食物
        eat = True
    if eat:# 吃到食物就要产生新的食物
        food = ge_food() #随机产生食物的函数 返回Point
    # 将蛇头插入到snakes列表中
    snakes.insert(0, head.copy())
    # 将最后一个元素删除
    if not eat:
        snakes.pop()
     # 判断蛇是否死亡
    dead = False
    # 判断蛇是否撞墙
    if head.col<0 or head.row<0 or head.row>=ROW or head.col>=COL:
        dead = True
    # 判断蛇是否撞蛇身
    for snake in snakes:
        if snake.row==head.row and snake.col==head.col:
            dead = True
            break
    if dead:
        showWindow = False

It can be done more finely here. Here I set it to exit the interface directly once the snake hits the wall or the snake bites the snake.

6. Display of running results

insert image description here
The yellow ones are randomly generated food, while the dark ones are snake heads, which will grow into a snake body when the snake head eats food. Due to the tight time, only the basic functions have been completed, and will continue to be improved in the later stage, including the setting of various game modes, endless mode, breakthrough mode, etc., as well as the addition of background pictures and background music, and you can even use custom pictures. Set the display of the snake head and so on.

7. All code display

import pygame
import random
class Point:
    def __init__(self, row=0, col=0):
        self.row = row
        self.col = col
    def copy(self):
        return Point(self.row, self.col)
# 定义显示窗口的W(宽) H(高)
W = 800
H = 600
snakes = [] #定义蛇身列表
def ge_food():
    while True:
        pos = Point(random.randint(0, ROW - 1), random.randint(0, COL - 1))
        is_collide = False
        if pos.row == head.row and pos.col == head.col:  # 与蛇头重合
            is_collide = True
        # 与蛇身碰撞
        for snake in snakes:
            if (snake.row == pos.row and snake.col == pos.col):
                is_collide = True
                break
        if not is_collide:
            return pos
ROW = 40 #行数
COL = 30 #列数
size = (W, H)
pygame.init() # 初始化界面
window = pygame.display.set_mode(size)
pygame.display.set_caption("贪吃蛇大作战")
bak_color = (255, 255, 255)
# 定义蛇头
head = Point(row=int(ROW/2), col=int(COL/2))
head_color = (0, 128, 128)
# 定义食物
food = ge_food()
food_color = (255, 255, 0)

snake_color = (128, 128, 128)
direct = 'left'
def rect(point, color):
    cell_width = W/COL
    cell_height = H/ROW
    left = point.col*cell_width
    top = point.row*cell_height
    pygame.draw.rect(
        window, color,
        (left, top, cell_width, cell_height)
    )

showWindow = True
clock = pygame.time.Clock() #时钟控制
while showWindow:
    # 处理事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            showWindow = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                if direct=='left' or direct=='right':
                    direct = "top"
            elif event.key == pygame.K_DOWN:
                if direct == 'left' or direct == 'right':
                    direct = "down"
            elif event.key == pygame.K_LEFT:
                if direct=='top' or direct=='down':
                    direct = 'left'
            elif event.key == pygame.K_RIGHT:
                if direct == 'top' or direct == 'down':
                    direct = 'right'
    # 判断蛇是否吃到东西
    eat = False
    if head.row == food.row and head.col == food.col:# 蛇吃到食物
        eat = True
    if eat:# 吃到食物就要产生新的食物
        food = ge_food()
    # 将蛇头插入到snakes列表中
    snakes.insert(0, head.copy())
    # 将最后一个元素删除
    if not eat:
        snakes.pop()
    # 移动蛇头
    if direct == 'left':
        head.col-=1  # 注意 direct = 'left'与head.col-=1不能写在一起 因为蛇头要一直移动
    elif direct == 'right':
        head.col+=1
    elif direct == 'top':
        head.row-=1
    else:
        head.row+=1
    # 判断蛇是否死亡
    dead = False
    # 判断蛇是否撞墙
    if head.col<0 or head.row<0 or head.row>=ROW or head.col>=COL:
        dead = True
    # 判断蛇是否撞蛇身
    for snake in snakes:
        if snake.row==head.row and snake.col==head.col:
            dead = True
            break
    if dead:
        showWindow = False
    # 页面渲染
    pygame.draw.rect(window, bak_color, (0, 0, W, H))
    # 这里需要注意 绘制食物与蛇头要在绘制背景之后 因为黑色的背景颜色会覆盖一切
    # 画蛇头
    rect(head, head_color)
    # 画蛇身
    for snake in snakes:
        rect(snake, snake_color)
    # 画食物
    rect(food, food_color)
    pygame.display.flip() #更新整个待显示的Surface对象到屏幕上

    clock.tick(15)# 设置帧频 可以用来控制蛇头移动的速度

Guess you like

Origin blog.csdn.net/a772304419/article/details/130087202