「行空板Python入门教程」第六课:贪吃蛇小游戏

描述

在很久很久以前,手机屏幕都还是黑白的年代,有一款叫做“贪吃蛇”的游戏风靡了大街小巷,在那分辨率极低的屏幕上,几条扭扭曲曲的弧线似乎穿越了整个童年。

这节课上,就让我们用DFRobot行空板来实现一下这款经典的游戏吧!

 

任务目标

在屏幕上进行贪吃蛇小游戏。

DFRobotDFRobot

知识点

1、认识pygame库

2、学习使用pygame库创建游戏窗口的方法

3、学习使用pygame库绘制图形、绘制文本、更新屏幕显示的方法

4、学习使用pygame库实现键盘交互的方法

材料清单

硬件清单:

DFRobotDFRobot

软件使用:Mind+编程软件x1

知识储备

1、贪吃蛇小游戏实现原理与逻辑

(1)实现原理

在这个贪吃蛇游戏中,我们将整个游戏区域划分成一个个的小格子,每一个格子的所在位置可以通过行列来表示,由一组连在一起的小格子组成“蛇”,“蛇”分为“蛇头”和“蛇身”两部分。“蛇头”用一个格子表示,“蛇身”用一个列表来存储,结合不同的颜色,这样一条“蛇”就出来了。“蛇”的移动则是将下一格的行列位置添加到列表开头,并移除列表的最后一个元素,就相当于“蛇”向前移动了一格。食物同样以格子的形式随机呈现,当“蛇头”与食物的位置重合,那么“蛇”就吃到了食物,而当“蛇”移动超出了范围亦或者“蛇头”撞在了“蛇身”上,那么游戏结束并计算食物数量。

 

(2)游戏逻辑图

由于游戏包含了蛇的移动、吃食物、事件监测、结束游戏等多个功能,在编程时,我们可以通过定义函数的方式,实现各个不同的功能部分,之后依据游戏逻辑在所需处调用即可。

DFRobot

2、什么是pygame库

pygame是专为电子游戏设计的跨平台Python库。通过它,我们可以设计包含图像、声音等元素的电子游戏。pygame做游戏开发的优势在于不需要过多地考虑底层相关的内容,而可以把重心放在游戏逻辑上,例如,pygame中集成了很多和底层相关的模块,如访问显示设备、管理事件、使用字体等。关于pygame常用的一些模块可参考下表。

模块名 功能
pygame.display 访问显示设备
pygame.event 管理事件
pygame.draw 绘制形状、线和点
pygame.key 读取键盘按键
pygame.mouse 控制鼠标事件
pygame.music 播放音频

3、pygame库常见函数

pygame库中的函数有很多,我们只使用其中的一部分,编程时,通过“import pygame”导入库后可采用“pygame.函数名()”的形式来实现功能。

(1)init()函数初始化pygame模块

通过init()函数我们可对pygame中的模块进行初始化,在编程时,我们需要将这条指令放在其他pygame指令之前,初始化后方可使用其中的模块。

pygame.init() # 初始化pygame

(2)quit()函数退出pygame库

quit()函数是与init()函数功能相反的一个函数,可以实现退出pygame,使pygame库结束工作。在编程时,我们通常在需要结束游戏时使用。

pygame.quit() # 退出pygame

4、pygame库display模块中的常用方法

pygame库display模块可用来访问显示设备,以便在设备上显示内容。其中的方法有很多,我们只使用其中的一部分,在编程时,可通过“模块名.方法名()”的形式来实现功能。

(1)set_mode()方法初始化一个准备显示的窗口界面

set_mode()方法可以实现游戏窗口的创建

size=(240,320) # 定义尺寸

window = pygame.display.set_mode(size) # 创建游戏窗口,尺寸为(240,320)

其中,size是我们设定的要显示的游戏窗口的尺寸大小,和行空板屏幕相同,window是一个生成的屏幕Surface对象,我们可以对它进行填充颜色、涂画、添加其他对象等各种操作。

如下,在填充颜色时,我们可通过“对象.fill()”的指令实现。

bg_color=(255,255,255) # 定义背景色为白

window.fill(bg_color) # fillcolor # 填充窗口的背景颜色

而要想将其他对象添加到窗口对象上,我们可通过“对象.blit()”指令来实现。

window.blit(score, (40,250)) # 在窗口上(40,250)处显示得分

(2)flip()方法更新屏幕

flip()方法可以将待显示的画面更新到屏幕上。通常,我们在使用pygame.display模块编写一些功能后,需要使用flip方法,才能将其更新显示到屏幕上。

pygame.display.flip() # Refresh all displays to the window # 更新所有待显示的内容到屏幕

5、pygame库draw模块中的常用方法

pygame库display模块可用来绘制各种不同的形状,其中的方法有很多,编程时,可通过“模块名.方法名()”的形式来实现功能。

(1)rect()方法绘制矩形

rect()方法可以实现矩形的绘制。

left=point.col*15 # 定义小方格距离左边缘的距离

top=point.row*15 # 定义小方格距离上边缘的距离

pygame.draw.rect(window,color,(left,top,15,15)) # 在窗口上绘制矩形,颜色为color

其中,window表示矩形绘制在窗口上,color是指矩形的颜色,left和top分别指矩形距离窗口左边缘和上边缘的距离,用以表示矩形的位置区域。

6、pygame库font模块中的常用方法

pygame库font模块可实现字体的使用,其中的方法有很多,编程时,可通过“模块名.方法名()”的形式来实现功能。

(1)SysFont()方法创建字体对象

SysFont()方法可以实现字体对象的创建。

font = pygame.font.SysFont('Arial', 20) # 设置字体

其中,Arial指的是具体的字体类型,20指的是字体大小,font是一个变量用于存储生成的字体对象。

而在创建好字体对象后,我们就可以在其上绘制具体的文本,以达到显示的效果,我们可通过“对象.render()”指令来实现。

score = font.render('Your Score is ' , False, 'pink') # 计算得分

其中,'Your Score is '指的是具体绘制的文本,False表示无需抗锯齿,pink指的是文本的颜色,score是一个变量用于存储生成的文本。

7、pygame库中的事件、事件类型、键盘事件以及事件检测

事件(Event)是 pygame 的重要模块之一,它是构建整个游戏程序的核心,比如鼠标点击、键盘敲击、游戏窗口移动、退出游戏等等,这些都可以看做是“事件”,pygame 会接受用户产生的各种操作(或事件),这些操作随时产生,并且操作量可大可小,那么 pygame 是如何处理这些事件的呢?

pygame 定义了一个专门用来处理事件的结构,即事件队列,该结构遵循队列“先到先处理”的基本原则,通过事件队列,我们可以有序的、逐一的处理用户的操作(触发事件)。对于 pygame 中常用的游戏事件,可参考下表:

事件类型 描述 成员属性
QUIT 用户按下窗口的关闭按钮 None
KEYDOWN 键盘按下 unicode、key、mod
KEYUP 键盘放开 key、mod
MOUSEBUTTONDOWN 鼠标按下 pos, button
MOUSEBUTTONUP 鼠标放开 pos, button

Tips:当使用 pygame 做游戏开发时,上述事件并非都会应用的到。

其中,键盘事件会涉及到大量的按键操作,比如游戏中的上下左右,或者人物的前进、后退等操作,这些都需要键盘来配合实现。
键盘事件提供了一个 key 属性,通过该属性可以获取键盘的按键。pygame 将键盘上的字母键、数字键、组合键等按键以常量的方式进行了定义,对于部分常用按键的常量,可参考下表:

常量名 描述
K_SPACE 空格键(Space)
K_RETURN 回车键(Enter)
K_0...K_9 0...9
K_a...Kz a...z
K_UP 向上箭头(up arrow)
K_DOWN 向下箭头(down arrow)
K_LEFT 向左箭头(left arrow)
K_RIGHT 向右箭头(right arrow)

Tips :由于行空板在开发时已做处理,将按键a、b映射为键盘上的a、b按键,因此,在获取键盘事件时,按下行空板上的按键a、b,同样能够被检测出来。

最后,要想实现键盘按键控制游戏的进行,那么我们就需要先检测事件,那如何才能实现呢?

pygame库event 模块提供了处理事件队列的常用方法,我们通过其中的get()方法就可以实现对于事件的检测。

events = pygame.event.get() # 获取事件

其中,events是一个变量,用来存储检测到的事件。

而在获取到了事件之后,我们就可以对它进行判别了

if (event.type == pygame.QUIT): # 如果事件类型为退出(关闭窗口)

pygame.quit() # 退出游戏

if (event.type == pygame.KEYDOWN): # 如果事件类型为键盘按下

if (event.key == pygame.K_a): # 如果是按键a被按下

.......

elif (event.key == pygame.K_b): # 如果是按键b被按下

其中,event.type表示事件的类型,pygame.QUIT表示退出事件,pygame.KEYDOWN表示键盘按下事件,event.key表示键盘的按键, pygame.K_a表示按键a,pygame.K_b表示按键b。

动手实践

任务描述1:创建游戏窗口

通过pygame库创建一个游戏窗口界面。

1、硬件搭建

通过USB连接线将行空板连接到计算机

2、程序编写

STEP1:创建与保存项目文件

启动Mind+,另存项目并命名为“006、贪吃蛇小游戏”。

STEP2:创建与保存Python文件

创建一个Python程序文件“main1.py”,双击打开。

STEP3:程序编写

(1) 导入所需功能库

在这个任务中,我们需要结合pygame库和time库来绘制游戏窗口,因此,我们须先导入它们。

import pygame # 导入pygame库import time # 导入time库

(2) 初始化游戏并创建指定尺寸的游戏窗口

在使用pygame进行游戏时,我们需先对其进行初始化操作,之后,为了能和行空板的屏幕一致,我们创建一个大小为(240,320)的游戏窗口。

pygame.init() # 游戏初始化W=240 # 定义宽H=320 # 定义高size=(240,320) # 定义尺寸window = pygame.display.set_mode(size) # 创建游戏窗口,尺寸为(240,320)

(3) 定义背景色和初始运行状态

创建好游戏窗口后,我们再为其定义一个背景色和初始的运行状态以便在后续进行设置。

bg_color=(255,255,255) # 定义背景色为白run=True # 定义初始运行状态为True,表示运行

(4) 填充窗口的背景颜色并保持窗口显示

接下来,我们对窗口的背景进行颜色的填充,而为了能使窗口始终保持显示,我们需要不断刷新窗口屏幕的显示内容,这里我们结合循环来实现。

while run: # 游戏循环 window.fill(bg_color) # fillcolor # 填充窗口的背景颜色 pygame.display.flip() # Refresh all displays to the window # 更新所有待显示的内容到屏幕 time.sleep(0.2) # delay 0.2 seconds

Tips:完整示例程序如下:

'''创建游戏窗口'''import pygame # 导入pygame库import time # 导入time库 pygame.init() # 游戏初始化W=240 # 定义宽H=320 # 定义高size=(240,320) # 定义尺寸window = pygame.display.set_mode(size) # 创建游戏窗口,尺寸为(240,320)bg_color=(255,255,255) # 定义背景色为白run=True # 定义初始运行状态为True,表示运行 while run: # 游戏循环 window.fill(bg_color) # fillcolor # 填充窗口的背景颜色 pygame.display.flip() # Refresh all displays to the window # 更新所有待显示的内容到屏幕 time.sleep(0.2) # delay 0.2 seconds

3、程序运行

STEP1:远程连接行空板

STEP2:点击右上方的运行按钮

STEP3:观察效果

观察行空板,首先可以看到行空板的屏幕变成了白色,而这,正是我们所创建游戏窗口的背景。

DFRobot

任务描述2:添加游戏元素

上述生成的屏幕窗口上空空如也,为了完善游戏,接下来,我们将在其上添加游戏中的最重要的角色元素---蛇和食物。

1、程序编写

STEP1:创建与保存项目文件

新建一个Python程序文件“main2.py”,双击打开。

Step2:程序编写

和任务一相同,在程序的开始部分,我们依旧导入所需功能库,初始化游戏并创建游戏窗口。之后再在此基础上编写其他部分程序。

(1)定义游戏方式

在贪吃蛇游戏中,有蛇和食物两个最重要的元素,那么如何才能在我们的屏幕上表示它呢?

这里,我们将游戏窗口划分成一个个小方格,通过方格来表示界面内的元素,每个小方格的宽和高皆为15像素,这样,由于窗口大小为240*320,因此在横向上会有18个方格,纵向上会有24个,即24行18列的小方格。

# 将游戏窗口划分为一个个小方格,每个方格的宽和高皆为15,共计24行,18列ROW=24 # 定义行数,每格15*15,24行18列COL=18 # 定义列数cell_width=W/COL # 定义格子的宽cell_height=H/ROW # 定义格子的高

(4)定义方格位置

接下来,我们定义一个Point类,将方格看作一个点,通过行与列来表示它的位置。

# 定义Point类以表示方格的位置class Point: row=0 # 行 col=0 # 列 def __init__(self,row,col): # 行 列 self.row=row self.col=col

(5)定义蛇头、蛇身、食物的位置和颜色

之后,我们将蛇分为蛇头和蛇身两部分,设定其初始时各占一个和三个方格,而食物也作为一个元素占一格。

接着我们通过实例化类的方式来定义他们的位置,同时也定义好他们颜色,其中,蛇身的位置我们以列表来表示,具体过程如下。

# 定义蛇头、蛇身、食物的位置和颜色head = Point(row=int(ROW/2),col=int(COL/2)) # 定义蛇头的小方格位置在第12行,第9列snakes=[ Point(row=head.row,col=head.col+1), # 定义蛇身1的小方格位置在第12行,第10列 Point(row=head.row,col=head.col+2), # 定义蛇身2的小方格位置在第12行,第11列 Point(row=head.row,col=head.col+3) # 定义蛇身3的小方格位置在第12行,第12列]food = Point(row=2,col=3) # 定义食物的小方格位置在第2行,第3列head_color=(65,105,225) # 定义蛇头颜色snake_color=(204,204,204) # 定义蛇身颜色food_color=(255,10,10) # 定义食物颜色

(6)定义每个小方格的绘制方法

随后,我们通过pygame库绘制矩形的方法来绘制小方格,由于每个小方格的尺寸大小一致,仅位置和颜色不同,因此,我们可定义一个绘制方格的通用函数,将位置和颜色作为两个参数传入,其中,各个方格的位置,我们可以通过其所在的行和列来确定。

# 定义每个小方格的绘制(包含两个参数:位置和颜色)def rect(point,color): left=point.col*cell_width # 定义小方格距离左边缘的距离 top=point.row*cell_height # 定义小方格距离上边缘的距离 pygame.draw.rect(window,color,(left,top,cell_width,cell_height)) # 在窗口上绘制矩形

(6)实例化Star类,并结束绘图

最后,我们在指定的位置上绘制指定颜色的方格,分别代表蛇头、蛇身和食物,而为了使其始终出现,编程时我们将其放在循环中。

while run: # 游戏循环 window.fill(bg_color) # fillcolor # 填充窗口的背景颜色 # 以小方格来定义蛇身、蛇头和食物 for snake in snakes: rect(snake,snake_color) # 创建蛇身,颜色为snake_color rect(head,head_color) # 创建蛇头,颜色为head_color rect(food,food_color) # 创建食物,颜色为food_color pygame.display.flip() # Refresh all displays to the window # 更新所有待显示的内容到屏幕 time.sleep(0.2) # delay 0.2 seconds

Tips:完整示例程序如下:

'''在游戏窗口上添加蛇和食物'''import pygame # 导入pygame库import time # 导入time库 pygame.init() # 游戏初始化W=240 # 定义宽H=320 # 定义高size=(240,320) # 定义尺寸window = pygame.display.set_mode(size) # 创建游戏窗口,尺寸为(240,320)bg_color=(255,255,255) # 定义背景色为白 # 将游戏窗口划分为一个个小方格,每个方格的宽和高皆为15,共计24行,18列ROW=24 # 定义行数,每格15*15,24行18列COL=18 # 定义列数cell_width=W/COL # 定义格子的宽cell_height=H/ROW # 定义格子的高 # 定义Point类以表示方格的位置class Point: row=0 # 行 col=0 # 列 def __init__(self,row,col): # 行 列 self.row=row self.col=col# 定义蛇头、蛇身、食物的位置和颜色head = Point(row=int(ROW/2),col=int(COL/2)) # 定义蛇头的小方格位置在第12行,第9列snakes=[ Point(row=head.row,col=head.col+1), # 定义蛇身1的小方格位置在第12行,第10列 Point(row=head.row,col=head.col+2), # 定义蛇身2的小方格位置在第12行,第11列 Point(row=head.row,col=head.col+3) # 定义蛇身3的小方格位置在第12行,第12列]food = Point(row=2,col=3) # 定义食物的小方格位置在第2行,第3列head_color=(65,105,225) # 定义蛇头颜色snake_color=(204,204,204) # 定义蛇身颜色food_color=(255,10,10) # 定义食物颜色 # 定义每个小方格的绘制(包含两个参数:位置和颜色)def rect(point,color): left=point.col*cell_width # 定义小方格距离左边缘的距离 top=point.row*cell_height # 定义小方格距离上边缘的距离 pygame.draw.rect(window,color,(left,top,cell_width,cell_height)) # 在窗口上绘制矩形,颜色为color run=True # 定义初始运行状态为True,表示运行while run: # 游戏循环 window.fill(bg_color) # fillcolor # 填充窗口的背景颜色 # 以小方格来定义蛇身、蛇头和食物 for snake in snakes: rect(snake,snake_color) # 创建蛇身,颜色为snake_color rect(head,head_color) # 创建蛇头,颜色为head_color rect(food,food_color) # 创建食物,颜色为food_color pygame.display.flip() # Refresh all displays to the window # 更新所有待显示的内容到屏幕 time.sleep(0.2) # delay 0.2 seconds

2、程序运行

STEP1:远程连接行空板

STEP2:运行程序并观察效果

点击运行后,观察行空板,可以看到在游戏窗口内显示出了一条红头蓝身的蛇,以及一颗黄色的食物。

DFRobot

任务描述3:设定游戏机制

在上个任务中,我们在游戏界面内添加了蛇和食物,但这还不够,接下来,我们将设定游戏机制,使得能通过行空板的板载按键a和b控制蛇左右移动来吃食物,并且,食物由原来在固定位置生成改为随机生成。

1、程序编写

STEP1:创建与保存项目文件

新建一个Python程序文件“main3.py”,双击打开。

STEP2:程序编写

这个程序中,我们承任务2继续编写。

(1)设定食物的随机生成

这里,我们修改原来固定位置的食物,使其在屏幕窗口内随机位置生成。

# 定义食物的生成位置def gen_food(): pos = Point(row=random.randint(0,ROW-1),col=random.randint(0,COL-1)) # 定义食物的小方格位置在窗口内随机的地方 return posfood = gen_food() # 生成食物的位置

(2)定义事件监测

为了能通过行空板上的按键来控制蛇的移动,我们首先需要定义一个事件监测,具体过程如下。

# 定义事件监测def detect(): global direction global run events = pygame.event.get() # 获取事件 for event in events: # 遍历所有事件 if (event.type == pygame.QUIT): # 如果事件类型为退出(关闭窗口) pygame.quit() # 退出游戏 run = 0 if (event.type == pygame.KEYDOWN): # 如果事件类型为键盘按下 if (event.key == pygame.K_a): # 如果是按键a被按下 if (direction == 'up'): # 如果原来方向为up(向上) direction = 'left' # 将方向设为left(向左) elif (direction == 'left'): direction = 'down' elif (direction == 'down'): direction = 'right' elif (direction == 'right'): direction = 'up' print(direction) elif (event.key == pygame.K_b): # 如果是按键b被按下 if (direction == 'up'): # 如果原来方向为up(向上) direction = 'right' # 将方向设为right(向右) elif (direction == 'right'): direction = 'down' elif (direction == 'down'): direction = 'left' elif (direction == 'left'): direction = 'up' print(direction)

(3)定义移动方式并设定初始方向

之后,我们设定蛇的移动方式,并定义初始方向为left,具体过程如下。

# 定义移动方式def move(): global direction if direction == 'left': # 如果方向为left head.col-=1 # 设置蛇头向左移动一格(蛇头所在的列数-1) elif direction == 'right': head.col+=1 elif direction == 'up': head.row-=1 elif direction == 'down': head.row+=1 direction = 'left' # 定义初始方向为left

(4)复制方格位置

由于蛇在吃到食物时蛇身会增加,从效果上看蛇头的位置变成了蛇身第一格,因此,我们需要在定义Point类时,补充一个copy实例方法,达到复制方格自身位置的功能,以便后续在吃食物时调用。

# 定义Point类以表示方格的位置class Point: row=0 # 行 col=0 # 列 def __init__(self,row,col): # 行 列 self.row=row self.col=col def copy(self): # 复制 return Point(row=self.row,col=self.col)

(5)定义吃食物

接下来,我们定义蛇吃食物的方法,具体过程如下。

# 定义吃食物def eat(): global food eating = (head.row == food.row and head.col == food.col) # 定义正在吃的形式:蛇头的行列位置与食物相同 if eating : # 如果正在吃 food = Point(row=random.randint(0,ROW-1),col=random.randint(0,COL-1)) # 在随机处再生成一颗食物 snakes.insert(0,head.copy()) # 处理蛇身:1、把原来的头,插入到蛇身的最初位置(即在snakes蛇身列表的第0个位置增加一个元素) if not eating: # 如果不在吃了,吃完后 snakes.pop() #处理蛇身:2、把蛇身的最后一格移除(即移除snakes蛇身列表的最后一个元素)

(6)循环调用

最后,我们将上述定义好的事件监测、移动、吃食物三个功能函数放入循环中,使其永久执行。

while run: # 游戏循环 window.fill(bg_color) # fillcolor # 填充窗口的背景颜色 # 以小方格来定义蛇身、蛇头和食物 for snake in snakes: rect(snake,snake_color) # 创建蛇身,颜色为snake_color rect(head,head_color) # 创建蛇头,颜色为head_color rect(food,food_color) # 创建食物,颜色为food_color eat() # 吃 detect() # 事件监测 move() # 移动 pygame.display.flip() # Refresh all displays to the window # 更新所有待显示的内容到屏幕 time.sleep(0.2) # 可修改延时的时间改变蛇的移动速度,调整游戏难易度

Tips:完整示例程序如下:

'''控制蛇的移动、生成随机的食物、蛇吃食物'''import pygame # 导入pygame库import random # 导入随机数库import time # 导入time库 pygame.init() # 游戏初始化W=240 # 定义宽H=320 # 定义高size=(240,320) # 定义尺寸window = pygame.display.set_mode(size) # 创建游戏窗口,尺寸为(240,320)bg_color=(255,255,255) # 定义背景色为白 # 将游戏窗口划分为一个个小方格,每个方格的宽和高皆为15,共计24行,18列ROW=24 # 定义行数,每格15*15,24行18列COL=18 # 定义列数cell_width=W/COL # 定义格子的宽cell_height=H/ROW # 定义格子的高 # 定义Point类以表示方格的位置class Point: row=0 # 行 col=0 # 列 def __init__(self,row,col): # 行 列 self.row=row self.col=col def copy(self): # 复制 return Point(row=self.row,col=self.col) # 定义蛇头、蛇身的位置和颜色head = Point(row=int(ROW/2),col=int(COL/2)) # 定义蛇头的小方格位置在第12行,第9列snakes=[ # 定义蛇身列表 Point(row=head.row,col=head.col+1), # 定义蛇身1的小方格位置在第12行,第10列 Point(row=head.row,col=head.col+2), # 定义蛇身2的小方格位置在第12行,第11列 Point(row=head.row,col=head.col+3) # 定义蛇身3的小方格位置在第12行,第12列]# 定义食物的生成位置def gen_food(): pos = Point(row=random.randint(0,ROW-1),col=random.randint(0,COL-1)) # 定义食物的小方格位置在窗口内随机的地方 return posfood = gen_food() # 生成食物的位置 head_color=(65,105,225) # 定义蛇头颜色snake_color=(204,204,204) # 定义蛇身颜色food_color=(255,10,10) # 定义食物颜色 # 定义每个小方格的绘制(包含两个参数:位置和颜色)def rect(point,color): left=point.col*cell_width # 定义小方格距离左边缘的距离 top=point.row*cell_height # 定义小方格距离上边缘的距离 pygame.draw.rect(window,color,(left,top,cell_width,cell_height)) # 在窗口上绘制矩形,颜色为color # 定义事件检测def detect(): global direction global run events = pygame.event.get() # 获取事件 for event in events: # 遍历所有事件 #for event in pygame.event.get(): if (event.type == pygame.QUIT): # 如果事件类型为退出(关闭窗口) pygame.quit() # 退出游戏 run = 0 if (event.type == pygame.KEYDOWN): # 如果事件类型为键盘按下 if (event.key == pygame.K_a): # 如果是按键a被按下 if (direction == 'up'): # 如果原来方向为up(向上) direction = 'left' # 将方向设为left(向左) elif (direction == 'left'): direction = 'down' elif (direction == 'down'): direction = 'right' elif (direction == 'right'): direction = 'up' print(direction) elif (event.key == pygame.K_b): # 如果是按键b被按下 if (direction == 'up'): # 如果原来方向为up(向上) direction = 'right' # 将方向设为right(向右) elif (direction == 'right'): direction = 'down' elif (direction == 'down'): direction = 'left' elif (direction == 'left'): direction = 'up' print(direction) # 定义移动方式def move(): global direction if direction == 'left': # 如果方向为left head.col-=1 # 设置蛇头向左移动一格(蛇头所在的列数-1) elif direction == 'right': head.col+=1 elif direction == 'up': head.row-=1 elif direction == 'down': head.row+=1 # 定义吃食物def eat(): global food eating = (head.row == food.row and head.col == food.col) # 定义正在吃的形式:蛇头的行列位置与食物相同 if eating : # 如果正在吃 food = Point(row=random.randint(0,ROW-1),col=random.randint(0,COL-1)) # 在随机处再生成一颗食物 snakes.insert(0,head.copy()) # 处理蛇身:1、把原来的头,插入到蛇身的最初位置(即在snakes蛇身列表的第0个位置增加一个元素) if not eating: # 如果不在吃了,吃完后 snakes.pop() #处理蛇身:2、把蛇身的最后一格移除(即移除snakes蛇身列表的最后一个元素) direction = 'left' # 定义初始方向为leftrun = True # 定义初始运行状态为True,表示运行while run: # 游戏循环 window.fill(bg_color) # fillcolor # 填充窗口的背景颜色 # 以小方格来定义蛇身、蛇头和食物 for snake in snakes: rect(snake,snake_color) # 创建蛇身,颜色为snake_color rect(head,head_color) # 创建蛇头,颜色为head_color rect(food,food_color) # 创建食物,颜色为food_color eat() # 吃 detect() # 事件监测 move() # 移动 pygame.display.flip() # Refresh all displays to the window # 更新所有待显示的内容到屏幕 time.sleep(0.2) # 可修改延时改变蛇的移动速度,调整游戏难易度

2、程序运行

STEP1:远程连接行空板

STEP2:运行程序并观察效果

点击运行后,观察行空板,可以看到在游戏窗口内显示出了一条红头蓝身的蛇,以及一颗黄色的食物。随后蛇向左移动,此时,我们可通过按下板载按键a和b来分别控制蛇左转和右转。

DFRobot

任务描述4:结束游戏并计分

最后,我们在上述功能的基础上添加结束游戏和计分机制。

1、程序编写

STEP1:创建与保存项目文件

新建一个Python程序文件“main4.py”,双击打开。

Step2:程序编写

(1)导入所需功能库创建字体对象

由于需要显示得分,因此,我们需要提前在定义背景颜色后创建一个字体对象。

font = pygame.font.SysFont('Arial', 20) # 设置字体

(2)结束游戏机制

之后,我们在吃食物的功能后再定义结束游戏的方式:要么蛇撞上窗口四周,要么撞上自身。同时,我们设定在结束前显示最终的游戏得分。

# 定义游戏结束def game_over(): global run dead=False # 定义一个状态dead # 游戏结束方式1、撞墙 if head.col<0 or head.row<0 or head.col>=COL or head.row>=ROW: # 如果蛇头的行和列在屏幕外 dead = True # 游戏结束方式2、撞自己 for snake in snakes: if head.col==snake.col and head.row==snake.row: # 如果蛇头和蛇身位置相同 dead = True break if dead: # 如果状态为dead score = font.render('Your Score is ' + str(10*len(snakes)-30), False, 'pink') # 计算得分 window.blit(score, (40,250)) # 在窗口上显示得分 pygame.display.flip() # Refresh all displays to the screen # 更新所有显示的内容到屏幕 print("GG") # goodgame! =-= time.sleep(5) # delay 5 seconds run=False # set state False

(3)循环执行

最后,我们将上述定义好的结束游戏功能函数放入循环中,使其永久执行。

while run: # 游戏循环 window.fill(bg_color) # fillcolor # 填充窗口的背景颜色 # 以小方格来定义蛇身、蛇头和食物 for snake in snakes: rect(snake,snake_color) # 创建蛇身,颜色为snake_color rect(head,head_color) # 创建蛇头,颜色为head_color rect(food,food_color) # 创建食物,颜色为food_color eat() # 吃 detect() # 事件监测 move() # 移动 game_over() # 结束游戏 pygame.display.flip() # Refresh all displays to the window # 更新所有待显示的内容到屏幕 time.sleep(0.2) # delay 0.2 seconds # 可修改延时的时间改变蛇的移动速度,调整游戏难易度

Tips:完整示例程序如下:

'''计分和结束游戏'''import pygame # 导入pygame库import random # 导入随机数库import time # 导入 time库 pygame.init() # 游戏初始化W=240 # 定义宽H=320 # 定义高size=(240,320) # 定义尺寸window = pygame.display.set_mode(size) # 创建游戏窗口,尺寸为(240,320)bg_color=(255,255,255) # 定义背景色为白 font = pygame.font.SysFont('Arial', 20) # 创建字体对象 # 将游戏窗口划分为一个个小方格,每个方格的宽和高皆为15,共计24行,18列ROW=24 # 定义行数,每格15*15,24行18列COL=18 # 定义列数cell_width=W/COL # 定义格子的宽cell_height=H/ROW # 定义格子的高 # 定义Point类以表示方格的位置class Point: row=0 # 行 col=0 # 列 def __init__(self,row,col): # 行 列 self.row=row self.col=col def copy(self): # 复制 return Point(row=self.row,col=self.col) # 定义蛇头、蛇身的位置和颜色head = Point(row=int(ROW/2),col=int(COL/2)) # 定义蛇头的小方格位置在第12行,第9列snakes=[ # 定义蛇身列表 Point(row=head.row,col=head.col+1), # 定义蛇身1的小方格位置在第12行,第10列 Point(row=head.row,col=head.col+2), # 定义蛇身2的小方格位置在第12行,第11列 Point(row=head.row,col=head.col+3) # 定义蛇身3的小方格位置在第12行,第12列]# 定义食物的生成位置def gen_food(): pos = Point(row=random.randint(0,ROW-1),col=random.randint(0,COL-1)) # 定义食物的小方格位置在窗口内随机的地方 return posfood = gen_food() # 生成食物的位置 head_color=(65,105,225) # 定义蛇头颜色snake_color=(204,204,204) # 定义蛇身颜色food_color=(255,10,10) # 定义食物颜色 # 定义每个小方格的绘制(包含两个参数:位置和颜色)def rect(point,color): left=point.col*cell_width # 定义小方格距离左边缘的距离 top=point.row*cell_height # 定义小方格距离上边缘的距离 pygame.draw.rect(window,color,(left,top,cell_width,cell_height)) # 在窗口上绘制矩形,颜色为color # 定义事件检测def detect(): global direction global run events = pygame.event.get() # 获取事件 for event in events: # 遍历所有事件 #for event in pygame.event.get(): if (event.type == pygame.QUIT): # 如果事件类型为退出(关闭窗口) pygame.quit() # 退出游戏 run = 0 if (event.type == pygame.KEYDOWN): # 如果事件类型为键盘按下 if (event.key == pygame.K_a): # 如果是按键a被按下 if (direction == 'up'): # 如果原来方向为up(向上) direction = 'left' # 将方向设为left(向左) elif (direction == 'left'): direction = 'down' elif (direction == 'down'): direction = 'right' elif (direction == 'right'): direction = 'up' print(direction) elif (event.key == pygame.K_b): # 如果是按键b被按下 if (direction == 'up'): # 如果原来方向为up(向上) direction = 'right' # 将方向设为right(向右) elif (direction == 'right'): direction = 'down' elif (direction == 'down'): direction = 'left' elif (direction == 'left'): direction = 'up' print(direction) # 定义移动方式def move(): global direction if direction == 'left': # 如果方向为left head.col-=1 # 设置蛇头向左移动一格(蛇头所在的列数-1) elif direction == 'right': head.col+=1 elif direction == 'up': head.row-=1 elif direction == 'down': head.row+=1 # 定义吃食物def eat(): global food eating = (head.row == food.row and head.col == food.col) # 定义正在吃的形式:蛇头的行列位置与食物相同 if eating : # 如果正在吃 food = Point(row=random.randint(0,ROW-1),col=random.randint(0,COL-1)) # 在随机处再生成一颗食物 snakes.insert(0,head.copy()) # 处理蛇身:1、把原来的头,插入到蛇身的最初位置(即在snakes蛇身列表的第0个位置增加一个元素) if not eating: # 如果不在吃了,吃完后 snakes.pop() #处理蛇身:2、把蛇身的最后一格移除(即移除snakes蛇身列表的最后一个元素) # 定义游戏结束def game_over(): global run dead=False # 定义一个状态dead # 游戏结束方式1、撞墙 if head.col<0 or head.row<0 or head.col>=COL or head.row>=ROW: # 如果蛇头的行和列在屏幕外 dead = True # 游戏结束方式2、撞自己 for snake in snakes: if head.col==snake.col and head.row==snake.row: # 如果蛇头和蛇身位置相同 dead = True break if dead: # 如果状态为dead score = font.render('Your Score is ' + str(10*len(snakes)-30), False, 'pink') # 计算得分 window.blit(score, (40,250)) # 在窗口上显示得分 pygame.display.flip() # Refresh all displays to the screen # 更新所有显示的内容到屏幕 print("GG") # goodgame! =-= time.sleep(5) # delay 5 seconds run=False # set state False direction = 'left' # 定义初始方向为leftrun = True # 定义初始运行状态为True,表示运行while run: # 游戏循环 window.fill(bg_color) # fillcolor # 填充窗口的背景颜色 # 以小方格来定义蛇身、蛇头和食物 for snake in snakes: rect(snake,snake_color) # 创建蛇身,颜色为snake_color rect(head,head_color) # 创建蛇头,颜色为head_color rect(food,food_color) # 创建食物,颜色为food_color eat() # 吃 detect() # 事件监测 move() # 移动 game_over() # 结束游戏 pygame.display.flip() # Refresh all displays to the window # 更新所有待显示的内容到屏幕 time.sleep(0.2) # delay 0.2 seconds # 可修改延时的时间改变蛇的移动速度,调整游戏难易度

2、程序运行

STEP1:远程连接行空板

STEP2:运行程序并观察效果

运行程序后,我们可通过板载按键a、b控制蛇的移动,当蛇撞上自身或撞上窗口四边时,游戏结束,此时可看到我们游戏的最终得分。

 

DFRobotDFRobot

挑战自我

1、和同学比一比,看谁的得分更高吧!

2、尝试减小屏幕刷新的时间间隔,使蛇移动得更快,加大难度试一试吧!

3、想一想,我们是否可以给不同难度的游戏设置关卡呢,自己动手修改程序,练习一下吧!

审核编辑:符乾江

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分