Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础上开发。我们今天将利用它来制作一款大家基本都玩过的小游戏——贪吃蛇。

一、需要导入的包

?
1
2
3
import pygame
import time
import random
  • pygame:获取图形组件构建游戏
  • time:主要用来设置帧率
  • random:主要用来设置食物的刷新位置

二、窗口界面设置

首先我们初始化游戏,建立一个窗口

?
1
pygame.init()

然后我们定义游戏中需要使用的颜色,在这个示例中,我们定义了六种颜色

?
1
2
3
4
5
6
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)

接下来,我们设置窗口的尺寸和标题栏,在这个示例中,我们将窗口设置为800*600

?
1
2
3
4
5
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('贪吃蛇游戏')

三、游戏中的变量

初始化一个clock变量,使用开头导入的time包。这个变量将用来处理游戏的帧率。

?
1
clock = pygame.time.Clock()

定义蛇的速度与大小。可以随意更改,选择你适应的即可

?
1
2
snake_block = 10
snake_speed = 12

设置分数显示和其他信息的字体大小与样式。

?
1
2
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)

四、设置功能函数

定义三个辅助功能函数,实现以下功能。

  • 显示计算分数
  • 蛇的参数
  • 其他消息显示,比如失败后的重玩提示。

首先,定义一个计算分数的函数

?
1
2
3
def Your_score(score):
value = score_font.render("Your Score: " + str(score), True, yellow)
dis.blit(value, [0, 0]

接下来定义蛇的参数。我们定义了蛇的颜色,位置与大小,即snake_block。我们额外定义了一个snake_list作为输入,将在下面用到。

?
1
2
3
def our_snake(snake_block, snake_list):
for x in snake_list:
pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])

最后定义一个消息显示函数,这个辅助函数将msg和颜色作为输入参数。我们将设置字体,然后以所需的颜色显示信息。我们需要指定信息在游戏中显示的位置。

?
1
2
3
def message(msg, colour):
mesg = font_style.render(msg, True, colour)
dis.blit(mesg, [width / 6, height / 3])

五、构建游戏

开始建立游戏循环,让游戏运行并能响应键盘输入。首先定义两个变量game_over和game_close,用来描述游戏的状态。第一个提示游戏是否结束,下一个定义是否关闭游戏。都定义为false

?
1
2
game_over = False
game_close = False

下一步,我们将定义x1和y1来表示蛇在游戏中的位置。我们分别初始化它们的宽度/2和高度/2。同时,我们将定义变量x1_change和y1_change来表示蛇的位置根据用户提供的输入而发生的变化。

?
1
2
3
4
5
x1 = width / 2
y1 = height / 2
x1_change = 0
y1_change = 0

另外,我们还需要定义snake_List和snake_length变量,分别存储蛇的所有头部位置和蛇的长度。

?
1
2
snake_List = []
snake_length = 1

吃掉食物新食物产生的位置,用random模块来实现。

?
1
2
foodx = round(random.randrange(0, width — snake_block) / 10.0) * 10.0
foody = round(random.randrange(0, height — snake_block) / 10.0) * 10.0

接下来,我们将启动一个循环,直到game_over变成True为止。

在这个循环中,我们将首先定义在 game_close 变量为 True 时要执行的指令。

下面的代码将帮助我们处理game_close等于True时的情况。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
while game_close == True:
dis.fill(blue)
message("Lost! q quit or p again", red)
Your_score(Length_of_snake - 1)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
if event.key == pygame.K_p:
gameLoop()

如你所见,我们已经定义了很多东西。我们用蓝色填充显示(你当然可以选择你的颜色)。游戏结束时,我们显示一条消息,显示该用户输掉了游戏,我们应该询问用户是想再玩一次还是退出游戏。

我们也会显示用户的分数,等于蛇的长度减1。每当我们的蛇吃到食物时,我们都会更新1分。

现在,为了接受用户关于他是想再玩一次还是退出游戏的输入,我们定义了一个for-loop。当我们要求用户输入关于他的决定时,我们定义了输入的可能性。

如果用户输入的是'p',那么我们将继续我们的游戏循环。如果用户输入的是'q',那么我们就需要退出游戏。

现在,在处理完game_close的条件后,我们将定义所有需要的步骤,这将使我们的蛇根据用户的输入移动。我们将接受W、A、S、D和上、下、左、右键组合来进行游戏。你可以自由选择你的按键来玩游戏。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
x1_change = -snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
x1_change = snake_block
y1_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_w:
y1_change = -snake_block
x1_change = 0
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
y1_change = snake_block
x1_change = 0

在上面的代码中,我们根据用户提供的输入改变x1_change和y1_change的值。同时,如果用户想退出游戏,我们也会退出游戏。

接下来,我们将定义输掉游戏的条件。同时,我们借助x1_change和y1_change更新x1和y1的值。我们还将用蓝色填充整个显示屏,并通过在显示屏中传递蛇和食物的出现位置来绘制它们。

?
1
2
3
4
5
6
if x1 >= width or x1 < 0 or y1 >= height or y1 < 0:
game_close = True
x1 += x1_change
y1 += y1_change
dis.fill(blue)
pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])

接下来,我们定义一个名为snake_Head的列表,它将在每次迭代后存储蛇头的值。我们将x1和y1的值追加到它上面。然后,我们将该snake_Head追加到snake_List中。

然后我们检查条件检查snake_List的长度是否大于snake_length。如果是,则删除snake_List中的第一个元素。

然后,我们检查当前的snake_Head是否等于snake_List中的任何一个元素,除了新增加的那个元素,也就是被检查的snake_Head。如果是,那么我们就关闭游戏,玩家就输了。

这是因为在snake_List中出现snake_Head意味着它曾经被添加到snake_List中,再次找到相同的值意味着蛇碰到了自己。所以,此时游戏介绍。

然后我们调用函数our_snake和Your_score(前面定义的),并将所需参数传递给这些函数,以显示更新后的蛇和玩家的分数。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
snake_Head = []
snake_Head.append(x1)
snake_Head.append(y1)
snake_List.append(snake_Head)
if len(snake_List) > snake_length:
del snake_List[0]
for x in snake_List[:-1]:
if x == snake_Head:
game_close = True
our_snake(snake_block, snake_List)
Your_score(snake_length — 1)
pygame.display.update()

接下来,我们将在蛇吃完前一个食物后,形成新的食物。所以,为了做到这一点,我们需要在显示屏中找到一个新的随机位置来生成食物。另外,由于蛇刚吃完食物,我们需要将蛇的长度增加1。

最后,我们将蛇的速度作为参数给clock.tick,作为游戏的帧率。

?
1
2
3
4
5
6
if x1 == foodx and y1 == foody:
foodx = round(random.randrange(0, width — snake_block) / 10.0) * 10.0
foody = round(random.randrange(0, height — snake_block) / 10.0) * 10.0
snake_length += 1
clock.tick(snake_speed)

功能已经完全实现,我们最后退出游戏,并再次调用游戏循环

?
1
2
3
4
pygame.quit()
quit()
gameLoop()

六、完整代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import pygame
import time
import random
pygame.init()
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('贪吃蛇')
clock = pygame.time.Clock()
snake_block = 10
snake_speed = 15
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)
def Your_score(score):
value = score_font.render("Score: " + str(score), True, yellow)
dis.blit(value, [0, 0])
def our_snake(snake_block, snake_list):
for x in snake_list:
pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
def message(msg, color):
mesg = font_style.render(msg, True, color)
dis.blit(mesg, [dis_width / 6, dis_height / 3])
def gameLoop():
game_over = False
game_close = False
x1 = dis_width / 2
y1 = dis_height / 2
x1_change = 0
y1_change = 0
snake_List = []
Length_of_snake = 1
foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
while not game_over:
while game_close == True:
dis.fill(blue)
message("Lost! q quit or p again", red)
Your_score(Length_of_snake - 1)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
if event.key == pygame.K_p:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
x1_change = -snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
x1_change = snake_block
y1_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_w:
y1_change = -snake_block
x1_change = 0
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
y1_change = snake_block
x1_change = 0
if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
game_close = True
x1 += x1_change
y1 += y1_change
dis.fill(blue)
pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
snake_Head = []
snake_Head.append(x1)
snake_Head.append(y1)
snake_List.append(snake_Head)
if len(snake_List) > Length_of_snake:
del snake_List[0]
for x in snake_List[:-1]:
if x == snake_Head:
game_close = True
our_snake(snake_block, snake_List)
Your_score(Length_of_snake - 1)
pygame.display.update()
if x1 == foodx and y1 == foody:
foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
Length_of_snake += 1
clock.tick(snake_speed)
pygame.quit()
quit()
gameLoop()

更多关于python的文章,欢迎关注python客栈。

标签:

五分钟学会怎么用Pygame做一个简单的贪吃蛇的更多相关文章

  1. python里glob模块知识点总结

    之前遇到过一类问题,要求快速做文件搜索,当时小编找了很多内容,但是没有发现实现方法,突然看到glob模块便豁然开朗了,该模块主要就是能够实现类似于windows的文件搜索,旗下的函数都可以实现搜索功能,并且有很多通配符,能够应用在多种场景中,一一对应的选择解决方案。简单介绍:匹配一定的格式文件和文件......

  2. Python实现微信表情包炸群

    Python实现微信表情包炸群# -*- coding = utf-8 -*- # @Time : 2021/1/26 15:19 # @Author : 陈良兴# @File : 微信表情包炸群.py# @Software : PyCharm# 运行程序 > 输入次数 > 回车 >......

  3. python使用numpy中的size()函数实例用法详解

    在python中,提到如何计算多维数组和矩阵,那一定会想到numpy。numpy定义了矩阵和数组,为它们提供了相关的运算。size中文解释为大家、尺寸的意思,如果想要统计矩阵元素个数,使用size()函数就可以解决。1、Numpy size()函数主要是用来统计矩阵元素个数,或矩阵某一维上的元素个数......

  4. python工业互联网应用实战6

    本章节我们讲述了如何通过admin.py来快速的完成页面功能的构建,并通过自定义action快速的实现了任务分解功能,并根据业务进展也逐步的完善了查看页面以内联表的方式显示作业详情。根据需求定义“任务”是一个完整的业务搬运流程,整个流程涉及到多个机构(设备)分别动作执行多个步骤,所以依据前面的模型设......

  5. Pytorch BertModel的使用说明

    基本介绍环境: Python 3.5+, Pytorch 0.4.1/1.0.0安装:pip install pytorch-pretrained-bert必需参数:--data_dir: "str": 数据根目录.目录下放着,train.xxx/dev.xxx/test.xxx......

  6. python实现excel公式格式化的示例代码

    之前跟一些小伙伴有个讨论:大概就是很多跟数据打交道的朋友都面对过很复杂的excel公式,有时嵌套层数特别多,肉眼观看很容易蒙圈。有了这样的需求,我就有了解决问题的想法,说干就干,于是一个比较牛逼的excel公式格式化的工具就出现了。效果体验先看看效果吧:=IF(C11>100%*C4,IF(C......

  7. python 如何用 Hypothesis 来自动化单元测试

    高质量的代码离不开单元测试,而设计单元测试的用例往往又比较耗时,而且难以想到一些极端情况,本文讲述如何使用 Hypothesis 来自动化单元测试刷过力扣算法题的同学都知道,有时候觉得代码已经很完善了,一提交才发现很多情况没有考虑到。然后感叹力扣的单元测试真的牛比。因此,高质量的代码离不开单元测试,......

  8. Python骚操作从列表推导和生成器表达式开始

    序列序列是指一组数据,按存放类型分为容器序列与扁平序列,按能否被修改分为不可变序列与可变序列。容器序列与扁平序列容器序列存放的是对象的引用,包括list、tuple、collections.deque。扁平序列存放的是对象的值,包括str、bytes、bytearray、memoryview和arr......

  9. python中openpyxl和xlsxwriter对Excel的操作方法

    前几天,项目中有个小需求:提供Excel的上传下载功能,使用模块:openpyxl 和 xlsxwriter,这里简单记录一下。1.简介Python中操作Excel的库非常多,为开发者提供了多种选择,如:xlrd、 xlwt、xlutils、xlwings、pandas、 win32com、open......

  10. Python抓取文件夹的所有文件,包括子文件夹和子文件夹的文件

    #!/user/bin/python # -*- coding:utf8 -*- import Basic import os ##################################################### ######## Input......

随机推荐

  1. .NET Core部署到linux(CentOS)最全解决方案,高阶篇(Docker+Nginx 或 Jexus)

    在前两篇:.NET Core部署到linux(CentOS)最全解决方案,常规篇与.NET Core部署到linux(CentOS)最全解决方案,进阶篇(Supervisor+Nginx)我们对.netcore部署到linux有了一个充分的了解,已经可以满足应用要求了,这篇文章我们继续深入带你了解使......

  2. pandas读取excel,txt,csv,pkl文件等命令的操作

    pandas读取txt文件读取txt文件需要确定txt文件是否符合基本的格式,也就是是否存在\t,,,等特殊的分隔符一般txt文件长成这个样子txt文件举例下面的文件为空格间隔1 2019-03-22 00:06:24.4463094 中文测试 2 2019-03-22 00:06:32.45656......

  3. 在PHP中灵活使用foreach+list处理多维数组的方法

    先抛出问题,有时候我们接收到的参数是多维数组,我们需要将他们转成普通的数组,比如: $arr = [ [1, 2, [3, 4]], [5, 6, [7, 8]],]; 我们需要的结果是元素1变成1,2,3,4,元素2变成5,6,7,8,这时候,我们就可以用foreach配合list来实......

  4. 分布式系统限流算法分析与实现

    一、限流的关键作用 对于大型互联网架构中,限流的设计是必不可少的一个环节。在给定的时间内, 客户端请求次数过多, 服务器就会拦截掉部分请求,避免请求流量过大造成数据库负载高的问题。 二、常见限流算法利弊分析 计数器限流 计数器限流主要有固定窗口计数器和滑动窗口......

  5. linux GPU上多个buffer间的同步之ww_mutex、dma_fence的使用

    原文链接:https://www.cnblogs.com/yaongtime/p/14111134.htmlWW-Mutexes在GPU中一次Render可能会涉及到对多个buffer的引用。所以在command buffer提交到GPU前,需要等到所有依赖的buffer可用。因为这些buffer可......

  6. std::async的使用总结

    C++98标准中并没有线程库的存在,直到C++11中才终于提供了多线程的标准库,提供了管理线程、保护共享数据、线程间同步操作、原子操作等类。多线程库对应的头文件是#include ,类名为std::thread。然而线程毕竟是比较贴近系统的东西,使用起来仍然不是很方便,特别是线程同步及获取线程运行结......

  7. ASP下通过Adodb.Stream实现多线程下载大文件

    有个朋友 做 某种小众音乐交换站的(他们那个行业的昵图网),需要用到付费下载。尝试过 防盗链,不太理想,最终使用了 Adodb.Stream 读取,直接输出。解决了 盗版的问题,但是新的问题又来了。Adodb.Stream 这种方式 电脑还好说,大部分电脑浏览器都支持。移动端 很多 浏览器为了 加速......

  8. 使用Python封装excel操作指南

    前言openpyxl 是 python 中操作 excel 表格比较常用的一个库,可以读取和写入excel文件,支持【.xlsx / .xlsm / .xltx / .xltm】格式的文件,处理excel数据、公式、样式,且可以在表格内插入图表但是在实际项目的使用过程中,如果经常要用到 openpy......

  9. vue使用transition组件动画效果的实例代码

    transition文档地址定义一个背景弹出层实现淡入淡出效果Toggle helloexport default {data: () => ({show: true}),};.fadeBg-enter-active,.fadeBg-leave-active {transition: opa......

  10. 如何查看postgres数据库端口

    如下所示:Linux:netstat -a | grep PGSQL示例输出:[highgo@hgdbt data]$ netstat -a | grep PGSQLunix 2 [ ACC ] STREAM LISTENING 14710 /tmp/.s.PGSQL.5866补充:post......