1、项目说明
介绍
贪吃蛇是我们小时候的一款经典游戏,毕竟在那个Nokia称霸的年代,这款游戏可是经典中的经典啊!而用Python(蛇)玩Snake(贪吃蛇),那再合适不过了。
需求分析
我们先来回顾下贪吃蛇中的游戏元素及游戏规则:
- 需要有贪吃蛇、有食物
- 需要能控制贪吃蛇来上下移动获取食物
- 贪吃蛇在吃取食物后,自身长度增加,同时食物消失并随机生成新的食物
- 如果贪吃蛇触碰到四周墙壁或是触碰到自己身体时,则游戏结束
2、项目预览
3、开发必备
游戏开发运行环境
- python3.7以上
- 开发工具PyCharm
- Python内置模块:random
- 第三方模块:pygame
4、贪吃蛇代码实现
4.1、窗口和基本参数实现
分析
我们首先需要初始化一些参数:游戏界面大小、蛇和食物的参数以及一些游戏边界和障碍的设置等等
- 初始化 Pygame 模块,让游戏程序能够使用 Pygame 提供的功能;
- 设置游戏窗口的大小;
- 定义两个字体对象,分别用于绘制不同大小的文字;
- 定义了一个方向列表,包含了贪吃蛇可能移动的四个方向;
- 定义了 X 和 Y 的坐标列表,方便后续使用;
- 定义了几种不同的食物颜色,用于给不同等级的食物染色;
- 定义了障碍物(墙)的位置和尺寸以及食物的初始位置和尺寸;
- 设置蛇的一些参数,如速度、长度、宽度和高度等;
- 设置游戏的等级和初始等待时间;
- 设置游戏窗口的标题和一些初始化的变量。
代码实现
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()
的函数,它用来绘制游戏的背景。
具体的绘制过程如下:
screen.fill(COLORS['white'])
使用白色填充背景屏幕,将屏幕背景设置为白色。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()
的函数,它用来绘制游戏中的墙壁。
具体的绘制过程如下:
- 使用
for
循环遍历墙壁列表wall_list
中的每个元素,每个元素表示一个墙壁的位置。 - 对于每个墙壁位置,调用
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()
的函数,它用来绘制游戏中的蛇。
具体的绘制过程如下:
- 使用
snake_list
列表中的第一个元素作为蛇头,调用pygame.draw.circle()
函数绘制一个圆作为蛇头。圆心的位置(x, y)
是(head[0], head[1])
,半径为SNAKE_WIDTH/2
。圆的颜色是 COLORS 字典中的darkred
。 - 对于蛇身上的其他部分(不包括蛇头),使用
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()
的函数,它用来绘制食物物品。
具体的绘制过程如下:
- 使用
for
循环遍历食物列表food_list
中的每个元素,每个元素表示一个食物的位置和类型。 - 对于每个食物位置,调用
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()
的函数,它用来绘制游戏的上下文信息。
具体的绘制过程如下:
- 创建一个文本对象
txt
,文本内容是 "Snake length: " 连接上蛇身长度len(snake_list)-1
。使用FONT_M
字体来渲染文本,文本颜色是 COLORS 字典中的lightblue
。 - 计算文本的位置
(x, y)
,其中x
的初始值为10
,y
的初始值为GAME_SIZE[1]+(int((SIZE[1]-GAME_SIZE[1])/2))
。接下来,将y
的值减去文本字体尺寸的一半,以实现垂直居中。 - 使用
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()
的函数,它用于在游戏暂停时绘制暂停界面。
具体的绘制过程如下:
- 创建一个透明表面
s
,大小与SIZE
相同,并填充为带有半透明的白色(255,255,255,220)
。 - 使用
screen.blit()
函数将表面s
绘制到屏幕上的位置(0, 0)
,实现背景的半透明效果。 - 创建一个文本对象
txt
,文本内容为 “PAUSE”,使用FONT_M
字体渲染文本,文本颜色为 COLORS 字典中的darkgray
。 - 计算文本的位置
(x, y)
,其中x
的初始值为SIZE[0]/2
,y
的初始值为SIZE[1]/2
。然后,将x
和y
的值减去文本字体尺寸的一半,以实现水平和垂直居中。 - 使用
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()
的函数,用于在游戏中玩家死亡时绘制死亡界面。
具体的绘制过程如下:
- 创建一个透明表面
s
,大小与SIZE
相同,并填充为带有半透明的白色(255,255,255,240)
。 - 使用
screen.blit()
函数将表面s
绘制到屏幕上的位置(0, 0)
,实现背景的半透明效果。 - 创建一个文本对象
txt
,文本内容为 “YOU DEAD”,使用FONT_M
字体渲染文本,文本颜色为 COLORS 字典中的black
。 - 计算文本的位置
(x, y)
,其中x
的初始值为SIZE[0]/2
,y
的初始值为SIZE[1]/2
。然后,将x
和y
的值减去文本字体尺寸的一半,以实现水平和垂直居中。 - 使用
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)
的函数,用于判断两个矩形是否相交。
具体的判断过程如下:
- 将每个矩形的四个边界值提取出来,并转换为整数类型。其中,
left1
表示矩形rect1
左边界,right1
表示矩形rect1
右边界,up1
表示矩形rect1
上边界,down1
表示矩形rect1
下边界;同理,left2
、right2
、up2
、down2
分别为矩形rect2
的四个边界值。 - 如果矩形
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
中添加食物。
具体的过程如下:
- 进入一个无限循环
while(True)
。 - 在每次循环中,生成一个由随机选择的
X_LIST
中的元素、随机选择的Y_LIST
中的元素和随机选择的[1,2,3,4]
中的元素组成的列表xyz
。 - 检查
xyz
是否存在于墙壁列表wall_list
中。如果不存在,说明xyz
没有被墙壁占据,可以作为食物的位置。 - 将
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
中添加身体节。
具体的过程如下:
- 使用一个循环来控制添加的身体节的数量,循环的次数由参数
length
决定,默认为1。 - 在每次循环中,获取蛇身体列表
snake_list
中的倒数第二个和最后一个元素,并分别赋值给last2
和last1
。 - 检查最后两个身体节的相对位置:如果它们在垂直方向上相等,则代表这两节身体是竖直排列的;如果它们在水平方向上相等,则代表这两节身体是水平排列的。
- 根据身体节的相对位置,确定新的身体节的坐标。如果是竖直排列,根据最后一节的朝向选择向上或向下添加一节;如果是水平排列,根据最后一节的朝向选择向左或向右添加一节。
- 将新的身体节坐标添加到蛇的身体列表
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、实现贪吃蛇吃食物功能
分析
定义一个检查蛇头是否与食物碰撞的函数。具体的实现逻辑如下:
- 首先获取蛇的头部坐标
snake_list[0]
,并计算出蛇头的矩形区域snake_head_rect
。矩形区域的坐标为(蛇头x坐标-SNAKE_WIDTH/2, 蛇头y坐标-SNAKE_WIDTH/2, SNAKE_WIDTH, SNAKE_HEIGHT)
。 - 遍历食物列表
food_list
,获取每个食物的坐标xyz
。再计算出食物的矩形区域food_rect
。矩形区域的坐标为(食物x坐标-FOOD_WIDTH/2, 食物y坐标-FOOD_WIDTH/2, FOOD_WIDTH, FOOD_HEIGHT)
。 - 调用
rect_cover
函数判断蛇头的矩形区域是否与当前食物的矩形区域重叠。如果重叠,则表示蛇头与该食物碰撞了。 - 如果蛇头与食物碰撞,则调用
add_body
函数将食物的类型xyz[2]
加入到蛇的身体中,并从食物列表中移除该食物。 - 最后返回一个布尔值,表示蛇头是否与任何食物碰撞。
代码
# 检查是否有食物被吃掉
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()
函数用于检查蛇是否死亡,即判断蛇头是否与边缘、墙壁或自身的身体发生碰撞。具体过程如下:
- 获取蛇头的位置,即蛇列表中的第一个元素。
- 创建蛇头的矩形区域,以便后续与边缘、墙壁或自身的身体进行碰撞检测。
- 检查蛇头是否与边缘发生碰撞,即蛇头是否超出了游戏区域的范围。如果超出范围,则视为蛇死亡,返回
True
。 - 遍历墙壁列表,获取每个墙壁的坐标。
- 创建墙壁的矩形区域,以便后续与蛇头的矩形区域进行碰撞检测。
- 检查蛇头是否与墙壁发生碰撞。如果发生碰撞,则视为蛇死亡,返回
True
。 - 遍历蛇列表中除蛇头外的元素,即蛇的身体。
- 创建身体节的矩形区域,以便后续与蛇头的矩形区域进行碰撞检测。
- 检查蛇头是否与自身的身体发生碰撞。如果发生碰撞,则视为蛇死亡,返回
True
。 - 如果以上都未发生,即蛇未死亡,返回
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、实现键盘控制游戏
分析
编写一个处理事件的循环,它的作用是根据用户的输入来控制游戏的行为。主要包含以下几个事件处理:
pygame.QUIT
事件:当用户点击窗口的关闭按钮时,这个事件会触发。在这段代码中,会将running
变量设置为False
,从而退出游戏循环。pygame.MOUSEBUTTONDOWN
事件:当用户点击鼠标按钮时,这个事件会触发。在这段代码中,每次点击鼠标按钮会切换pause
变量的状态,用来暂停游戏。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、结束
需要源码留言