Python的Pygame模块制作贪吃蛇游戏


前言

初次学习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自己进行调色。

欢迎大家交流各自的意见,一起学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值