音效素材网提供各类素材,打造精品素材网站!

站内导航 站长工具 投稿中心 手机访问

音效素材

python实战之利用pygame实现贪吃蛇游戏(二)
日期:2021-09-08 14:16:30   来源:脚本之家

一、前言

在上一篇博客中,我们实现了基本的界面搭建,这次实现一下逻辑部分。

二、创建蛇

首先,先分析一下蛇的移动,不然我们一定会吃亏的(别问,问就是自己写了一堆无效代码)。

蛇的移动其实并没有想象中那样复杂,每一个模块都需要有一个方向,按照方向进行移动。
其实实际上就是一个出队的感觉,即每一个元素都取代上一个元素的位置,然后再按照贪吃蛇当前的方向,移动一下头节点即可。
snake.py:

""""🐍类"""
import pygame
class Snake():
    def __init__(self,snake_color,snake_head_color,x,y,lattice_wh):
        self.color = snake_color
        self.head_color = snake_head_color
        # 格子的左上角坐标
        self.pos = (x,y)
        self.lattice_wh = lattice_wh
        self.rect = pygame.Rect(x,y,self.lattice_wh,self.lattice_wh)

        self.move_distance = {
            0:(0,0),
            1:(0,-self.lattice_wh),
            2:(0, self.lattice_wh),
            3:(-self.lattice_wh,0),
            4:( self.lattice_wh,0)
        }
    
    def move(self,direction):
        self.rect.x += self.move_distance[direction][0]
        self.rect.y += self.move_distance[direction][1]
    
    def forecast(self,direction):
        return (self.rect.x+self.move_distance[direction][0],
        		self.rect.y+self.move_distance[direction][1])

创建蛇,需要给一个位置(坐标),同时也需要输入一个颜色。
这里为了区分头节点,我传入了两个颜色,一个为头节点的颜色,另一个为身子部分的颜色。
(其实颜色不需要给在这里,在update传入一个即可)

蛇的主要部分就是移动,这里我给出了两个方法:

1.移动方法,是针对头节点的移动
2.预测移动位置方法,是判断下一步蛇的移动的位置,看看是否会撞到自己/墙壁,或者吃到食物。

为了方便我们针对方向进行处理,我使用了哈希的方式(其实就是字典),将每一个方向移动一次(x,y)坐标变化量记录好。

【那个方向0,是最开始我们的蛇是固定的,所以我添加了一个(0,0)】

最开始,我们在main文件中创建一个snakes列表,来存储所有的蛇节点,并且添加了最开始的两个节点(头和第一部分的身子)

# 蛇头&1个蛇身
snakes = []
snakes.append(Snake(snake_color,snake_head_color,lattice_wh,24*lattice_wh,lattice_wh))
snakes.append(Snake(snake_color,snake_head_color,0,24*lattice_wh,lattice_wh))

效果:

在这里插入图片描述

(主要是左下角的两个方块,紫色为头,绿色为身子,我是写完了才写的博客)

三、创建食物

这部分,主要就是随机生成一个位置,然后保证这个位置不在蛇身上即可。
食物类:
传入颜色、渲染的界面、一个格子的宽度以及坐标
另外我还提供了一个绘制圆的方法(pos为坐标,radius为直径)
circle函数参数:界面screen,颜色,位置(元组形式),直径,线条宽度。
这里我们将线条设置为直径,就能绘制一个圆盘。(注意宽度一定要是int类型,需要强转)

"""食物类"""
import pygame
class Food():
    def __init__(self,food_color,screen,lattice_wh,x,y):
        self.screen = screen
        self.food_color = food_color
        self.lattice_wh = lattice_wh
        self.radius = lattice_wh/2
        self.x,self.y = x,y

    def draw(self):
        pos = (self.x+self.lattice_wh/2,self.y+self.lattice_wh/2)
        pygame.draw.circle(self.screen,self.food_color,pos,self.radius,int(self.radius))

fuc.py中,写了一个生成食物的函数:

def create_food(food_color,screen,lattice_wh,snakes):
    success = 0
    x,y = 0,0
    while not success:
        x,y = randint(0,24),randint(0,24)
        x *= lattice_wh
        y *= lattice_wh
        for i in snakes:
            if (x,y) != (i.rect.x,i.rect.y):
                success = 1
                break
    food = Food(food_color,screen,lattice_wh,x,y)
    return food

randint生成一个整数位置,乘上格子的宽度,我们就能得到一个格子的左上角坐标,看看是否在蛇身上,不在就可以生成了。

四、蛇的移动

之前只给出了方法,现在我们来实现一下。
蛇的移动就三种情况:

  • 撞到自己或者边界
  • 吃到食物
  • 正常移动

如果是第一种,直接结束游戏,第三中我们就按照上面说的,将身子向前移动一位,修改一下头节点即可。
但是第二种,涉及到了需要在snakes添加一个对象,我们就需要搞清楚添加的位置。

在即将碰到食物时,我们将食物位置添加到列表首项。

实现:
这里的game_stats为游戏种需要传递并需要被修改的项,整合成一个列表好看一点:
game_stats =[if_lose,direction,num,food]
游戏是否结束的状态变量、蛇头方向(1234:上下左右,0为静止)、吃到的食物个数、食物的实例

def going(snakes,snake_color,snake_head_color,lattice_wh,game_stats,food_color,screen):
    """蛇的移动和转向问题"""
    # 初始状态,不需要移动
    if not game_stats[1]:
        return
    # 预测位置
    (x,y) = snakes[0].forecast(game_stats[1])
    # 撞到边界
    if x == -lattice_wh or x == 25*lattice_wh or y == -lattice_wh or y == 25*lattice_wh:
        game_stats[0] = 0
        return
    # 吃到食物
    if (x,y) == (game_stats[3].x,game_stats[3].y):
        head = Snake(snake_color,snake_head_color,x,y,lattice_wh)
        snakes.insert(0,head)
        game_stats[2] += 1
        game_stats[3] = create_food(food_color,screen,lattice_wh,snakes)
        return
    # 撞到蛇身
    for i in snakes:
        if (x,y) == (i.rect.x,i.rect.y):
            game_stats[0] = 0
            return
    # 都没有,就正常移动
    for i in range(len(snakes)-1,0,-1):
        snakes[i].rect.x = snakes[i-1].rect.x
        snakes[i].rect.y = snakes[i-1].rect.y
    snakes[0].move(game_stats[1])

这里的正常移动,我们是否可以这样写?
snake[i] = snakes[i-1
这样是不行的,在python中,赋值是将地址赋值过去,所以实际上我们是将两个实例指向一个地址。
对于snakes[1],当我们指向snakes[0],然后修改snakes[0]之后,两者会合并为一个,而整个蛇身就会缺失一部分。

五、按键感应

对于蛇方向的控制,我们是通过上下左右四个按键实现的,所以我们还需要修改一下check_events。

先说明一下,这里我没有使用正常的if-elif对每一个方向进行判断,其实都一样的。

首先,蛇不能在向上的情况下按向下,所以是有一个方向冲突的,拿小本本记下来。

# 方向冲突
conflict = {
    pygame.K_RIGHT:4,
    pygame.K_LEFT :3,
    pygame.K_UP   :1,
    pygame.K_DOWN :2,
    0:0,	# 这个纯属凑数,问题不大
    1:2,
    2:1,
    3:4,
    4:3
}

事件检测:

def check_events(game_stats,conflict,snakes,snake_color,snake_head_color,
				 lattice_wh,food_color,screen):
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
        	# 按键匹配
            if event.key in conflict:
                ret = conflict[event.key]
                # 判断我们输入的方向和当前方向是否冲突,不冲突就可以修改,然后赋值
                if conflict[ret] != game_stats[1]:
                    game_stats[1] = ret
                    # 调用移动函数
                    going(snakes,snake_color,snake_head_color,
                    	  lattice_wh,game_stats,food_color,screen)
        elif event.type == pygame.QUIT:
            sys.exit()

(这部分,其实改变方向不使用going,也没什么问题)

六、整合部分

剩下的工作,就是将整体串起来。
换掉了之前的time.sleep,改成了设置帧率。

import pygame
from fuc import *
from snake import Snake
from time import sleep
from food import Food
# 基本属性
lattice_wh = 20 #长宽
snake_color = (84, 255, 159)
snake_head_color = (123, 104, 238)
food_color = (255, 64, 64)

# 绘制界面
pygame.init()
screen = pygame.display.set_mode((25*lattice_wh,25*lattice_wh))
pygame.display.set_caption('贪吃蛇')

# 设置帧率
FPS=10
level = 0.9     # 每吃掉一个,间隔时间缩短系数
FPSClock=pygame.time.Clock()

if_lose = 1
if_food = 1

# 蛇的方向
direction = 0
# 得分,吃一个一分
num = 0

# 蛇头&1个蛇身
snakes = []
snakes.append(Snake(snake_color,snake_head_color,lattice_wh,24*lattice_wh,lattice_wh))
snakes.append(Snake(snake_color,snake_head_color,0,24*lattice_wh,lattice_wh))

# 食物
food = create_food(food_color,screen,lattice_wh,snakes)

# 游戏状态打包
game_stats =[if_lose,direction,num,food]

# 方向冲突
conflict = {
    pygame.K_RIGHT:4,
    pygame.K_LEFT :3,
    pygame.K_UP   :1,
    pygame.K_DOWN :2,
    0:0,
    1:2,
    2:1,
    3:4,
    4:3
}

while game_stats[0]:
    update(screen,lattice_wh,snakes,game_stats)
    check_events(game_stats,conflict,snakes,snake_color,snake_head_color,
    			 lattice_wh,food_color,screen)
    going(snakes,snake_color,snake_head_color,lattice_wh,game_stats,food_color,screen)
    FPSClock.tick(FPS* level**num)

然后修改一下update函数:

def update(screen,lattice_wh,snakes,game_stats):
    """屏幕刷新"""
    # 背景颜色
    screen.fill((255,255,255))
    # 画蛇,需要先画,不然网格会被盖住
    pygame.draw.rect(screen,snakes[0].head_color,snakes[0].rect)
    for i in range(1,len(snakes)):
        pygame.draw.rect(screen,snakes[i].color,snakes[i].rect)
    # 绘制网格
    for i in range(25):
        pygame.draw.line(screen,(105, 105, 105),(0,lattice_wh*i),(500,lattice_wh*i))
    for i in range(25):
        pygame.draw.line(screen,(105, 105, 105),(lattice_wh*i,0),(lattice_wh*i,500))
    # 绘制食物
    game_stats[3].draw()
    pygame.display.flip()

七、结语

本来还想添加一些其他的部分,比如在死亡时候显示一下得分什么的,但是好象基本上都在这篇博客的弹窗显示部分写过了,那么我们这个就先结束吧,然后开新坑。

到此这篇关于python实战之利用pygame实现贪吃蛇游戏(二)的文章就介绍到这了,更多相关pygame实现贪吃蛇游戏内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

    您感兴趣的教程

    在docker中安装mysql详解

    本篇文章主要介绍了在docker中安装mysql详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编...

    详解 安装 docker mysql

    win10中文输入法仅在桌面显示怎么办?

    win10中文输入法仅在桌面显示怎么办?

    win10系统使用搜狗,QQ输入法只有在显示桌面的时候才出来,在使用其他程序输入框里面却只能输入字母数字,win10中...

    win10 中文输入法

    一分钟掌握linux系统目录结构

    这篇文章主要介绍了linux系统目录结构,通过结构图和多张表格了解linux系统目录结构,感兴趣的小伙伴们可以参考一...

    结构 目录 系统 linux

    PHP程序员玩转Linux系列 Linux和Windows安装

    这篇文章主要为大家详细介绍了PHP程序员玩转Linux系列文章,Linux和Windows安装nginx教程,具有一定的参考价值,感兴趣...

    玩转 程序员 安装 系列 PHP

    win10怎么安装杜比音效Doby V4.1 win10安装杜

    第四代杜比®家庭影院®技术包含了一整套协同工作的技术,让PC 发出清晰的环绕声同时第四代杜比家庭影院技术...

    win10杜比音效

    纯CSS实现iOS风格打开关闭选择框功能

    这篇文章主要介绍了纯CSS实现iOS风格打开关闭选择框,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作...

    css ios c

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的

    Win7给电脑C盘扩容的办法大家知道吗?当系统分区C盘空间不足时,就需要给它扩容了,如果不管,C盘没有足够的空间...

    Win7 C盘 扩容

    百度推广竞品词的投放策略

    SEM是基于关键词搜索的营销活动。作为推广人员,我们所做的工作,就是打理成千上万的关键词,关注它们的质量度...

    百度推广 竞品词

    Visual Studio Code(vscode) git的使用教程

    这篇文章主要介绍了详解Visual Studio Code(vscode) git的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...

    教程 Studio Visual Code git

    七牛云储存创始人分享七牛的创立故事与

    这篇文章主要介绍了七牛云储存创始人分享七牛的创立故事与对Go语言的应用,七牛选用Go语言这门新兴的编程语言进行...

    七牛 Go语言

    Win10预览版Mobile 10547即将发布 9月19日上午

    微软副总裁Gabriel Aul的Twitter透露了 Win10 Mobile预览版10536即将发布,他表示该版本已进入内部慢速版阶段,发布时间目...

    Win10 预览版

    HTML标签meta总结,HTML5 head meta 属性整理

    移动前端开发中添加一些webkit专属的HTML5头部标签,帮助浏览器更好解析HTML代码,更好地将移动web前端页面表现出来...

    移动端html5模拟长按事件的实现方法

    这篇文章主要介绍了移动端html5模拟长按事件的实现方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家...

    移动端 html5 长按

    HTML常用meta大全(推荐)

    这篇文章主要介绍了HTML常用meta大全(推荐),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    cdr怎么把图片转换成位图? cdr图片转换为位图的教程

    cdr怎么把图片转换成位图? cdr图片转换为

    cdr怎么把图片转换成位图?cdr中插入的图片想要转换成位图,该怎么转换呢?下面我们就来看看cdr图片转换为位图的...

    cdr 图片 位图

    win10系统怎么录屏?win10系统自带录屏详细教程

    win10系统怎么录屏?win10系统自带录屏详细

    当我们是使用win10系统的时候,想要录制电脑上的画面,这时候有人会想到下个第三方软件,其实可以用电脑上的自带...

    win10 系统自带录屏 详细教程

    + 更多教程 +
    ASP编程JSP编程PHP编程.NET编程python编程