文章目录
前言
初次学习pygame,可能存在不足,请谅解。
一、Pygame知识储备
1、窗口标题和图标设置
screen=pygame.display.set_mode(size)
:设计窗口,size为窗口大小(height,width)
pygame.display.set_caption("贪吃蛇小游戏")
:窗口名字
icon=pygame.image.load("snake.jpg")
:加载图片
pygame.display.set_icon(icon)
:设置图标
2、文字设计
首先需要调出字体
f1 = pygame.freetype.Font('C:\Windows\Fonts\simkai.ttf', size=50)
:里面的路径是我们电脑内自带的路径,大家可以自行查询其他的字体,后缀不一定一样,有两种。
f1.render_to(screen,[250,150],"游戏暂停",fgcolor=BLACK,bgcolor=None,size=50)
:文字增强,属性:screen是窗口图层,也就是我们设计窗口赋给的那个;位置;字体颜色;背景色;大小。
3、事件监听
pygame的事件都在一个列表pygame.event.get()
里面,通过循环找出是哪个事件发生了。从队列中获取事件
event.type:
事件类型
for event in pygame.event.get():
if event.type == pygame.QUIT: # 点击了退出
sys.exit() # 退出
下面是常用事件集:
下面是按键的常量名称
4、绘图
画矩形,属性包含:绘图层,颜色,左上角,高度,宽度
pygame.draw.rect(screen, BLUE, (food_point[0], food_point[1], 10, 10))
当然也可以画其他的图形,大家可以自行学习关于pygame的画图操作。
二、设计思路
我们需要设计出的东西有:蛇的身体,食物,分数显示位置
可执行的操作有:
1、生成食物,限定在窗口内部生成,必须显示出来
2、按上下左右键使蛇的移动方向发生变化,首先从蛇头开始,陆续跟进。
3、当我们按下空格键时,游戏暂停,蛇不发生移动,屏幕上显示 “ 游戏暂停 ” 字样,再次按空格继续进行游戏。
4、当蛇触碰到食物时,食物被吃掉消失,转化为蛇的尾部,同时产生新的食物
5、当蛇撞到窗口的边缘时,视为死亡,游戏结束
三、设计流程
1、引入库
代码如下:
import pygame
import sys
import random
import pygame.freetype
pygame
:游戏模块
sys
:设计退出游戏
random
:生成随机位置,后续用来产生食物的位置
pygame.freetype
:调用系统的字体,用来显示文字
2、设计窗口
代码如下:
pygame.init()#初始化init()及设置
size=width,height=700,400
speed=1
black=0,0,0
screen=pygame.display.set_mode(size)#窗口大小
pygame.display.set_caption("贪吃蛇小游戏")#窗口名字
icon=pygame.image.load("snake.jpg")
pygame.display.set_icon(icon)
fps=10
fclock=pygame.time.Clock()#创建一个Clock对象用于操作时间
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT: # 点击了退出
sys.exit()
pygame.display.update() # 对显示窗口进行更新,默认窗口全部重绘
fclock.tick(fps) # 窗口刷新速度,每秒300次
这些代码设计出了简单的窗口,最后的while循环是避免窗口一闪而过,无限重绘窗口里面的for循环是在所有的事件列表中判断是否有事件发生了,当我们点了窗口右上角的叉号就是上面代码里面的pygame.QUIT
,就会让系统退出游戏。
其他的知识在上面的pygame知识里面有了简单的讲解,如果不是很清楚可以去专门搜一下学习。
3、设计游戏初始状态
direct = 'up'
:蛇的初始移动方向
direct = 'up'#初始移动方向
#几个需要的颜色的调出
RED=pygame.Color("red")
BLACK=pygame.Color("black")
BLUE=pygame.Color("blue")
MOCCASIN=pygame.Color("moccasin")
screen.fill(MOCCASIN)
screen.fill(MOCCASIN)
:窗口的填充颜色,作为游戏的背景色。
下面的food
函数是设计食物的产生,使用随机数,函数返回一个列表,两个元素组成一个位置。
控制位置产生在10的倍数的位置上,调整蛇的移动距离,我们要保证蛇头的位置可以和食物的位置重合,用来判断贪吃蛇是否吃了食物。
def food():
food_x=random.randint(0,width/10-2)*10
food_y=random.randint(0,height/10-1)*10
food_point=[food_x,food_y]
return food_point
eat
函数是用来判断蛇头位置是否和食物的位置重合,同时蛇要移动一次。
蛇的移动我们采用的是头部向当前移动方向增加一格,尾部删除一格,实现视觉上蛇的移动。
当蛇吃了食物的时候增加的是尾部,相互抵消以后就是不删除尾部,但头部还是要增加。同时还要调用一次食物的产生函数,生成新的食物。
我们通过insert
在蛇的身体列表的第一个位置添加新的蛇头。
函数的返回值是蛇的身体列表和食物的位置,组成的是一个元组,通过重新赋值进行分离。
def eat(food_point,head_point,direction):
if food_point[0]==head_point[0] and food_point[1]==head_point[1]:
food_point = food()
a.insert(0, [head_point[0] + direction[0], head_point[1] + direction[1]])
else:
a.remove(a[-1])
a.insert(0,[head_point[0]+direction[0],head_point[1]+direction[1]])
return a,food_point
游戏结束函数,输出一个“GameOver!”后关闭游戏。
def gameover():
print("GameOver!")
sys.exit() # 退出
移动方向和对应移动方向的坐标变化值
directs=['left','right','up','down']
direct_step=[[-10,0],[10,0],[0,-10],[0,10]]
4、游戏的循环
pygame是基于事件驱动的,也就是说如果没有任何事件,游戏会停下等待用户操作(事件),所以游戏里首先要有一个事件循环,不停检测用户的事件,否则程序会直接结束。
只有当游戏输了或者点了结束游戏的按钮时才会结束游戏,否则就无限进行下去,直至达到输的条件。
while True:
实现游戏的无限循环
while do_not:
for event in pygame.event.get():
if event.type == pygame.QUIT: # 点击了退出
sys.exit() # 退出
pygame.display.update() # 对显示窗口进行更新,默认窗口全部重绘
fclock.tick(fps) # 窗口刷新速度,每秒300次
5、改变方向
按键动作分为按下和释放
event.type == pygame.KEYDOWN
:选取按下时的键,进而再判断是哪一个键
改变方向我们需要设计不能反向转头,也就是是说当前向左移动,那么不能改变为向右移动,以此类推。
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
do_not = False
if event.key == pygame.K_LEFT and direct != "right":
direct = "left"
elif event.key == pygame.K_RIGHT and direct != "left":
direct = "right"
elif event.key == pygame.K_UP and direct != "down":
direct = "up"
elif event.key == pygame.K_DOWN and direct != "up":
direct = "down"
elif event.key == pygame.K_ESCAPE:
sys.exit()
6、移动
调用eat
函数实现移动和吃食物的判定,输入对应参数,获取输出,更新对应的参数,蛇的身体和食物坐标,供下一次使用。
重绘蛇的身体和食物,实现视觉上的移动。
direct_index=directs.index(direct)
screen.fill(MOCCASIN)
x = eat(food_point, a[0], direct_step[direct_index])
a, food_point = x[0], x[1]
for i in a:
pygame.draw.rect(screen, RED, (i[0], i[1], 10, 10))
pygame.draw.rect(screen, BLUE, (food_point[0], food_point[1], 10, 10))
7、文字显示和边界判定
调用render_to
函数将蛇的长度显示在屏幕的固定位置。
边界判定选取蛇的头部坐标和窗口的边界对比,当超出边界就判定为输,调用gameover()
函数。
f1.render_to(screen,[630,170],str(len(a)),fgcolor=BLACK,bgcolor=None,size=50)
if a[0][0] > width or a[0][0] < 0: # 判断是否超出边界
gameover()
elif a[0][1] > height or a[0][1] < 0:
gameover()
8、游戏的暂停设计
通过双重while实现游戏的暂停和继续
我们需要借助do_not
来进行切换,我们将暂停按钮绑定为空格键,那么当检测到我们下了空格键时,将do_not
的值改变即可切换游戏的状态
do_not=True
while True:
while do_not:
#游戏进行的设计......
pygame.display.update() # 对显示窗口进行更新,默认窗口全部重绘
fclock.tick(fps) # 窗口刷新速度,每秒300次
while not do_not:
#游戏暂停的设计......
pygame.display.update() # 对显示窗口进行更新,默认窗口全部重绘
fclock.tick(fps) # 窗口刷新速度,每秒300次
通过以下代码我们就可以实现两种状态的切换。
do_not=True
while True:
while do_not:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
do_not = False
#游戏进行的代码设计
pygame.display.update() # 对显示窗口进行更新,默认窗口全部重绘
fclock.tick(fps) # 窗口刷新速度,每秒300次
while not do_not:
screen.fill(MOCCASIN)
for event in pygame.event.get():
if event.type == pygame.QUIT: # 点击了退出
sys.exit() # 退出
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
do_not = True
#游戏暂停的设计
pygame.display.update() # 对显示窗口进行更新,默认窗口全部重绘
fclock.tick(fps) # 窗口刷新速度,每秒300次
四、完整代码
import pygame
import sys
import random
import pygame.freetype
pygame.init() #初始化init()及设置
size=width,height=700,400 #窗口的大小
black=0,0,0
screen=pygame.display.set_mode(size)#窗口展示
pygame.display.set_caption("贪吃蛇小游戏")#窗口名字
icon=pygame.image.load("snake.jpg")#加载图片
pygame.display.set_icon(icon)#设置图标
RED=pygame.Color("red")#调出颜色
BLACK=pygame.Color("black")
BLUE=pygame.Color("blue")
MOCCASIN=pygame.Color("moccasin")
screen.fill(MOCCASIN)#窗口颜色填充
a=[[300,300],[300,310],[300,320]]#贪吃蛇的初始身体
fps=10#设置刷新的速度,每秒钟的次数
fclock=pygame.time.Clock()#创建一个Clock对象用于操作时间
f1 = pygame.freetype.Font('C:\Windows\Fonts\simkai.ttf', size=50)#调出字体,每个电脑应该是这个路径下,可以去C盘查询其他的字体
direct = 'up'#初始方向
def food():
food_x=random.randint(0,width/10-2)*10
food_y=random.randint(0,height/10-1)*10
food_point=[food_x,food_y]
return food_point
def eat(food_point,head_point,direction):
if food_point[0]==head_point[0] and food_point[1]==head_point[1]:#吃掉食物
food_point = food()#新的食物
a.insert(0, [head_point[0] + direction[0], head_point[1] + direction[1]])#头部移动,无尾部删除操作
else:#没有吃掉食物
a.remove(a[-1])#删除尾部
a.insert(0#头部移动[head_point[0]+direction[0],head_point[1]+direction[1]])
return a,food_point#输出贪吃蛇的身体和食物
def gameover():
print("GameOver!")
sys.exit() # 退出
food_point=food()#第一次调出食物
do_not=True
directs=['left','right','up','down']#四个方向
direct_step=[[-10,0],[10,0],[0,-10],[0,10]]#向四个方向移动的坐标变化
while True:
while do_not:#游戏进行
for event in pygame.event.get():
if event.type == pygame.QUIT: # 点击了退出
sys.exit() # 退出
elif event.type == pygame.KEYDOWN:#按下键盘
if event.key == pygame.K_SPACE:#如果是空格键,可以去网上搜其他的按键对应的名字
do_not = False#跳出当前循环
if event.key == pygame.K_LEFT and direct != "right":#当按键是向左,但当前方向不是向右时
direct = "left"#改变方向
elif event.key == pygame.K_RIGHT and direct != "left":
direct = "right"
elif event.key == pygame.K_UP and direct != "down":
direct = "up"
elif event.key == pygame.K_DOWN and direct != "up":
direct = "down"
elif event.key == pygame.K_ESCAPE:
sys.exit()
direct_index=directs.index(direct)#找到方向的位置
screen.fill(MOCCASIN)
x = eat(food_point, a[0], direct_step[direct_index])#里面最后一个参数时找到索引位置对应的坐标变化列表
a, food_point = x[0], x[1]#更新数据
for i in a:#绘制新的蛇和食物
pygame.draw.rect(screen, RED, (i[0], i[1], 10, 10))
pygame.draw.rect(screen, BLUE, (food_point[0], food_point[1], 10, 10))
f1.render_to(screen,[630,170],str(len(a)),fgcolor=BLACK,bgcolor=None,size=50)#添加一个蛇的当前长度在窗口内
if a[0][0] > width or a[0][0] < 0: # 判断是否超出边界
gameover()
elif a[0][1] > height or a[0][1] < 0:
gameover()
pygame.display.update() # 对显示窗口进行更新,默认窗口全部重绘
fclock.tick(fps) # 窗口刷新速度,每秒300次
while not do_not:#当游戏暂停时进行
screen.fill(MOCCASIN)
for event in pygame.event.get():#暂停时也可以退出,所以仍需要检测是否点击了退出
if event.type == pygame.QUIT: # 点击了退出
sys.exit() # 退出
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:#再次点击空格键,更改do_not的值切换过去
do_not = True
f1.render_to(screen,[250,150],"游戏暂停",fgcolor=BLACK,bgcolor=None,size=50)#在屏幕中央展示“游戏暂停”文字
pygame.display.update() # 对显示窗口进行更新,默认窗口全部重绘
fclock.tick(fps) # 窗口刷新速度,每秒300次
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210313163614167.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzkzMjgz,size_16,color_FFFFFF,t_70)
总结
刚开始学习pygame,简单的实现贪吃蛇游戏,代码只实现了一部分操作,游戏玩起来难度较小,我们也可以添加更多的操作如:
- 食物不能产生在身体内部
- 自己不能碰到自己的身体,否则也算输
- 将蛇进行优化使得易于辨认蛇头和身体,食物也可以优化
- 将显示身体的长度更改为得分
- 我的颜色选取表随意大家可以更改为更为美观的颜色,色板可以搜到,也可以在我的五子棋文章中找到,也可以使用RGB自己进行调色。
欢迎大家交流各自的意见,一起学习。