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 pygameif __name__ == "__main__":# 初始化pygamepygame.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*1000screen = 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,12snake_v = 0count_time = 0# 等级frame = 0.05level = 1# 主循环running = Truepause = Falsedead = Falsehead = '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 backgroundscreen.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]/2x,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]/2x,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 Truereturn 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 Truereturn 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 Truereturn 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 = Falsebreak# 处理鼠标点击事件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、结束

需要源码留言

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

elementui中的el-table,当使用fixed属性时,table主体会遮挡住滚动条的大半部分,导致很难选中。

情况&#xff1a; 解决&#xff1a; el-table加个类&#xff0c;这里取为class"table" 然后是样式部分&#xff1a; <style scoped lang"scss"> ::v-deep.table {// 滚动条高度调整::-webkit-scrollbar {height: 15px;}// pointer-events 的基本信…

处理HTTP响应状态码和错误处理

在Web开发的世界里&#xff0c;HTTP响应状态码和错误处理是不可或缺的一部分。它们就像是道路上的交通信号灯&#xff0c;指导着我们前进的方向&#xff0c;确保我们的应用程序能够正常运行。 HTTP响应状态码是Web服务器返回给客户端的数字代码&#xff0c;用于表示请求的处理…

以编程方式向 App 设计工具添加 UI 组件

App 设计工具组件库中提供了大多数 UI 组件&#xff0c;可以将它们拖放到画布上。有时&#xff0c;可能需要在代码视图中以编程方式添加组件。以下是一些常见情况&#xff1a; 创建在组件库中未提供的组件。例如&#xff0c;用于显示某对话框的 App 必须调用适当的函数来显示该…

Volta简单介绍

Volta是一款强大的JavaScript工具管理器&#xff0c;它简化了命令行工具的安装和管理。通过Volta&#xff0c;开发者可以轻松地在多个项目中切换和配置Node.js、npm以及其它JavaScript工具版本&#xff0c;提高开发效率和环境一致性。 什么是 Volta Volta 是一种管理 JavaScri…

数据之门:使用IPIDEA开启网络自由之旅~

本文目录 前言一、网络代理IP简介二、IPIDEA 优势2.1 多种类型IP代理2.2 海量纯净代理池2.3 稳定高效数据收集架构2.4 个人IP管理中心 三、IP代理实操小Tips3.1 查看本地网络IP3.2 使用浏览器IP代理3.3 使用IPIDEA进行爬虫实操 四、总结 前言 各位友友&#xff0c;大家好&…

ASP.NET MVC+EntityFramework图片头像上传

1&#xff0c;先展示一下整体的效果 2&#xff0c;接下来展示用户添加以及上传头像代码、添加用户界面 前端代码如下&#xff1a; <div class"form-group">Html.LabelFor(model > model.img, "头像&#xff1a;", htmlAttributes: new { class &…

【计算机组成与体系结构Ⅱ】多处理器部分讨论题目

多处理机课堂讨论 1.并行计算体系结构有哪些? SIMD、MIMD 2.多处理机的存储结构有哪些? 对称式共享存储器结构、分布式共享存储结构 3.什么是多处理机的一致性? 如果对某个数据项的任何读操作均可得到其最新写入的值&#xff0c;则认为这个存储系统是一致的。 4.监听协议的工…

UCloud + 宝塔 + PHP = 个人网站

UCloud 宝塔 PHP 个人网站 文章目录 1.概要2.UCloud使用教程&#xff08;租用云端服务器&#xff09;3.宝塔使用教程&#xff08;免费服务器运维面板&#xff09;4.总结 1.概要 今天主要是想教大家如何将在网络上白嫖到源码&#xff08;特指PHP源码!!!&#xff09;搭建运行…

uni-app 用于开发H5项目展示饼图,使用ucharts 饼图示例

先下载ucharts H5示例源码&#xff1a; uCharts: 高性能跨平台图表库&#xff0c;支持H5、APP、小程序&#xff08;微信小程序、支付宝小程序、钉钉小程序、百度小程序、头条小程序、QQ小程序、快手小程序、360小程序&#xff09;、Vue、Taro等更多支持canvas的框架平台&#…

使用bs4 分析html文件

首先需要 pip install beautifulsoup4安装 然后为了方便学习此插件&#xff0c;随便打开一个网页&#xff0c;然后鼠标右键&#xff0c;打开源网页&#xff0c;如下图片 这样就可以获得一个网页源码&#xff0c;全选复制粘贴到本地&#xff0c;存储为 .html 文件&#xff0c;…

WebLangChain_ChatGLM:结合 WebLangChain 和 ChatGLM3 的中文 RAG 系统

WebLangChain_ChatGLM 介绍 本文将详细介绍基于网络检索信息的检索增强生成系统&#xff0c;即 WebLangChain。通过整合 LangChain&#xff0c;成功将大型语言模型与最受欢迎的外部知识库之一——互联网紧密结合。鉴于中文社区中大型语言模型的蓬勃发展&#xff0c;有许多可供利…

自封组件-带边框的渐变色数据卡片

<template> <el-row :gutter"10"><el-col :span"8"><div class"dplay_green"><div class"dplay_num_green">{{ jhdl }}</div><div class"dplay_text_green">提示文字</div>…

计算机网络——数据链路层-可靠传输的实现机制:选择重传协议SR(介绍、工作原理、窗口尺寸、题目练习)

目录 选择重传协议SR 介绍 工作原理 窗口尺寸 练习 题目 答案 解析 示意图 选择重传协议SR 介绍 在上篇中&#xff0c;我们介绍了回退N帧协议。回退N帧协议的接收窗口尺寸只能等于一&#xff0c;因此接收方只能按序接收正确到达的数据分组&#xff1b;一个数据分组…

宣布推出 ML.NET 3.0

作者&#xff1a;Jeff Handley 排版&#xff1a;Alan Wang ML.NET 是面向 .NET 开发人员的开源、跨平台的机器学习框架&#xff0c;可将自定义机器学习模型集成到 .NET 应用程序中。ML.NET 3.0 版本现已发布&#xff0c;其中包含大量新功能和增强功能&#xff01; 此版本中的深…

零刻EQ12 N100 双2.5G网口 All In One新手教程

零刻EQ12 N100 双2.5G网口 All In One新手教程 前言1.硬件配置2.准备工作2.1. ESXI8.0U2镜像2.2. Rufus磁盘工具下载2.3. ikuai镜像下载2.4. StarWindConverter虚拟磁盘格式转换工具下载2.5. OpenWrt镜像下载2.6. 黑群晖RR引导镜像下载(DSM7.2)2.7. 需要准备的硬件2.8. 格式化需…

kafka offset sasl加密连接

kafka-tool&#xff08;offset&#xff09; 进行SCRAM连接&#xff0c;直接上图 填写jaas的认证&#xff08;账密 引用包&#xff09;

图片曝光修正方法(直方图均衡和CNN)

图像过曝或曝光不足时需要曝光处理&#xff0c; 这里以曝光不足举例。 直方图均衡法&#xff1a; 通过RGB通道的直方图均衡达到处理曝光不足的效果。 代码&#xff1a; underexpose cv2.imread("exposure_test.jpg") #underexpose cv2.cvtColor(underexpose, cv2…

Android WorkManager入门(一)

WorkManager入门 前言一、WorkManager是什么&#xff1f;二、使用1.添加依赖2.定义工作3.创建 WorkRequest并提交 一次性的任务&#xff08;OneTimeWorkRequest&#xff09;4.setExpedited 加急方法5. setInitialDelay 延时任务6.约束 总结参考资料 前言 在当今快节奏的生活中…

袋鼠目标检测数据集VOC+YOLO格式1400多张

袋鼠是双门齿目袋鼠亚目袋鼠科大袋鼠属的哺乳动物。袋鼠跳得最高、最远。雌性袋鼠都长有一个前开的育儿袋&#xff0c;袋鼠也因此得名。 [8]袋鼠泛指任一种属于袋鼠目的有袋动物&#xff0c; [7]它头小眼大耳朵长&#xff0c;面部较长&#xff0c;鼻孔两侧有黑色须痕。袋鼠胆小…

java --- 多线程

目录 一、java多线程的三种实现方式 1.1 多线程的第一种实现方式&#xff1a;继承Thread类 1.2 多线程的第二种实现方式&#xff1a;Runnable接口 1.3 多线程的第三种实现方式&#xff1a;Callable接口和Future接口 1.3 多线程三种实现方式的对比 二、线程常用的成员方…