目录
0 引言
1 环境
2 需求分析
3 代码实现
4 后记
0 引言
前几天,星球有人提到贪吃蛇,一下子就勾起了我的兴趣,毕竟在那个Nokia称霸的年代,这款游戏可是经典中的经典啊!而用Python(蛇)玩Snake(贪吃蛇),那再合适不过了
1 环境
操作系统:Windows
Python版本:3.7.3
2 需求分析
我们先来回顾下贪吃蛇中的游戏元素及游戏规则。
首先呢,需要有贪吃蛇、有食物;需要能控制贪吃蛇来上下移动获取食物;贪吃蛇在吃取食物后,自身长度增加,同时食物消失并随机生成新的食物;如果贪吃蛇触碰到四周墙壁或是触碰到自己身体时,则游戏结束。
游戏规则就是这么简单,接下来我们借助一个第三方库pygame来实现它。
Pygame是一个利用SDL库的游戏库, 是一组用来开发游戏软件的 Python 程序模块。
SDL(Simple DirectMedia Layer)是一个跨平台库,支持访问计算机多媒体硬件(声音、视频、输入等),SDL非常强大,但美中不足的是它是基于 C 语言的。
PyGame是 SDL 库的 Python 包装器(wrapper),Pygame 在SDL库的基础上提供了各种接口,从而使用用户能够使用python语言创建各种各样的游戏或多媒体程序。
它的安装方法很简单,如下:
pip install pygame
想要了解更多pygame功能的朋友也可以查阅官方的文档。
3 代码实现
首先导入我们要用到的模块,除了第三方库pygame外,我们还会用到一些Python内置的模块如sys、random、time等,一并导入即可。
import
pygame
,
sys
,
random
,
time
# 从pygame模块导入常用的函数和常量
from
pygame
.
locals
import
*
3.1 一些全局参数的初始化
接下来,我们需要声明一些全局参数。如初始化pygame、定义游戏窗口的大小、窗口的标题、定义全局的颜色变量等信息。
# 初始化Pygame库
pygame
.
init
(
)
# 初始化一个游戏界面窗口
DISPLAY
=
pygame
.
display
.
set_mode
(
(
640
,
480
)
)
# 设置游戏窗口的标题
pygame
.
display
.
set_caption
(
'人人都是Pythonista - Snake'
)
# 定义一个变量来控制游戏速度
FPSCLOCK
=
pygame
.
time
.
Clock
(
)
# 初始化游戏界面内使用的字体
BASICFONT
=
pygame
.
font
.
SysFont
(
"SIMYOU.TTF"
,
80
)
# 定义颜色变量
BLACK
=
pygame
.
Color
(
0
,
0
,
0
)
WHITE
=
pygame
.
Color
(
255
,
255
,
255
)
RED
=
pygame
.
Color
(
255
,
0
,
0
)
GREY
=
pygame
.
Color
(
150
,
150
,
150
)
3.2 初始化贪吃蛇及食物
游戏中需要有贪吃蛇及食物,我们给定一个初始值。我们将整个界面看成许多20*20的小方块,每个小方块代表一个标准小格子,贪吃蛇的长度就可以用几个标准小格子表示。我们将贪吃蛇身体用列表的形式存储,方便之后的删减。
‘’‘初始化贪吃蛇及食物’’’
# 贪吃蛇的的初始位置
snake_Head
=
[
100
,
100
]
# 初始化贪吃蛇的长度 (注:这里以20*20为一个标准小格子)
snake_Body
=
[
[
80
,
100
]
,
[
60
,
100
]
,
[
40
,
100
]
]
# 指定蛇初始前进的方向,向右
direction
=
"right"
# 给定第一枚食物的位置
food_Position
=
[
300
,
300
]
# 食物标记:0代表食物已被吃掉;1代表未被吃掉。
food_flag
=
1
3.3 实现贪吃蛇的上下左右移动
我们需要控制贪吃蛇的上下左右的移动,这里通过监听键盘输入来实现。利用键盘中的上下左右键或WASD键来控制贪吃蛇的运动。
# 检测按键等Pygame事件
for
event
in
pygame
.
event
.
get
(
)
:
if
event
.
type
==
QUIT
:
# 接收到退出事件后,退出程序
pygame
.
quit
(
)
sys
.
exit
(
)
# 判断键盘事件,用 方向键 或 wsad 来表示上下左右
elif
event
.
type
==
KEYDOWN
:
if
(
event
.
key
==
K_UP
or
event
.
key
==
K_w
)
and
direction
!=
DOWN
:
direction
=
UP
if
(
event
.
key
==
K_DOWN
or
event
.
key
==
K_s
)
and
direction
!=
UP
:
direction
=
DOWN
if
(
event
.
key
==
K_LEFT
or
event
.
key
==
K_a
)
and
direction
!=
RIGHT
:
direction
=
LEFT
if
(
event
.
key
==
K_RIGHT
or
event
.
key
==
K_d
)
and
direction
!=
LEFT
:
direction
=
RIGHT
接下来就是将蛇前进方向按照键盘的输入进行转弯操作,并将蛇的头部当前的位置加入到蛇身的列表中。
# 根据键盘的输入,改变蛇的头部,进行转弯操作
if
direction
==
LEFT
:
snake_Head
[
0
]
-=
20
if
direction
==
RIGHT
:
snake_Head
[
0
]
+=
20
if
direction
==
UP
:
snake_Head
[
1
]
-=
20
if
direction
==
DOWN
:
snake_Head
[
1
]
+=
20
# 将蛇的头部当前的位置加入到蛇身的列表中
snake_Body
.
insert
(
0
,
list
(
snake_Head
)
)
3.4 判断是否吃到食物
如果蛇头与食物的位置重合,则判定吃到食物,将食物数量清零;而没吃到食物的话,蛇身就会跟着蛇头运动,蛇身的最后一节将被踢出列表。
# 判断是否吃掉食物
if
snake_Head
[
0
]
==
food_Position
[
0
]
and
snake_Head
[
1
]
==
food_Position
[
1
]
:
food_flag
=
0
else
:
snake_Body
.
pop
(
)
3.5 重新生成食物
当游戏界面中的食物数量为0时,需要重新生成食物。利用random函数来生成随机位置
# 生成新的食物
if
food_flag
==
0
:
# 随机生成x, y
x
=
random
.
randrange
(
1
,
32
)
y
=
random
.
randrange
(
1
,
24
)
food_Position
=
[
int
(
x
*
20
)
,
int
(
y
*
20
)
]
food_flag
=
1
3.6 绘制贪吃蛇、食物、分数等信息
定义贪吃蛇的绘制函数
# 绘制贪吃蛇
def
drawSnake
(
snake_Body
)
:
for
i
in
snake_Body
:
pygame
.
draw
.
rect
(
DISPLAY
,
WHITE
,
Rect
(
i
[
0
]
,
i
[
1
]
,
20
,
20
)
)
定义食物的绘制函数
# 绘制食物的位置
def
drawFood
(
food_Position
)
:
pygame
.
draw
.
rect
(
DISPLAY
,
RED
,
Rect
(
food_Position
[
0
]
,
food_Position
[
1
]
,
20
,
20
)
)
定义分数的绘制函数
# 打印出当前得分
def
drawScore
(
score
)
:
# 设置分数的显示颜色
score_Surf
=
BASICFONT
.
render
(
'%s'
%
(
score
)
,
True
,
GREY
)
# 设置分数的位置
score_Rect
=
score_Surf
.
get_rect
(
)
score_Rect
.
midtop
=
(
320
,
240
)
# 绑定以上设置到句柄
DISPLAY
.
blit
(
score_Surf
,
score_Rect
)
这些都定义好之后,我们需要在游戏主逻辑中调用它们,并刷新Pygame的显示层,贪吃蛇与食物的每一次移动,都会进行刷新显示层的操作来显示。最后我们可以设定一个速度值来合理控制游戏执行的速度。
DISPLAY
.
fill
(
BLACK
)
# 画出贪吃蛇
drawSnake
(
snake_Body
)
# 画出食物的位置
drawFood
(
food_Position
)
# 打印出玩家的分数
drawScore
(
len
(
snake_Body
)
-
3
)
# 刷新Pygame的显示层,贪吃蛇与食物的每一次移动,都会进行刷新显示层的操作来显示。
pygame
.
display
.
flip
(
)
# 控制游戏速度
FPSCLOCK
.
tick
(
7
)
3.7 定义游戏结束的画面并判断游戏是否结束
定义函数,用于展示游戏结束的画面并退出程序
# 游戏结束并退出
def
GameOver
(
)
:
# 设置GameOver的显示颜色
GameOver_Surf
=
BASICFONT
.
render
(
'Game Over!'
,
True
,
GREY
)
# 设置GameOver的位置
GameOver_Rect
=
GameOver_Surf
.
get_rect
(
)
GameOver_Rect
.
midtop
=
(
320
,
10
)
# 绑定以上设置到句柄
DISPLAY
.
blit
(
GameOver_Surf
,
GameOver_Rect
)
pygame
.
display
.
flip
(
)
# 等待3秒
time
.
sleep
(
3
)
# 退出游戏
pygame
.
quit
(
)
# 退出程序
sys
.
exit
(
)
在游戏主逻辑中加入判断,游戏是否结束
'''游戏结束的判断'''
# 贪吃蛇触碰到边界
if
snake_Head
[
0
]
<
0
or
snake_Head
[
0
]
>
620
:
GameOver
(
)
if
snake_Head
[
1
]
<
0
or
snake_Head
[
1
]
>
460
:
GameOver
(
)
# 贪吃蛇触碰到自己
for
i
in
snake_Body
[
1
:
]
:
if
snake_Head
[
0
]
==
i
[
0
]
and
snake_Head
[
1
]
==
i
[
1
]
:
GameOver
(
)
4 后记
本文利用Pygame模块实现了最简单的贪吃蛇版本。当然还有很多需要优化的地方,比如随机生成食物时如何避免出现在贪吃蛇的自身上、通过贪吃蛇的长度来自动控制游戏速度等等。更高级一点的有如何通过AI自动玩贪吃蛇、贪吃蛇的双人对战等,期待大家利用Python可以把贪吃蛇玩出一个新的高度!
公众号「 Python专栏 」后台回复关键字「 贪吃蛇 」获取本文全套完整代码!