Python-项目实战--贪吃蛇小游戏-贪吃蛇功能实现(4)

5.贪吃蛇功能的实现

  • 在这一小节,我们就以完成的游戏框架为基础,加入贪吃蛇的功能,完成整个游戏的开发

  • 本小节的知识重点包括:

  • 贪吃蛇类的设计

  • 定义贪吃蛇类

  • 添加蛇身体

  • 绘制和移动身体

  • 改变贪吃蛇的方向

  • 贪吃蛇吃食物

  • 贪吃蛇的死亡

5.1贪吃蛇类的设计

我们首先来明确一下在贪吃蛇类中应该封装哪些属性和方法, 这些内容的确定,会为后续的开发做好准备和铺垫。

按照贪吃蛇的游戏规则描述:

  • 贪吃蛇初始出现在游戏窗口的左上角位置,体长共有3节

  • 贪吃蛇初始沿屏幕水平方向,向右侧运动,每隔0.5秒移动一节身体

  • 使用键盘的方向键(↑、 ↓、←、→)可以改变蛇头的运动方向

  • 当蛇头与食物相遇时,代表蛇吃到了食物,游戏分数增加10分

5.1.1属性设计

  • 运动方向属性

要描述贪吃蛇的运动方向,我们可以使用pygame预置的方向键常量,分别是:

  • pygame.K_UP上

  • pygame.K_DWON下

  • pygame.K_LEFT左

  • pygame.K_RIGHT右

提示:在后续监听键盘按键事件以及修改蛇的运动方向时,还会使用到这些常量

  • 时间间隔属性

在初始状态时,贪吃蛇是每隔0.5秒移动一节身体的,而随着吃到的食物增加,这个时间间隔会不断缩小。因此我们还需要考虑使用一个属性来记录这个时间间隔

  • 身体列表属性

如果把贪吃蛇的每节身体看成屏幕上的一个小格子,那么我们就可以使用一个Rect对象,来表示贪吃蛇的一节身体。这样,要记录整个身体,只需要定义一个body _list的列表属性,用来记录从蛇头到蛇尾的每一身体的Rect对象即可。

  • 游戏得分属性

每一轮新游戏开始之后,游戏中只有一条贪吃蛇, 并且只有在这条蛇吃到食物之后,游戏分数才会增加,一旦贪吃蛇在运动过程中,蛇头撞到了窗口的边缘或者身体的其他部位,则判定为死亡。而再次开启新一轮游戏后,游戏分数会归零重新计算。

因此,我们可以定义一个游戏分数的属性,用来记录当前这条贪吃蛇对象的累计得分。

5.1.2方法设计

  • 重置贪食蛇属性

按照游戏规则描述--每一 轮游戏结束后,用户按下空格键会开启新一轮游戏。这就意味着,开启新一轮游戏需要把贪吃蛇对象的属性设置为初始值。我们可以定义1个reset_snake的方法,专门负责来重设贪吃蛇的属性值。

  • 添加身体

除了在初始化贪吃蛇时,我们要在水平向右的方向(蛇的初始运动方向)上增加三节身体之外,在游戏过程中,如果贪吃蛇再吃到食物,身体长度同样也要增加。

因此,我们可以定义1个add_node方法,专门负责向贪吃蛇的身体列表中增加一节身体。

  • 绘制身体和更新位置

为了方便游戏循环中的代码调用,我们可以定义2个方法来负责绘制身体和更新位置:

  • draw方法负责在游戏窗口中绘制贪吃蛇的身体

  • update方法负责移动蛇的身体

  • 改变蛇的方向

按照游戏规则描述--使用键盘的方向键 (↑、↓、←、→) 可以改变蛇头的运动方向。为了方便游戏循环中的代码调用,我们可以定义1个change_dir 方法,专门负责根据用户按键改变蛇的运动方向。

  • 判断死亡和吃到食物

为了方便游戏循环中的代码调用,我们可以定义2个方法来负责判断蛇的死亡和是否吃到食物

  • is_dead方法返回是否死亡

  • has_eat方法返回是否吃到指定的食物

5.1.3贪吃蛇的类图

综上所述,我们可以得到贪吃蛇的类图如下:

5.2定义贪吃蛇类

在这一小节,我们先做一些准备工作,其中包括:

  • 定义贪吃蛇类并准备reset_snake方法

  • 使用贪吃蛇的分数属性调整游戏中的得分显示

5.2.1定义贪吃蛇类

  • 首先,在game_items.py中定义Snake类,并且实现初始化方法reset_snake方法,代码如下:

class Snake(object):
    """蛇类"""

    def __init__(self):
        """初始化蛇的数据"""
        self.dir = pygame.K_RIGHT
        self.time_interval = 500  # 运动时间间隔
        self.score = 0  # 游戏得分
        self.color = (64, 64, 64)  # 身体颜色 - 深灰色
        body_list = []  # 身体列表

    def reset_snake(self):
        """重置蛇的数据"""
        self.dir = pygame.K_RIGHT
        self.time_interval = 500
        self.score = 0
        self.body_list = []
  • 然后,在game.py中的Game类中添加reset_game方法

def reset_game(self):
    """重置游戏参数"""
    self.score = 0
    self.is_game_over = False
    self.is_pause = False

    # 重置蛇的数据
    self.snake.reset_snake()

    # 重置食物位置
    self.food.random_rect()
  • 接着,修改game.py中的Game类中的绘制得分代码。得分是贪吃蛇的分数

# 绘制得分
self.score_label.draw(self.main_window, "DeFen: %d" % self.snake.score)

# 绘制暂停、游戏结束的标签
if self.is_game_over:
    self.tip_label.draw(self.main_window, "Youxi Jiesu anKonggeJian KaiQi xinyouxi")
elif self.is_pause:
    self.tip_label.draw(self.main_window, "Youxi Zanting KonggejianJixu...")
else:
    self.snake.score += 1

# 绘制食物
self.food.draw(self.main_window)

5.3添加蛇身体

添加蛇身体也就是add_ node这个方法是贪吃蛇游戏中非常关键的一个方法!

按照之前的分析,我们已经知道,在游戏中要添加一节身体一共有两种情况:

  • 初始化贪吃蛇时,在屏幕的左上角,沿水平向右方向,依次添加3节身体

  • 在游戏过程中,吃到食物后,同样需要增加1节身体

我们先看一下如下示意图,分析一下在吃到食物后,增加身体的处理方式

观察上图不难发现,当吃到食物时,我们只需要在蛇头的前方位置,也就是沿着蛇当前的运动方向偏移一个小格子,再增加一节身体作为蛇头就可以了。

这种处理方式最大的好处是:增加身体和向前移动可以一步到位!而不需要先在蛇尾添加一节身体,再向前依次移动每一节蛇的身体

接下来,再看一下添加蛇身体的流程图,进一步确认一下添加蛇身体的处理方式

接下来,按照流程图,来实现一下在game_items.py的Snake类中添加add_node方法,代码如下:

def add_node(self):
    """添加一节身体"""
    # 生成新的矩形对象
    if self.body_list:
        # 已经有身体了
        head = self.body_list[0].copy()
    else:
        # 还没有身体
        head = pygame.Rect(-CELL_SIZE, 0, CELL_SIZE, CELL_SIZE)

    # 根据移动方向,把新生成的头部放到恰当的位置
    if self.dir == pygame.K_RIGHT:
        head.x += CELL_SIZE
    elif self.dir == pygame.K_LEFT:
        head.x -= CELL_SIZE
    elif self.dir == pygame.K_UP:
        head.y -= CELL_SIZE
    elif self.dir == pygame.K_DOWN:
        head.y += CELL_SIZE

    # 把新生成头部放到列表的最前面
    self.body_list.insert(0, head)

5.4绘制和移动身体

在这一小节,要完成两个任务:

  • 利用draw模块提供的方法绘制蛇的身体

  • 利用定时器事件实现蛇的移动

5.4.1绘制身体

  • game_items.py的Snake类中定义draw方法,并实现如下代码:

def draw(self,window):
    """绘制蛇的每一节身体"""
    for idx, rect in enumerate(self.body_list):
        pygame.draw.rect(window, self.color, rect.inflate(-2, -2), idx==0)
  • 在game.py的Game类的游戏循环中,让蛇对象调用draw方法,代码如下:

# 绘制食物
self.food.draw(self.main_window)

# 绘制贪吃蛇
self.snake.draw(self.main_window)

# 刷新窗口内容
pygame.display.update()

未完待续

内容总结于:https://space.bilibili.com/441640380

猜你喜欢

转载自blog.csdn.net/aaaccc444/article/details/129064205