python实现贪吃蛇游戏

文章目录

        • 1、项目说明
        • 2、项目预览
        • 3、开发必备
        • 4、贪吃蛇代码实现
          • 4.1、窗口和基本参数实现
          • 4.2、绘制背景
          • 4.3、绘制墙壁
          • 4.4、绘制贪吃蛇
          • 4.5、绘制食物
          • 4.6、实现长度信息显示
          • 4.7、定义游戏暂停界面
          • 4.8、定义贪吃蛇死亡界面
          • 4.9、实现贪吃蛇碰撞效果
          • 4.10、实现添加食物功能
          • 4.11、实现贪吃蛇身体增长功能
          • 4.12、实现贪吃蛇吃食物功能
          • 4.12、贪吃蛇死亡功能
          • 4.13、实现键盘控制游戏
          • 4.14、更新贪吃蛇位置功能
          • 4.15、更新游戏画面和处理用户输入功能
        • 5、结束

1、项目说明

介绍

贪吃蛇是我们小时候的一款经典游戏,毕竟在那个Nokia称霸的年代,这款游戏可是经典中的经典啊!而用Python(蛇)玩Snake(贪吃蛇),那再合适不过了。

需求分析

我们先来回顾下贪吃蛇中的游戏元素及游戏规则:

  1. 需要有贪吃蛇、有食物
  2. 需要能控制贪吃蛇来上下移动获取食物
  3. 贪吃蛇在吃取食物后,自身长度增加,同时食物消失并随机生成新的食物
  4. 如果贪吃蛇触碰到四周墙壁或是触碰到自己身体时,则游戏结束
2、项目预览

image-20231219171058611

3、开发必备

游戏开发运行环境

  1. python3.7以上
  2. 开发工具PyCharm
  3. Python内置模块:random
  4. 第三方模块:pygame
4、贪吃蛇代码实现
4.1、窗口和基本参数实现

分析

我们首先需要初始化一些参数:游戏界面大小、蛇和食物的参数以及一些游戏边界和障碍的设置等等

  1. 初始化 Pygame 模块,让游戏程序能够使用 Pygame 提供的功能;
  2. 设置游戏窗口的大小;
  3. 定义两个字体对象,分别用于绘制不同大小的文字;
  4. 定义了一个方向列表,包含了贪吃蛇可能移动的四个方向;
  5. 定义了 X 和 Y 的坐标列表,方便后续使用;
  6. 定义了几种不同的食物颜色,用于给不同等级的食物染色;
  7. 定义了障碍物(墙)的位置和尺寸以及食物的初始位置和尺寸;
  8. 设置蛇的一些参数,如速度、长度、宽度和高度等;
  9. 设置游戏的等级和初始等待时间;
  10. 设置游戏窗口的标题和一些初始化的变量。

代码实现

import pygame

if __name__ == "__main__":
    # 初始化pygame
    pygame.init()
    
    # 游戏界面大小
    GAME_SIZE = [900,900]
    SIZE = [GAME_SIZE[0],GAME_SIZE[1]+100]
    
    # 字体设置
    FONT_S = pygame.font.SysFont('Times', 50)
    FONT_M = pygame.font.SysFont('Times', 90)
    
    # 方向列表
    DIRECTION = ['up','right','down','left']
    
    # X 和 Y 坐标列表
    X_LIST = [x for x in range(GAME_SIZE[0])]
    Y_LIST = [y for y in range(GAME_SIZE[1])]
    
    # 食物颜色
    FOOD_COLORS = ((46,139,87),(199,21,133),(25,25,112),(255,215,0))

    # 墙
    wall_list = [[100,200],[600,500],[350,200],[500,800]]
    WALL_WIDTH,WALL_HEIGHT = 30,30

    # 食物
    food_list = [(150,200,1),(300,500,1),(740,542,1),(300,600,1),(700,600,1)]
    FOOD_WIDTH,FOOD_HEIGHT = 14,14
    
    # 创建游戏窗口 900*1000
    screen = pygame.display.set_mode(SIZE)
    
    # 蛇的参数
    snake_list = [[100+12*4,100],[100+12*3,100],[100+12*2,100],[100+12*1,100],[100,100]]
    SNAKE_WIDTH,SNAKE_HEIGHT = 12,12
    snake_v = 0
    count_time = 0

    # 等级
    frame = 0.05
    level = 1
    
    # 主循环
    running = True
    pause = False
    dead = False
    head = 'right'
4.2、绘制背景

分析

定义一个名为 draw_background() 的函数,它用来绘制游戏的背景。

具体的绘制过程如下:

  1. screen.fill(COLORS['white']) 使用白色填充背景屏幕,将屏幕背景设置为白色。
  2. pygame.draw.rect(screen,COLORS['black'],(-100,GAME_SIZE[1],3000,200),0) 绘制一个长方形作为地面。该矩形的位置 (x, y)(-100, GAME_SIZE[1]),宽度为 3000,高度为 200。矩形的颜色是 COLORS 字典中的 black

通过调用 draw_background() 函数,可以在游戏屏幕上绘制出白色的背景以及一个黑色的长方形作为地面

代码

def draw_background():
    # white background
    screen.fill(COLORS['white'])
    pygame.draw.rect(screen,COLORS['black'],(-100,GAME_SIZE[1],3000,200),0)
4.3、绘制墙壁

分析

定义一个名为 draw_wall() 的函数,它用来绘制游戏中的墙壁。

具体的绘制过程如下:

  1. 使用 for 循环遍历墙壁列表 wall_list 中的每个元素,每个元素表示一个墙壁的位置。
  2. 对于每个墙壁位置,调用 pygame.draw.rect() 函数绘制一个矩形,位置 (x, y)(xy[0]-WALL_WIDTH/2, xy[1]-WALL_WIDTH/2),宽度为 WALL_WIDTH,高度为 WALL_HEIGHT。矩形的颜色是 COLORS 字典中的 darkgray

通过调用 draw_wall() 函数,可以在游戏屏幕上绘制出墙壁。每个墙壁由一个矩形组成,矩形的位置和大小均在调用时指定。注意,墙壁的位置需要减去一半的墙壁宽度和高度,以便将矩形的中心对齐到墙壁位置上。

代码

def draw_wall():
    for xy in wall_list:
        pygame.draw.rect(screen,COLORS['darkgray'],(xy[0]-WALL_WIDTH/2,xy[1]-WALL_WIDTH/2,WALL_WIDTH,WALL_HEIGHT),0)
4.4、绘制贪吃蛇

分析

定义一个名为 draw_snake() 的函数,它用来绘制游戏中的蛇。

具体的绘制过程如下:

  1. 使用 snake_list 列表中的第一个元素作为蛇头,调用 pygame.draw.circle() 函数绘制一个圆作为蛇头。圆心的位置 (x, y)(head[0], head[1]),半径为 SNAKE_WIDTH/2。圆的颜色是 COLORS 字典中的 darkred
  2. 对于蛇身上的其他部分(不包括蛇头),使用 for 循环遍历 snake_list 中除了第一个元素以外的其他元素。对于每个元素,调用 pygame.draw.rect() 函数绘制一个矩形,位置 (x, y)(xy[0]-SNAKE_WIDTH/2, xy[1]-SNAKE_WIDTH/2),宽度为 SNAKE_WIDTH,高度为 SNAKE_HEIGHT,边框宽度为 2。矩形的颜色与圆的颜色相同。

通过调用 draw_snake() 函数,可以在游戏屏幕上绘制出蛇。蛇头使用一个圆表示,蛇身使用一系列矩形拼接而成,每个矩形的位置和大小均在调用时指定。注意,蛇头和蛇身分别使用了不同的绘制方式,因为它们形状不同。

代码

def draw_snake():
    head = snake_list[0]
    pygame.draw.circle(screen,COLORS['darkred'],(head[0],head[1]),int(SNAKE_WIDTH/2),0)
    for xy in snake_list[1:]:
        pygame.draw.rect(screen,COLORS['darkred'],(xy[0]-SNAKE_WIDTH/2,xy[1]-SNAKE_WIDTH/2,SNAKE_WIDTH,SNAKE_HEIGHT),2)
4.5、绘制食物

分析

定义一个名为 draw_food() 的函数,它用来绘制食物物品。

具体的绘制过程如下:

  1. 使用 for 循环遍历食物列表 food_list 中的每个元素,每个元素表示一个食物的位置和类型。
  2. 对于每个食物位置,调用 pygame.draw.rect() 函数绘制一个矩形,位置 (x, y)(xyz[0]-FOOD_WIDTH/2, xyz[1]-FOOD_WIDTH/2),宽度为 FOOD_WIDTH,高度为 FOOD_HEIGHT。矩形的颜色是 FOOD_COLORS 列表中根据食物类型 xyz[2] 所对应的颜色值。

通过调用 draw_food() 函数,可以在游戏屏幕上绘制出各种类型的食物。每个食物由一个矩形组成,矩形的位置和大小均在调用时指定。注意,食物的位置需要减去一半的食物宽度和高度,以便将矩形的中心对齐到食物位置上。

代码

# 绘制食物
def draw_food():
    # 遍历食物列表
    for xyz in food_list:
        # 获取食物位置和类型,绘制食物矩形
        pygame.draw.rect(screen, FOOD_COLORS[xyz[2]-1], (xyz[0] - FOOD_WIDTH/2, xyz[1] - FOOD_WIDTH/2, FOOD_WIDTH, FOOD_HEIGHT), 0)
4.6、实现长度信息显示

分析

定义一个名为 draw_context() 的函数,它用来绘制游戏的上下文信息。

具体的绘制过程如下:

  1. 创建一个文本对象 txt,文本内容是 "Snake length: " 连接上蛇身长度 len(snake_list)-1。使用 FONT_M 字体来渲染文本,文本颜色是 COLORS 字典中的 lightblue
  2. 计算文本的位置 (x, y),其中 x 的初始值为 10y 的初始值为 GAME_SIZE[1]+(int((SIZE[1]-GAME_SIZE[1])/2))。接下来,将 y 的值减去文本字体尺寸的一半,以实现垂直居中。
  3. 使用 screen.blit() 函数将文本对象绘制到屏幕上,位置为 (x, y)

通过调用 draw_context() 函数,可以在游戏屏幕上绘制出游戏的上下文信息,包括蛇的长度

代码

# 绘制游戏上下文信息
def draw_context():
    # 创建文本对象,包括蛇的长度信息
    txt = FONT_M.render('Snake length: '+str(len(snake_list)-1),True,COLORS['lightblue'])
    # 计算文本位置
    x,y = 10,GAME_SIZE[1]+(int((SIZE[1]-GAME_SIZE[1])/2))
    y = int(y-FONT_M.size('Count')[1]/2)
    # 绘制文本
    screen.blit(txt,(x,y))
4.7、定义游戏暂停界面

分析

定义一个名为 draw_pause() 的函数,它用于在游戏暂停时绘制暂停界面。

具体的绘制过程如下:

  1. 创建一个透明表面 s,大小与 SIZE 相同,并填充为带有半透明的白色 (255,255,255,220)
  2. 使用 screen.blit() 函数将表面 s 绘制到屏幕上的位置 (0, 0),实现背景的半透明效果。
  3. 创建一个文本对象 txt,文本内容为 “PAUSE”,使用 FONT_M 字体渲染文本,文本颜色为 COLORS 字典中的 darkgray
  4. 计算文本的位置 (x, y),其中 x 的初始值为 SIZE[0]/2y 的初始值为 SIZE[1]/2。然后,将 xy 的值减去文本字体尺寸的一半,以实现水平和垂直居中。
  5. 使用 screen.blit() 函数将文本对象绘制到屏幕上的位置 (x, y)

通过调用 draw_pause() 函数,可以在游戏屏幕上绘制暂停界面。呈现为一个半透明的背景,并显示 “PAUSE” 文本在中间位置。注意,需要使用透明度为 220 的色彩值来填充表面,以实现半透明效果。

代码

# 绘制暂停界面
def draw_pause():
    # 创建一个带有半透明的透明表面
    s = pygame.Surface(SIZE, pygame.SRCALPHA)
    s.fill((255,255,255,220))
    # 将透明表面绘制到屏幕上
    screen.blit(s, (0,0))
    # 创建文本对象,显示 "PAUSE"
    txt = FONT_M.render('PAUSE',True,COLORS['darkgray'])
    # 计算文本的位置
    x,y = SIZE[0]/2,SIZE[1]/2
    x,y = int(x-FONT_M.size('PAUSE')[0]/2),int(y-FONT_M.size('PAUSE')[1]/2)
    # 绘制文本
    screen.blit(txt,(x,y))
4.8、定义贪吃蛇死亡界面

分析

定义一个名为 draw_dead() 的函数,用于在游戏中玩家死亡时绘制死亡界面。

具体的绘制过程如下:

  1. 创建一个透明表面 s,大小与 SIZE 相同,并填充为带有半透明的白色 (255,255,255,240)
  2. 使用 screen.blit() 函数将表面 s 绘制到屏幕上的位置 (0, 0),实现背景的半透明效果。
  3. 创建一个文本对象 txt,文本内容为 “YOU DEAD”,使用 FONT_M 字体渲染文本,文本颜色为 COLORS 字典中的 black
  4. 计算文本的位置 (x, y),其中 x 的初始值为 SIZE[0]/2y 的初始值为 SIZE[1]/2。然后,将 xy 的值减去文本字体尺寸的一半,以实现水平和垂直居中。
  5. 使用 screen.blit() 函数将文本对象绘制到屏幕上的位置 (x, y)

通过调用 draw_dead() 函数,可以在游戏屏幕上绘制死亡界面。呈现为一个更加明亮的背景,并显示 “YOU DEAD” 文本在中间位置。注意,需要使用透明度为 240 的色彩值来填充表面,以实现更明显的半透明效果。

代码

# 绘制死亡界面
def draw_dead():
    # 创建一个更明亮的带有半透明的透明表面
    s = pygame.Surface(SIZE, pygame.SRCALPHA)
    s.fill((255,255,255,240))
    # 将透明表面绘制到屏幕上
    screen.blit(s, (0,0))
    # 创建文本对象,显示 "YOU DEAD"
    txt = FONT_M.render('YOU DEAD',True,COLORS['black'])
    # 计算文本的位置
    x,y = SIZE[0]/2,SIZE[1]/2
    x,y = int(x-FONT_M.size('YOU DEAD')[0]/2),int(y-FONT_M.size('YOU DEAD')[1]/2)
    # 绘制文本
    screen.blit(txt,(x,y))
4.9、实现贪吃蛇碰撞效果

分析

定义一个名为 rect_cover(rect1,rect2) 的函数,用于判断两个矩形是否相交。

具体的判断过程如下:

  1. 将每个矩形的四个边界值提取出来,并转换为整数类型。其中,left1 表示矩形 rect1 左边界,right1 表示矩形 rect1 右边界,up1 表示矩形 rect1 上边界,down1 表示矩形 rect1 下边界;同理,left2right2up2down2 分别为矩形 rect2 的四个边界值。
  2. 如果矩形 rect1 和矩形 rect2 相交,则它们的边界值应该满足下面的四种情况之一:
  • rect2 的右边界 right2 小于或等于 rect1 的左边界 left1
  • rect2 的左边界 left2 大于或等于 rect1 的右边界 right1
  • rect2 的下边界 down2 小于或等于 rect1 的上边界 up1
  • rect2 的上边界 up2 大于或等于 rect1 的下边界 down1

如果不满足上述四种情况,则认为它们相交,此时函数返回值为 True;否则,返回值为 False

代码

# 判断两个矩形是否相交
def rect_cover(rect1, rect2):
    # 提取矩形1的边界值
    left1 = int(rect1[0])
    right1 = int(rect1[0] + rect1[2])
    up1 = int(rect1[1])
    down1 = int(rect1[1] + rect1[3])

    # 提取矩形2的边界值
    left2 = int(rect2[0])
    right2 = int(rect2[0] + rect2[2])
    up2 = int(rect2[1])
    down2 = int(rect2[1] + rect2[3])

    # 判断两个矩形是否相交
    if not (right2 <= left1 or left2 >= right1 or down2 <= up1 or up2 >= down1):
        return True

    return False
4.10、实现添加食物功能

分析

定义一个名为 add_food() 的函数,用于向食物列表 food_list 中添加食物。

具体的过程如下:

  1. 进入一个无限循环 while(True)
  2. 在每次循环中,生成一个由随机选择的 X_LIST 中的元素、随机选择的 Y_LIST 中的元素和随机选择的 [1,2,3,4] 中的元素组成的列表 xyz
  3. 检查 xyz 是否存在于墙壁列表 wall_list 中。如果不存在,说明 xyz 没有被墙壁占据,可以作为食物的位置。
  4. xyz 添加到食物列表 food_list 中,并使用 break 语句跳出循环。

通过调用 add_food() 函数,可以在游戏中不断添加新的食物位置。在添加食物之前,会进行检查,确保新位置不与墙壁重叠。

代码

import random

# 向食物列表中添加食物
def add_food():
    while True:
        # 随机选择X、Y和数值
        xyz = [
            random.choice(X_LIST),
            random.choice(Y_LIST),
            random.choice([1, 2, 3, 4])
        ]
        
        # 检查食物位置是否与墙壁重叠
        if xyz not in wall_list:
            # 将食物位置添加到食物列表
            food_list.append(xyz)
            break  # 跳出循环
4.11、实现贪吃蛇身体增长功能

分析

一个名为 add_body() 的函数,用于向蛇的身体列表 snake_list 中添加身体节。

具体的过程如下:

  1. 使用一个循环来控制添加的身体节的数量,循环的次数由参数 length 决定,默认为1。
  2. 在每次循环中,获取蛇身体列表 snake_list 中的倒数第二个和最后一个元素,并分别赋值给 last2last1
  3. 检查最后两个身体节的相对位置:如果它们在垂直方向上相等,则代表这两节身体是竖直排列的;如果它们在水平方向上相等,则代表这两节身体是水平排列的。
  4. 根据身体节的相对位置,确定新的身体节的坐标。如果是竖直排列,根据最后一节的朝向选择向上或向下添加一节;如果是水平排列,根据最后一节的朝向选择向左或向右添加一节。
  5. 将新的身体节坐标添加到蛇的身体列表 snake_list 中。

通过调用 add_body() 函数,可以向蛇的身体列表中添加指定数量的身体节,以延长蛇的长度。

代码

# 向蛇的身体列表中添加身体节
def add_body(length=1):
    for c in range(length):
        # 获取最后两个身体节的坐标
        last2, last1 = snake_list[-2], snake_list[-1]
        
        if last2[0] == last1[0]:  # 如果最后两节身体在垂直方向上相等
            if last2[1] > last1[1]:  # 朝下
                # 向下添加一节身体
                snake_list.append([last1[0], last1[1] - SNAKE_WIDTH])
            else:
                # 向上添加一节身体
                snake_list.append([last1[0], last1[1] + SNAKE_WIDTH])
        else:  # 如果最后两节身体在水平方向上相等
            if last2[0] > last1[0]:  # 朝右
                # 向右添加一节身体
                snake_list.append([last1[0] - SNAKE_WIDTH, last1[1]])
            else:
                # 向左添加一节身体
                snake_list.append([last1[0] + SNAKE_WIDTH, last1[1]])
4.12、实现贪吃蛇吃食物功能

分析

定义一个检查蛇头是否与食物碰撞的函数。具体的实现逻辑如下:

  1. 首先获取蛇的头部坐标 snake_list[0],并计算出蛇头的矩形区域 snake_head_rect。矩形区域的坐标为 (蛇头x坐标-SNAKE_WIDTH/2, 蛇头y坐标-SNAKE_WIDTH/2, SNAKE_WIDTH, SNAKE_HEIGHT)
  2. 遍历食物列表 food_list,获取每个食物的坐标 xyz。再计算出食物的矩形区域 food_rect。矩形区域的坐标为 (食物x坐标-FOOD_WIDTH/2, 食物y坐标-FOOD_WIDTH/2, FOOD_WIDTH, FOOD_HEIGHT)
  3. 调用 rect_cover 函数判断蛇头的矩形区域是否与当前食物的矩形区域重叠。如果重叠,则表示蛇头与该食物碰撞了。
  4. 如果蛇头与食物碰撞,则调用 add_body 函数将食物的类型 xyz[2] 加入到蛇的身体中,并从食物列表中移除该食物。
  5. 最后返回一个布尔值,表示蛇头是否与任何食物碰撞。

代码

# 检查是否有食物被吃掉
def check_food():
    # 获取蛇头的位置
    first = snake_list[0]
    
    # 创建蛇头的矩形区域
    snake_head_rect = (first[0] - SNAKE_WIDTH/2, first[1] - SNAKE_WIDTH/2, SNAKE_WIDTH, SNAKE_HEIGHT)
    
    # 遍历食物列表
    for i in range(len(food_list)):
        xyz = food_list[i]
        
        # 创建食物的矩形区域
        food_rect = (xyz[0] - FOOD_WIDTH/2, xyz[1] - FOOD_WIDTH/2, FOOD_WIDTH, FOOD_HEIGHT)
        
        # 检查蛇头是否与食物重叠
        if rect_cover(snake_head_rect, food_rect):
            # 添加食物对应的身体节
            add_body(xyz[2])
            
            # 从食物列表中删除已被吃掉的食物
            del food_list[i]
            
            return True
  
    return False
4.12、贪吃蛇死亡功能

分析

定义一个check_dead() 函数用于检查蛇是否死亡,即判断蛇头是否与边缘、墙壁或自身的身体发生碰撞。具体过程如下:

  1. 获取蛇头的位置,即蛇列表中的第一个元素。
  2. 创建蛇头的矩形区域,以便后续与边缘、墙壁或自身的身体进行碰撞检测。
  3. 检查蛇头是否与边缘发生碰撞,即蛇头是否超出了游戏区域的范围。如果超出范围,则视为蛇死亡,返回 True
  4. 遍历墙壁列表,获取每个墙壁的坐标。
  5. 创建墙壁的矩形区域,以便后续与蛇头的矩形区域进行碰撞检测。
  6. 检查蛇头是否与墙壁发生碰撞。如果发生碰撞,则视为蛇死亡,返回 True
  7. 遍历蛇列表中除蛇头外的元素,即蛇的身体。
  8. 创建身体节的矩形区域,以便后续与蛇头的矩形区域进行碰撞检测。
  9. 检查蛇头是否与自身的身体发生碰撞。如果发生碰撞,则视为蛇死亡,返回 True
  10. 如果以上都未发生,即蛇未死亡,返回 False

代码

# 检查蛇是否死亡
def check_dead():
    # 获取蛇头的位置
    first = snake_list[0]
    
    # 创建蛇头的矩形区域
    snake_head_rect = (first[0] - SNAKE_WIDTH/2, first[1] - SNAKE_WIDTH/2, SNAKE_WIDTH, SNAKE_HEIGHT)
    
    # 检查蛇头是否与边缘发生碰撞
    if first[0] < 0 or first[0] > GAME_SIZE[0] or first[1] < 0 or first[1] > GAME_SIZE[1]:
        return True
    
    # 检查蛇头是否与墙壁发生碰撞
    for xy in wall_list:
        wall_rect = (xy[0] - WALL_WIDTH/2, xy[1] - WALL_WIDTH/2, WALL_WIDTH, WALL_HEIGHT)
        if rect_cover(snake_head_rect, wall_rect):
            return True
    
    # 检查蛇头是否与自身的身体发生碰撞
    for xy in snake_list[1:]:
        body_rect = (xy[0] - SNAKE_WIDTH/2, xy[1] - SNAKE_WIDTH/2, SNAKE_WIDTH, SNAKE_HEIGHT)
        if rect_cover(snake_head_rect, body_rect):
            return True
    
    return False
4.13、实现键盘控制游戏

分析

编写一个处理事件的循环,它的作用是根据用户的输入来控制游戏的行为。主要包含以下几个事件处理:

  1. pygame.QUIT 事件:当用户点击窗口的关闭按钮时,这个事件会触发。在这段代码中,会将 running 变量设置为 False,从而退出游戏循环。
  2. pygame.MOUSEBUTTONDOWN 事件:当用户点击鼠标按钮时,这个事件会触发。在这段代码中,每次点击鼠标按钮会切换 pause 变量的状态,用来暂停游戏。
  3. pygame.KEYUP 事件:当用户松开键盘上的按键时,这个事件会触发。在这段代码中,根据松开的按键来控制蛇头的移动方向。具体的处理逻辑如下:
    • 如果松开的键是 K_LEFT(即左箭头键),并且当前蛇头方向不是向右(head 不为 ‘right’),则将新的蛇头方向设置为向左(‘left’)。
    • 如果松开的键是 K_RIGHT(即右箭头键),并且当前蛇头方向不是向左(head 不为 ‘left’),则将新的蛇头方向设置为向右(‘right’)。
    • 如果松开的键是 K_UP(即上箭头键),并且当前蛇头方向不是向下(head 不为 ‘down’),则将新的蛇头方向设置为向上(‘up’)。
    • 如果松开的键是 K_DOWN(即下箭头键),并且当前蛇头方向不是向上(head 不为 ‘up’),则将新的蛇头方向设置为向下(‘down’)。

代码

# 事件循环
while running:
    # 获取所有事件并逐个处理
    for event in pygame.event.get():
        # 处理关闭窗口事件
        if event.type == pygame.QUIT:
            # 退出游戏循环
            running = False
            break
        # 处理鼠标点击事件
        elif event.type == pygame.MOUSEBUTTONDOWN:
            # 切换暂停状态(pause变量为True时暂停,为False时正常运行)
            pause = not pause
        # 处理按键松开事件
        elif event.type == pygame.KEYUP:
            # 如果松开的键是左箭头键,并且当前蛇头方向不是向右,则将新的蛇头方向设置为向左
            if event.key == K_LEFT:
                if head in ['up','down']:
                    head = 'left'
            # 如果松开的键是右箭头键,并且当前蛇头方向不是向左,则将新的蛇头方向设置为向右
            elif event.key == K_RIGHT:
                if head in ['up','down']:
                    head = 'right'
            # 如果松开的键是上箭头键,并且当前蛇头方向不是向下,则将新的蛇头方向设置为向上
            elif event.key == K_UP:
                if head in ['left','right']:
                    head = 'up'
            # 如果松开的键是下箭头键,并且当前蛇头方向不是向上,则将新的蛇头方向设置为向下
            elif event.key == K_DOWN:
                if head in ['left','right']:
                    head = 'down'
4.14、更新贪吃蛇位置功能

分析

在游戏不暂停且蛇没有死亡的情况下,更新蛇的位置。具体操作如下:

  • 计算时间:根据帧率 frame 和游戏难度 level 来计算游戏进行的时间。
  • 获取蛇的头部位置:将蛇列表中的第一个元素作为蛇头的当前位置。
  • 移动蛇身:将蛇列表中索引为1以及之后的元素赋值为索引减1以及之前的元素,即每个蛇身的位置向前移动一个单位。
  • 根据当前头部的方向更新蛇头的位置:根据变量 head 的值,更新蛇头的位置。如果头部方向是 ‘up’,则将头部位置的纵坐标减去一个单位;如果方向是 ‘down’,则将纵坐标加上一个单位;如果方向是 ‘left’,则将横坐标减去一个单位;如果方向是 ‘right’,则将横坐标加上一个单位。

代码

# 如果游戏没有暂停,并且蛇没有死亡,则执行以下操作
if not pause and not dead:
    # 计算时间
    count_time += frame * level
    
    # 获取蛇的头部位置
    first = snake_list[0]
    
    # 将蛇身的每个部分向前移动一个单位
    snake_list[1:] = snake_list[:-1]
    
    # 根据当前头部的方向更新蛇头的位置
    if head == 'up':
        snake_list[0] = [first[0], first[1] - SNAKE_WIDTH]
    elif head == 'down':
        snake_list[0] = [first[0], first[1] + SNAKE_WIDTH]
    elif head == 'left':
        snake_list[0] = [first[0] - SNAKE_WIDTH, first[1]]
    elif head == 'right':
        snake_list[0] = [first[0] + SNAKE_WIDTH, first[1]]
4.15、更新游戏画面和处理用户输入功能

分析

负责更新游戏画面和处理用户输入,具体操作如下:

  • 绘制背景:绘制游戏的背景。
  • 绘制隧道:绘制游戏中的隧道。
  • 选择物品:绘制游戏的角色,即蛇。
  • 绘制食物:绘制游戏中的食物。
  • 绘制得分:绘制游戏中的得分。
  • 如果游戏暂停且蛇没有死亡,绘制暂停界面。
  • 如果蛇死亡,绘制游戏结束界面。
  • 刷新显示:更新显示,将绘制的内容显示在屏幕上。
  • 暂停 20 毫秒:暂停游戏的执行一段时间,控制游戏的帧率。
  • 检查是否死亡:检查当前游戏状态是否为死亡状态。
  • 检查是否吃到食物:检查蛇是否吃到食物。
  • 关闭 pygame:结束游戏。

代码

# 绘制背景
draw_background()

# 绘制隧道
draw_wall()

# 选择物品
draw_snake()

# 绘制食物
draw_food()

# 绘制得分
draw_context()

# 如果游戏暂停且蛇没有死亡,绘制暂停界面
if not dead and pause:
    draw_pause()

# 如果蛇死亡,绘制游戏结束界面
if dead:
    draw_dead()

# 刷新显示
pygame.display.flip()

# 暂停 20 毫秒
pygame.time.delay(int(frame/level*1000))

# 检查是否死亡
dead = check_dead()

# 检查是否吃到食物
if check_food():
    add_food()

# 关闭 pygame
pygame.quit()
5、结束

需要源码留言

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/258970.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jQuery —— 自定义四位数验证弹框

在提交表单发送请求前&#xff0c;想要校验下&#xff0c;但不想用第三方插件&#xff0c;就自己写了个自定义数字校验码弹框&#xff0c;更稳定些&#xff0c;样式有点low&#xff0c;记录下。 没什么硬性要求的话&#xff0c;可以使用第三方插件&#xff0c;会方便许多样式也…

SQL学习笔记+MySQL+SQLyog工具教程

文章目录 1、前言2、SQL基本语言及其操作2.1、CREATE TABLE – 创建表2.2、DROP TABLE – 删除表2.3、INSERT – 插入数据2.4、SELECT – 查询数据2.5、SELECTDISTINCT – 去除重复值后查询数据2.6、SELECTWHERE – 条件过滤2.7、AND & OR – 运算符2.8、ORDER BY – 排序2…

科研院校和研究所都在用功率放大器做哪些实验

科研院校和研究所在科研工作中常常使用功率放大器进行实验。功率放大器是一种电子设备&#xff0c;其主要功能是将输入信号的功率增加到预定的输出功率水平&#xff0c;并保持信号的波形不失真。它在各个学科领域都有广泛的应用&#xff0c;包括通信、无线电、雷达、生物医学等…

Mac安装Nginx

一起学习 1、确认你的电脑是否安装homebrew&#xff0c;打开电脑终端 输入&#xff1a; /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"2、确认homebrew是否安装成功&#xff0c;在终端输入&#xff1a; br…

Linux中使用HTTP协议进行网络通信的示例——你的“网络信使”

大家好&#xff0c;今天我们要聊聊在Linux中如何使用HTTP协议进行网络通信。听起来有点高大上&#xff0c;但其实并不难&#xff0c;让我们一起来看看&#xff01; 首先&#xff0c;我们要明白HTTP协议是什么。HTTP&#xff0c;全名为超文本传输协议&#xff08;Hypertext Tra…

操作系统课设-银行家算法VS2022

目录 1 目的和要求 2 银行家算法的数据结构 3 进程请求时的资源处理 4 安全性算法的设计思路 5 调试与分析 6 C语言源代码 7 心得体会 1 目的和要求 银行家算法是避免死锁的一种重要方法&#xff0c;能够有效的在资源分配的过程中&#xff0c;对系统的安全性进行检测。通…

搭建自动化 Web 页面性能检测系统 —— 设计篇

页面性能对于用户体验、用户留存有着重要影响&#xff0c;当页面加载时间过长时&#xff0c;往往会伴随着一部分用户的流失&#xff0c;也会带来一些用户差评。性能的优劣往往是同类产品中胜出的影响因素&#xff0c;也是一个网站口碑的重要评判标准。 一、名称解释 前端监控…

猫罐头哪个牌子好性价比高?五大性价比高的品牌推荐

很多猫奴担心猫咪天天吃干猫粮可能会导致营养不足&#xff0c;所以想给猫咪换换口味&#xff0c;改善一下饮食。这时&#xff0c;选择猫罐头是个不错的选择。不过&#xff0c;喂猫罐头也是有一些讲究的。 作为从业6年的宠物护理师来说&#xff0c;作为早在几年就开始接触猫罐头…

AI工具网站汇总——学习的好帮手

一、聊天AI 1.ChatGPT 地表最强AI聊天机器人 网址&#xff1a;https://chat.openai.com 2.Anthropic Anthropic发布的与ChatGPT竞争的聊天机器人 网址&#xff1a;https://www.anthropic.com 3.文心一言 百度全新知识增强大语言模型&#xff01;国产聊天机器人 网址&…

2023大湾区汽车创新大会暨IEEE自动驾驶国际标准研讨会成功举办

2023年12月15日-12月16日&#xff0c;由IEEE ADWG工作组主席孙栋博士、杨子江博士共同主持的2023大湾区汽车创新大会平行主题论坛-IEEE自动驾驶国际标准研讨会在深圳坪山成功举办。图灵奖获得者Joseph Sifakis、英伟达仿真生态总监German Ros、ASAM标准组织CEO Marius Dupuis、…

Seata:打造行业首个分布式事务产品

作者&#xff1a;季敏&#xff0c;阿里云分布式事务产品负责人、Seata 开源项目创始人 微服务架构下数据一致性的挑战 微服务开发的痛点 在 2019 年&#xff0c;我们基于 Dubbo Ecosystem Meetup&#xff0c;收集了 2000 多份关于“在微服务架构&#xff0c;哪些核心问题是开…

边缘计算有哪些常用场景?TSINGSEE边缘AI视频分析技术行业解决方案

随着ChatGPT生成式人工智能的爆发&#xff0c;AI技术在业界又掀起一波新浪潮。值得关注的是&#xff0c;边缘AI智能也在AI人工智能技术进步的基础上得到了快速发展。IDC跟踪报告数据显示&#xff0c;2021年我国的边缘计算服务器整体市场规模达到33.1亿美元&#xff0c;预计2020…

NFS原理详解

一、NFS介绍 1&#xff09;什么是NFS 它的主要功能是通过网络让不同的机器系统之间可以彼此共享文件和目录。 NFS服务器可以允许NFS客户端将远端NFS服务器端的共享目录挂载到本地的NFS客户端中。 在本地的NFS客户端的机器看来&#xff0c;NFS服务器端共享的目录就好像自己的磁…

耿明雨履新并担任名誉台长

据悉&#xff0c;近日&#xff1a;经美国科罗拉多州国务卿审批&#xff0c;中国大陆知名人士、媒体人、慈善家耿明雨先生获科罗拉多州办公室证书批复&#xff0c;担任中国驻美国中央国际广播电视总台名誉台长、集团董事。

C++ Qt开发:TabWidget实现多窗体功能

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍TabWidget标签组件的常用方法及灵活运用。 Q…

一行注解,省却百行代码:深度解析@RequiredArgsConstructor的妙用

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 一行注解&#xff0c;省却百行代码&#xff1a;深度解析RequiredArgsConstructor的妙用 前言RequiredArgsConstructor 简介Lombok框架简介RequiredArgsConstructor 的实现原理注解参数及使用技巧项目中…

弧形导轨的类型及应用

弧形导轨又叫圆弧形导轨&#xff0c;滚轮弧形导轨&#xff0c;是通过V型滚轮在圆弧形V型导轨面上的滚动&#xff0c;实现圆周运动&#xff1b;在工业自动化中&#xff0c;有些应用需要弧线运动&#xff0c;或者两个相交或平行的直线运动&#xff0c;这些情况需要通过弧线运动连…

Python安装及配置

一、前置说明 Python的安装有两种方式&#xff1a;1. 访问Python官方网站下载安装&#xff1b;2. 使用Python的开源发行版进行安装。 Anaconda 是一个用于科学计算、数据分析和机器学习的开源发行版&#xff0c;它包含了许多常用的科学计算和数据分析库。Anaconda 不仅仅是 P…

TongWEB安装

1.获取安装包 产品版本 安装包 绿色版 Windows: TongWeb7.0.x.x _XX_Windows.tar.gz Linux: TongWeb7.0.x.x_XX_Linux.tar.gz 安装程序版 Windows: Install_TW7.0.x.x_XX_Windows.exe Linux&#xff1a; Install_TW7.0.x.x_XX_Linux.bin 2.3 2.前提条件 TongWeb 启动前…

市域治理现代化建设方案(智慧网格解决方案):PPT全文33页,附下载

关键词&#xff1a;市域治理现代化&#xff0c;智慧网格解决方案&#xff0c;市域治理主要内容&#xff0c;市域社会治理重点内容&#xff0c;市域社会治理现代化 一、市域治理现代化背景 1、城市化进程加速&#xff1a;随着城市化进程的快速推进&#xff0c;城市人口不断增加…