引言大家好在平淡的编程日常学习中我继C语言之后又学习了python语言肯定会有人会问这两种语言哪个好学哪个好用呢就我个人学习的经历来说python好学更具趣味性同时它也好用至少它上手应用快。咳咳回归正题今天咱们就来讲讲如何使用python语言来开发一个贪吃蛇小游戏完整代码我放在了文章最后需要的同学可以自己拿。我将整个过程归纳为八个大点1.图片素材准备2.导入模块3.绘制界面4.绘制贪吃蛇饲料5.绘制贪吃蛇6.游戏规则设计7.打包8.代码一.图片素材准备请自行准备两张图片素材来作为游戏结束背景和游戏彩蛋图片。比如下面这两张二.导入模块在这里我主要讲以下三点1.如何导入模块2.没有对应模块该如何下载3.导入自定义模块的两种方法1如何导入模块语法import 模块名import pygame2没有对应模块该如何下载以我使用的pyCharm为例子1.首先要找到终端的功能点击它图中被黄色标记的图标就是终端功能。2.输入下载指令下载的指令有两种选择1.pip install 库名模块名 下载安装的是国外源⾥⾯的库 , 下载的会很慢 , 如果愿意等是没关系的2.pip install 库名模块名 -i 镜像源国内的国内的镜像源地址清华⼤学 https://pypi.tuna.tsinghua.edu.cn/simple/阿⾥云http://mirrors.aliyun.com/pypi/simple/中国科学技术⼤学 http://pypi.mirrors.ustc.edu.cn/simple/华中科技⼤学http://pypi.hustunique.com/⾖瓣源http://pypi.douban.com/simple/腾讯源http://mirrors.cloud.tencent.com/pypi/simple华为镜像源https://repo.huaweicloud.com/repository/pypi/simple镜像源地址起到的作用就像是连锁店一样本来需要在国外的仓库里下载的东西用了镜像源之后就可以在国内仓库下载这二者之间的距离想必大家应该清楚这节省了多少时间。3导入自定义模块的方法导入自定义模块又两种方法1.常规导入方式导入语法import 模块文件名调用语法模块文件名.函数名模块文件中你需要调用的函数名是否需要参数看你是怎么写的函数例如2.对应调用模块函数方式导入语法from 模块文件名 import 函数名模块文件中你需要调用的函数名是否需要参数看你是怎么写的函数调用语法函数名模块文件中你需要调用的函数名是否需要参数看你是怎么写的函数#可以直接调用函数例如三.绘制界面绘制界面我也分成几点1.初始化模块2.创建游戏界面和标题3.设置颜色背景颜色蛇的颜色蛇饲料的颜色等4.图片文字处理5.建立循环使游戏不断运行不断刷新以及退出设置。1.初始化模块init()用于初始化模块pygame的所有功能而pygame就是用于创建游戏方面的模块接下来主要就是用它来完成游戏的创建。2.创建游戏界面和标题1280,720这个参数哪里来的呢这就要问set_mode这个函数是干什么得了它是用来创建游戏界面的那我们的背景是不是要填满它没错需要所以这里我们就直接用图片的大小宽和高参数来设置游戏界面的大小。有人可能会问1280,720的参数是怎么查看的其实很简单鼠标右键点击文件夹中的图片点击属性选择详细信息我们用的数据就是其中的分辨率。3.设置颜色(255,252,22)这一串数据就代表了一种颜色那这一串数据怎么来的呢也很简单只要你找一个有截图功能的软件截图的时候就可以看到颜色数据比如钉钉。上面的三个数据会随着你的鼠标停留的目标变换而变换。4.图片文字处理pygame.font.SysFont(华文行楷,50)华文行楷参数一字体类别name50参数二字体大小size作用是设置在游戏界面种打印出来的字体和字体大小。到时候可以作为参数引用并且可以设置多种字体。pygame.image.load(imge/snake_end.png)是为了引用图片素材到程序中。图中图片的路径是如何找出来的呢其实很简单如果你的图片放在其他位置可以直接用鼠标右键点击然后选择复制文件地址拿过来就行了“E:\\database\\code data\\python数据库\\python项目\\pythonProject1\\24.python-贪吃蛇大作战游戏-8月12日\\imge\\蛇.png ”当然我建议文件地址复制过来之后像我一样多加一条斜杠这是为了防止转义字符影响文件地址的使用当然你也可以使用正斜杠“/”这样就不会被影响了。同样的如果你的文件就在项目里的话你也可以直接用鼠标右键点击图片文件选择复制路径在点击来自内容根的路径在地址拿过来之后修改一下只留下图片文件夹开头就行前提是图片文件夹与调用文件处于同一目录下就像这样“imge/snake_end.png”有些时候你觉得你的图片太大了不符合自己的心意或者游戏界面装不下你就可以使用以下函数扩大或这缩小它# 扩大 end_photopygame.transform.scale(end_photo,(1280,720)) # 缩小 color_eggpygame.transform.scale(color_egg,(500,400))pygame.transform.scale(),参数一更改目标参数二更改后数据要变成多大多小扩大和缩小只看你填的参数大小不过我不建议扩大很多扩大并不会增加图片细节只是将原有像素放大所以图片会越来越模糊而缩小是合并像素会相对清晰5.建立循环上图中# 事件设置 for event in pygame.event.get():#获得所有事件什么是事件呢其实事件就像是程序中某个状态改变或者动作发生的标记就像是交通信号灯控制等待与同行根据条件的触发来给出对应的回答。而这里的pygame.event.get()则代表获取电脑上所有发生的事件键盘的输入或者鼠标点击哪里都算事件通过for循环将其放入event名字可以自己取中。而我们想要设置一个退出的条件就可以用事件来一一对比我们所设置的条件是否触发就比如pygame.QUIT它就代表了窗口右上角的×意思是×被鼠标点击。只要满足条件就可以进入当前if语句中。pygame.quit()# 关闭所有窗口和功能 sys.exit()#退出程序上面的内容我相信大家看注释也能看明白不过我要提醒一点如果想要sys.exit()生效就需要引入对应模块。import sys当我们做完了以上步骤就可以运行程序看看效果了图中左上角就可以看到一行小字这就是之前我们设置的标题现在我们的窗口内是黑色的当然这是它默认的颜色和我们设置颜色并没有关系接下来我们就需要填充背景和绘制图文blit参数一绘制目标参数二绘制的位置这个参数其实是对应xy坐标以窗口从上往下为y0-上限以窗口从左到右为x0-上限绘制图片其实就和截图一样都是有一个起点的而这个坐标就是图片文字左上角的起点图中我们运用if else语句简单写了一个判断游戏是否运行的语句如果游戏正在运行那么就填充背景反之则绘制结束背景图。当然因为背景是黑色我们看不到变化所以我们将game_over的False改为True我们就可以直接看到结束背景图绘制的效果了四.绘制贪吃蛇饲料绘制蛇饲料分为以下几步1.设置蛇饲料的参数2.绘制蛇饲料1设置蛇饲料的参数首先在设置蛇饲料参数之前我们要先导入一个模块。random模块适用于生成伪随机数和执行随机化操作为什么是伪随机数那首先我们要知道什么是随机数不可预测的才是随机数但是random它的随机数都是基于数学算法算出来的只要知道参数并且主动设置了种子默认的是系统时间那么结果就是可预测的,所以说它是伪随机数但对于我们当前制作的小游戏来说只要随机出来的数字不是明显可预测的就行也就没有什么伪不伪的说法了。什么是随机化操作随机选择随机打乱等这些都是随机化操作接下来就是设置蛇饲料的参数random.randint(20,1200),取20-1200的随机数为什么要除以10.0呢因为蛇饲料的大小是10为单位除以10.0用round()取整在乘以10就可以防止出现除了10的倍数之外的值。2绘制蛇饲料当我们准备好了参数后就可以使用函数来绘制了这里我们简单介绍一下pygame.draw.rect()这个函数的功能是用来画矩形的参数分别是那些table是背景颜色food_color是蛇饲料的颜色food_x,food_y,是蛇饲料在窗口中的位置坐标x,y,food_size,设置的是长宽。下面是达成的效果图五.绘制贪吃蛇绘制贪吃蛇的步骤如下1.设置贪吃蛇需要用到的参数2.绘制贪吃蛇3.让贪吃蛇动起来1设置贪吃蛇需要用到的参数以上就是我们绘制一条贪吃蛇所需要的参数他们分别起到了什么作用大家可以通过注释了解。其中snake_body,我们使用的是列表方便记录贪吃蛇的每个身体节点的位置。2绘制贪吃蛇当我们做好准备之后可以开始绘制我们的贪吃蛇了pygame.draw.rect(table,snake_color,(x,y,snake_size,snake_size))如果我们只想绘制贪吃蛇只需要像绘制矩形一样绘制出贪吃蛇就行了具体用法我们看上面绘制蛇饲料哪里就行具体效果如下黄色矩形就是我们的贪吃蛇了。3让贪吃蛇动起来那如何让我们的贪吃蛇动起来呢首先我们得用之前我们设置好的snake_body列表记录我们贪吃蛇的节点坐标也就是当前的蛇头的位置我们可以写成snake_head[]然后将我们蛇头的坐标记录在其中snake_head[snake_x,snake_y]最后通过修改snake_x,snake_y的数值在用for循环来循环绘制达到移动的目的但如果只是不断的绘制的话最终只能绘制出一条直线所以我们需要删掉修改前的旧节点。以上写成代码运行视频https://live.csdn.net/v/515836https://live.csdn.net/v/515836我们动起来还不够我们需要能控制它上下左右的行动方向这才是一条蛇而不是一个会平移的矩形想要做到这一点我们需要怎么做呢首先通过键盘来控制贪吃蛇的移动方向这属于是一种事件而事件我们只需要在事件设置中写具体代码如下if event.typepygame.KEYDOWN:#获取键盘上的操作通过这串代码我们可以获得用户在键盘上的操作你想获得哪个键的操作情况就可以它下面具体是那个键触发后又该有什么的效果很简单不是吗就像下面这样# 获取键盘上的操作 if event.typepygame.KEYDOWN: if event.keypygame.K_LEFT:#获取左键的情况是否触发 #如果触发左键就执行以下语句 #左转 direction_x-1 direction_y0我们的移动其实就是将一个窗口划分程很多个小格子然后将小格子作为坐标轴的单位这样我们不管是蛇还是蛇饲料它们的坐标就等于通过修改横竖小格子数量来控制移动同理我们也可以修改坐标来控制方向。snake_xdirection_xsnake_ydirection_y而这一步就是将我们的键盘与贪吃蛇正式链接起来snake_x和snake_y是蛇头的坐标换句话说最新的一个坐标才是蛇头通过修改它就可以控制贪吃蛇的行动方向。运行视频https://live.csdn.net/v/515854https://live.csdn.net/v/515854六.游戏规则设计游戏规则主要针对以下几点1延时2吃到蛇饲料3出界4吃到自己5游戏时计分6彩蛋出现条件7自动加速1延时当我们运行游戏时我们会发现贪吃蛇的移动速度貌似有点太快了不好调试当这种时候我们就需要有一个延时功能来帮助我们调试代码。首先我们要导入时间相关模块import time然后在我们代码的倒数第二排写以下代码time.sleep(1 / 80)最后……就没了没错就这么简单运行视频https://live.csdn.net/v/515872https://live.csdn.net/v/5158722吃到蛇饲料当我们的蛇动起来后我们就得想办法让它吃东西不然怎么叫贪吃蛇呢顺便长身体。if abs(snake_x-food_x)snake_size and abs(snake_y-food_y)snake_size:abs()功能是返回绝对值通过abs(snake_x-food_x)计算出的绝对值我们就知道了蛇头距离蛇饲料的距离是否已经吃到了食物不管贪吃蛇在蛇饲料左边还是右边同理上下也可以知道这样我们就可以判断出蛇是否吃到蛇饲料。# 吃到了 food_x round(random.randint(20, 1200) / 10.0) * 10.0 food_y round(random.randint(20, 700) / 10.0) * 10.0 # 吃到食物的标记1 snake_length1吃到了我们就需要更新蛇饲料的坐标重新绘制一个蛇饲料并且记录下我们吃到的次数。# 如果蛇吃到食物就会变长反之则剪掉前一步 if len(snake_body) snake_length: del snake_body[0]这一步就是为了保证每吃到一次食物贪吃蛇就会多出一个节点长一小段也是为了防止无限拉长。3出界通过使用snake_x,snake_y,横竖的坐标来对比窗口的大小1280*720来判断是否出界game_overTruetextf.render(游戏结束祝大家蛇年快乐,True,font_color)game_overTrue,宣告游戏结束text装的是文本f.render,f指的是用之前设置好的字体render即渲染将准备好数据转化为可视化也就是在屏幕上输出。运行视频https://live.csdn.net/v/516030https://live.csdn.net/v/5160304吃到自己除了出界吃到自己或者说碰到自己身体的任何一部分都算游戏结束我实现这个功能整体的思想是先遍历一遍贪吃蛇出蛇头外的所有的节点然后与蛇头的坐标进行比对是否符合来达到判断是否吃到自己的目的我实现的比较粗略但大致的功能也算是实现了有兴趣的同学可以尝试着细化。table.blit(text, (550, 50))table.blit图像坐标blit在pygame中是绘制图像的核心方法全称“Bit Block Transfer”,也就是位块传输简单来说blit就是贴图操作在对应的位置贴上预设好的图片文字的图像。运行视频https://live.csdn.net/v/516035https://live.csdn.net/v/5160355游戏时计分一个游戏如果只是一条贪吃蛇在哪里不断的吃东西那有什么意思我们得知道它吃了多少才能体现大家的技术高低不是所以我们得为每次吃下的食物计分并且标明相关的文本。首先想要在一个文本中控制分数自动变化那就需要设置一个变量保证分数变化文本中的分数也要一起变化:我们先添加变量score,用来记录分数。然后在11点的部分中添加score10,意思是每当贪吃蛇吃掉一颗蛇饲料就会获得10分。我们可以看出在这里我把蛇的坐标給移到了if语句中意思是当游戏开始时贪吃蛇就可以不断移动但游戏结束后就不会移动。textf.render(f游戏运行中目前分数{score},True,font_color)# 当游戏运行时创建如果删除则不会创建就找不到正在运行时需要的对应text以上的代码我前面我都讲过功能用法这里我讲一下细节{f游戏运行中目前分数{score}这里的f是为了在文本中插入变量用的这应该算是python语言的特色用法为什么我会在这串代码后面写下这就注释呢因为我将所有text所需要的blit,集中成了一排代码放在了最外层倒数第三排不算注释的话这样就减少了我们的代码量虽然只减少了两句。这样我们就将141213中的blit给写成了一句因为它们都是在不同情况下创建text。运行视频https://live.csdn.net/v/516222https://live.csdn.net/v/5162226彩蛋出现条件我们游戏有时候也需要点彩蛋作为小奖励当贪吃蛇成长到一定地步就会跳出来一张图片作为彩蛋我们也不写太复杂的机制我们就采用等差数列的规律来安排每隔100分弹出一次。这里我们首先同样是创建变量a作为计数器在吃到蛇饲料时计数并且通过if语句作为判断并用and,提出了三个必须同时满足的条件使彩蛋每增加100分的时候出现一次彩蛋而我猜肯定有人会认为下面这句代码是多余的。if a6: a0这段代码在这里有三个作用1.重置计数器让控制彩蛋显示的变量a不会无限增大2.终止彩蛋显示通过重置a为 0让a1的条件不成立从而让彩蛋只短暂显示后消失3.支持循环触发重置后下次分数达到 100 的倍数时彩蛋能再次触发显示。运行视频https://live.csdn.net/v/516223https://live.csdn.net/v/5162237自动加速为什么在加了延迟的情况下还要加自动加速呢首先加延迟是因为贪吃蛇初始移动速度过快我们需要延时才好操作而加自动加速则是因为贪吃蛇总不能一直维持在一个很慢的速度吧所以我们要增加自动加速的功能。我们自动加速的规则很简单和彩蛋出现的条件相同只要增加100分就加一次速。我们怎么做到加速这一步呢很简单还记得这一步吗snake_xdirection_x snake_ydirection_y我们只需要将direction_x或者_y固定增加的值换成提前创建的变量add,就可以控制他贪吃蛇的移动速度。七.打包# file3.打包.py # authorwangjing-0522 # specifics; # 1 安装打包库 # pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple # 2.转到对应项目目录 # cd 21.python-FishingJoygame-8月7日 # 3.输⼊打包命令 # pyinstaller -F -w 启动程序 关联程序注意-w是小写间隔三格 # pyinstaller -F 启动程序 关联程序间隔三格(如果没有终端窗口的话) # 启动程序表示你的主程序也就是代码的开始 # 如果有其他程序需要⼀起打包,需要使⽤关联程序,如果没有,可以忽略 # 如果只是单独的python代码,没有界⾯窗体的,建议去掉-w,因为会直接显示控制条,其实这⼀类打 # 包没有太⼤意义 # 4.观察打包结束后的⽂件夹,exe就在dist⽂件夹中 # 5.注意事项 # 1解决办法: 将图⽚等资源⽂件放⼊dist中 # 2最后打包2个⼀起发给好兄弟即可八.代码# file贪吃蛇大作战小游戏.py # authorwangjing_0522 # specifics; import time import pygame import sys import random # 1.初始化模块 pygame.init() # 2.创建游戏界面1280,720和标题 # 游戏界面 tablepygame.display.set_mode((1280,720)) # 游戏标题 pygame.display.set_caption(贪吃蛇蛇年大作战) # 3.设置颜色 # 背景颜色 black_color(0, 0, 0) # 蛇的颜色 snake_color(255,252,22) # 蛇饲料颜色 food_color(249,35,255) # 字体颜色 font_color(0,255,0) # 4.图片文字处理 # 设置字体 fpygame.font.SysFont(华文行楷,50) f1pygame.font.SysFont(华文行楷,20) # 设置结束背景和彩蛋图片 end_photopygame.image.load(imge/snake_end.png) color_eggpygame.image.load(imge/蛇.png) # 扩大 end_photopygame.transform.scale(end_photo,(1280,720)) # 缩小 color_eggpygame.transform.scale(color_egg,(500,400)) # 6.蛇饲料的单个格子大小和初始位置 food_size10 food_xround(random.randint(20,1200)/10.0)*10.0 food_yround(random.randint(20,700)/10.0)*10.0 # 8.蛇的位置坐标和大小 snake_size10 snake_x100 snake_y200 # 9.蛇的后期大小,初始长度方便后期判断是否吃了蛇饲料 snake_body[[snake_x,snake_y]] snake_length1 # 10.蛇的行进方向 direction_x0 direction_y0 # 5建立程序循环 game_overFalse score0 a0 add5 while True: # 根据游戏状态不停绘制相应的游戏背景 if not game_over: # fill作用填充颜色 table.fill(black_color) else: # blit作用将图片文字绘制到指定的位置 table.blit(end_photo,(0,0)) # 事件设置 for event in pygame.event.get():#获得所有事件 # 退出条件 if event.typepygame.QUIT: pygame.quit()# 关闭所有窗口和功能 sys.exit()#退出程序 # 获取键盘上的操作 if event.typepygame.KEYDOWN: if event.keypygame.K_LEFT: direction_x -add direction_y 0 if event.key pygame.K_RIGHT: direction_x add direction_y 0 if event.key pygame.K_UP: direction_x 0 direction_y -add if event.key pygame.K_DOWN: direction_x 0 direction_y add # 14.蛇不管吃没吃到蛇饲料一旦游戏开始贪吃蛇就不停的移动开始计分 if not game_over: snake_xdirection_x snake_ydirection_y textf.render(f游戏运行中目前分数{score},True,font_color)# 当游戏运行时创建如果删除则不会创建就找不到正在运行时需要的对应text pygame.draw.rect(table, snake_color, (1100,680, snake_size, snake_size)) pygame.draw.rect(table, food_color, (1200,680, food_size, food_size)) text1f1.render(贪吃蛇,True,font_color) text2f1.render(:蛇饲料,True,font_color) table.blit(text1,(1105,680)) table.blit(text2,(1205,680)) # 15.当彩蛋满足条件时就会弹出来 if score % 100 0 and score ! 0 and a 1: table.blit(color_egg,(300,300)) time.sleep(1/10) a1 if a6: a0 # 7.不停的绘制蛇和蛇饲料 snake_head[snake_x,snake_y] snake_body.append(snake_head) # pygame.draw.rect(绘制到哪里,什么颜色,x坐标,y坐标,宽,高))画贪吃蛇 画矩形 for x,y in snake_body: pygame.draw.rect(table,snake_color,(x,y,snake_size,snake_size)) pygame.draw.rect(table,food_color,(food_x,food_y,food_size,food_size)) # 11.判断蛇是否吃到蛇饲料 if abs(snake_x-food_x)snake_size and abs(snake_y-food_y)snake_size: # 吃到了 food_x round(random.randint(20, 1200) / 10.0) * 10.0 food_y round(random.randint(20, 700) / 10.0) * 10.0 # 吃到蛇饲料的标记1 snake_length1 # 计分 score10 a1 # 16.加速条件判断 if score % 100 0 and score ! 0: add 2 # 如果蛇吃到食物就会变长反之则剪掉前一步 if len(snake_body) snake_length: del snake_body[0] # 12.判断是否出界 if snake_x0 or snake_x1280 or snake_y0 or snake_y720: game_overTrue text f.render(游戏结束祝大家蛇年快乐,True,font_color) # 13.判断是否吃到自己 for x,y in snake_body[:-1]: if snake_xx and snake_yy: game_overTrue text f.render(游戏结束祝大家蛇年快乐, True, font_color) table.blit(text, (550, 50)) time.sleep(1 / 20) # 不断刷新界面 pygame.display.update()完