本章,你将学习如何使用 Pygame 中的精灵。

导航

上一章:监测游戏时间

文章目录

  • 导航
  • 精灵
  • Sprite
  • Group
  • 碰撞检测函数
  • 实例:弹球
    • 创建精灵
    • 使用精灵
    • 完整代码
  • 结语(很重要!!)

精灵

当游戏对象变得繁多的时候,把所有游戏对象的处理存放在一个个函数中,虽然是一种可行的方法,但是会使代码逻辑比较混乱,难以维护。这时,精灵(sprite) 应运而生。使用精灵,可以将游戏对象封装到一个个类当中,以将处理游戏对象的逻辑与主代码逻辑分离开,使代码架构更加清晰明了。

Pygame 中,通过pygame.sprite模块使用精灵。该模块定义了Sprite类(用于定义精灵)和Group类(用于管理精灵的容器)以及一些继承于这两个类的拓展类和检测精灵碰撞的函数。

下面将主要介绍SpriteGroup类,以及常用的检测碰撞的函数。

Sprite

pygame.sprite.Sprite通常作为可见游戏对象的基类。构造函数Sprite(*groups) -> Sprite接受任意数量的Group容器以添加到这些容器中。

继承它的子类需要为imagerect属性赋值。image属性是一个pygame.Surface对象,指定该游戏对象的图像。rect属性是一个pygame.Rect对象,用于指定该游戏对象的位置,也用于检测精灵碰撞而使用。

Sprite类中定义的方法如下表(详见官方文档):

方法定义 方法作用
update(*args, **kwargs) -> None 用于控制精灵行为的方法,通常子类需要重写该方法。当调用了Group.update方法时,组中的所有精灵都会被调用Sprite.update方法,如果在Group.update方法中传入了参数,参数也将被传入Sprite.update方法中。
add(*groups) -> None 任意数量的Group对象作为参数传递,精灵将被添加到尚未成为成员的组中。
remove(*groups) -> None 任意数量的Group对象作为参数传递,精灵将从它所在的组中移除。
kill() -> None 将精灵从所有包含它的组中移除,这并不会改变本身的状态,之后也可以继续使用该精灵。
alive() -> bool 判断此精灵是否属于1个或多个组。
groups() -> group_list 返回包含此精灵的Group对象的列表。

Group

pygame.sprite.Group类通常作为用于管理多个Sprite对象的容器。此类也可以被继承以创建有更具体行为的容器。构造函数Group(*sprites) -> Group接受任意数量的Sprite对象作为参数以添加到容器中。Group类还支持以下标准的 Python 操作:

  • in,判断是否包含了某个精灵。
  • len,获取组中的精灵总数。
  • bool,判断组中是否包含任何精灵。
  • iter,迭代组中所有的精灵。

Group类中定义的方法如下表(详见官方文档):

方法定义 方法作用
sprites() -> sprite_list 返回组中包含的所有精灵的列表。
copy() -> Group 创建该组的副本。
add(*sprites) -> None 向组中添加任意数量的精灵,只添加尚未成为改组成员的精灵。
remove(*sprites) -> None 从组中删除任意数量的精灵。只删除是该组成员的精灵。
has(*sprites) -> bool 判断组中是否包含给定的所有精灵。
update(*args, **kwargs) -> None 对组中所有的精灵调用Sprite.update方法,被传入Group.update方法的参数也将传入Sprite.update方法中。
draw(Surface) -> List[Rect] 将组中包含的所有精灵绘制到给定的图像上,使用每个精灵的image属性作为源图像,rect属性作为位置。Group并不保存精灵的顺序,所以绘制顺序是任意的。
clear(Surface_dest, background) -> None 在给定的图像上清除上次调用Group.draw方法所使用的精灵,通过在对应精灵的位置上进行填充来清除。参数background通常是一个Surface图像,要求尺寸与目标图像相同,但是也可以是一个回调函数,需要两个参数:目标图像和要清除的区域。
clear(Surface_dest, background) -> None 从组中移除所有的精灵。

碰撞检测函数

sprite模块中还定义了一些碰撞检测函数。以下内容将介绍常用的函数(详见官方文档)。

spritecollide(sprite, group, dokill, collided = None) -> Sprite_list:返回一个组中与一个精灵相交的所有的精灵的列表。布尔参数dokill指定是否将所有将组中所有碰撞的精灵删除。可选的参数collided是一个回调函数,用于计算两个精灵是否碰撞,它应该把两个精灵作为参数,并返回一个布尔值,表明是否相撞。如果没有传递collided参数,则所有精灵都要求有rect属性,用于计算碰撞。collided可以传入的 Pygame 内置函数有:collide_rectcollide_rect_ratiocollide_circlecollide_circle_ratiocollide_mask

collide_rect(left, right) -> bool:使用pygame.Rect.collide_rect方法检测两个精灵之间的碰撞,要求两个精灵都有rect属性。

collide_rect_ratio(ratio) -> collided_callable:一个可调用的类,collide_rect函数的可缩放版本,初始化时传入一个比率。

collide_circle(left, right) -> bool:通过检测以精灵为中心的两个圆是否重叠来检测碰撞。如果精灵有radius属性,将被用来创建圆,否则,将创建一个足够大的圆完全包围精灵的rect属性。两个精灵必须有rect属性和可选的radius属性。

collide_circle_ratio(ratio) -> collided_callable:一个可调用的类,collide_circle函数的可缩放版本,初始化时传入一个比率。

groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict:参数与spritecollide函数类似,找到所有在两组之间发生碰撞的精灵。group1中的所有精灵将添加为返回字典的键,而每个键对应的值就是group2中与该精灵发生碰撞的精灵列表。

spritecollideany(sprite, group, collided = None) -> Sprite | None:简单测试精灵是否与组中任何一个精灵相撞,如果有碰撞,将返回组中的一个精灵,否则,返回None

实例:弹球

本实例将利用Sprite创建一个弹球引用程序。

请创建一个新的文件,命名为ball.py,并添加以下代码:

import sysimport pygameclass BallGame:def __init__(self) -> None:self.screen = pygame.display.set_mode((600, 600))pygame.display.set_caption('Ball')def run(self):while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()pygame.display.flip()if __name__ == '__main__':game = BallGame()game.run()

创建精灵

我们需要创建一个继承于Sprite类的精灵类Ball,在BallGame之前添加如下代码:

class Ball(pygame.sprite.Sprite):def __init__(self, screen_rect) -> None:super().__init__()self.image = pygame.Surface((20, 20))pygame.draw.circle(self.image, (255, 255, 255), (10, 10), 10)self.screen_rect = screen_rectself.rect = self.image.get_rect()self.rect.center = self.screen_rect.centerself.vel = (2, 1)def update(self):self.rect.x += self.vel[0]self.rect.y += self.vel[1]if self.rect.left < 0 or self.rect.right > self.screen_rect.width:self.vel = (-self.vel[0], self.vel[1])if self.rect.top < 0 or self.rect.bottom > self.screen_rect.height:self.vel = (self.vel[0], -self.vel[1])

上述代码中,Ball类继承于Sprite类,以定义一个精灵,并且使用pygame.draw.circle函数在image上绘制了一个白色的圆,同时将rect定位到屏幕矩形的中心。

update方法中,更新了rect的位置,并防止球超出屏幕范围。

使用精灵

更改BallGame类的方法,代码如下:

class BallGame:def __init__(self) -> None:self.screen = pygame.display.set_mode((600, 600))pygame.display.set_caption('Ball')self.ball = Ball(self.screen.get_rect())def run(self):while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()self.screen.fill((0, 0, 0))self.ball.update()self.screen.blit(self.ball.image, self.ball.rect)pygame.display.flip()

这里并没有使用Group来组织精灵,是因为我们只使用了一个精灵,无需使用它。

完整代码

import sysimport pygameclass Ball(pygame.sprite.Sprite):def __init__(self, screen_rect) -> None:super().__init__()self.image = pygame.Surface((20, 20))pygame.draw.circle(self.image, (255, 255, 255), (10, 10), 10)self.screen_rect = screen_rectself.rect = self.image.get_rect()self.rect.center = self.screen_rect.centerself.vel = (2, 1)def update(self):self.rect.x += self.vel[0]self.rect.y += self.vel[1]if self.rect.left < 0 or self.rect.right > self.screen_rect.width:self.vel = (-self.vel[0], self.vel[1])if self.rect.top < 0 or self.rect.bottom > self.screen_rect.height:self.vel = (self.vel[0], -self.vel[1])class BallGame:def __init__(self) -> None:self.screen = pygame.display.set_mode((600, 600))pygame.display.set_caption('Ball')self.ball = Ball(self.screen.get_rect())def run(self):while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()self.screen.fill((0, 0, 0))self.ball.update()self.screen.blit(self.ball.image, self.ball.rect)pygame.display.flip()if __name__ == '__main__':game = BallGame()game.run()

代码运行截图:

结语(很重要!!)

至此,Pygame 教程已经结束啦

Pygame 教程(6):使用精灵相关推荐

  1. python3.8安装pygame_Python3.8安装Pygame教程步骤详解

    注:因为最近想用一下Python做一些简单小游戏的开发作为项目练手之用,而Pygame模块里面提供了大量的有用的方法和属性.今天我们就在之前安装过PyCharm的基础上,安装Pygame,下面是安装的 ...

  2. mac python3.8上怎么安装pygame 第三方库_Python3.8安装Pygame Python3.8安装Pygame教程步骤详解...

    想了解Python3.8安装Pygame教程步骤详解的相关内容吗,孤傲小二~阿沐在本文为您仔细讲解Python3.8安装Pygame的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:Pyth ...

  3. pygame教程实例(四)小球弹跳(事件)

    上一篇:pygame教程实例(三)游戏事件 下一篇:pygame教程实例(五)物理引擎pymunk 本教程使用python3 在pygame教程实例(一)小球弹跳中我们写了一个小球在重力的作用下反复弹 ...

  4. pygame 教程翻译---- LGPL许可

    pygame 教程翻译---- LGPL许可 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 版权所有© 1991,1999自 ...

  5. pygame教程实例(三)游戏事件

    上一篇:pygame教程实例(二)模拟三体 下一篇:pygame教程实例(四)小球弹跳(事件) 本教程使用python3 在pygame教程实例(一)小球弹跳中我们写了一个小球在重力的作用下反复弹跳. ...

  6. python3.8.2安装pygame教程_Python3.8安装Pygame教程步骤详解

    注:因为最近想用一下Python做一些简单小游戏的开发作为项目练手之用,而Pygame模块里面提供了大量的有用的方法和属性.今天我们就在之前安装过PyCharm的基础上,安装Pygame,下面是安装的 ...

  7. pygame教程实例(八)不用3D引擎也可以写3D画面

    上一篇:pygame教程实例(七)python实现贪吃蛇自动寻路 目录:pygame游戏教程目录 效果图: 代码参考自:https://github.com/Apress/beg-python-gam ...

  8. pygame教程实例(五)物理引擎pymunk

    上一篇:pygame教程实例(四)小球弹跳(事件) 下一篇:pygame教程实例(六)你从来没玩过的俄罗斯方块 本教程使用python3 在前几个教程中,我们模拟了小球和星球的运动. 但是,在游戏中我 ...

  9. pygame教程----Sprite精灵模块介绍

    Sprite精灵模块介绍 来历 "精灵"这个词是从老式电脑和游戏机中流传下来的.这些较老的盒子无法快速绘制和删除普通图像,无法作为游戏使用.这些机器有特殊的硬件来处理需要快速动画的 ...

最新文章

  1. Go 学习笔记(40)— Go 标准库之 log
  2. ffmpeg加入libass
  3. Python中for else注意事项
  4. .NET开发框架(五)-IIS上部署ASP.NET Core项目教程
  5. 《20天吃透Pytorch》Pytorch自动微分机制学习
  6. 明知 | TypeScript 结合 egg.js 基本使用
  7. 【方案分享】2021美图美学营销方案.pdf(附下载链接)
  8. 设计模式再学习之简单工厂模式
  9. WordPress 在function.php 文件中方法中the_XXX方法失效
  10. Python:pip下载库后导入Pycharm的方法
  11. 【版本控制】如何从github 上删除项目
  12. Java常用到的快捷键
  13. python通信系统仿真_Python与V-REP联合仿真
  14. 国内最火的10款Java开源项目,都是国人开发,CMS居多
  15. AMD GPU任务调度(2)—— 内核态分析
  16. excel shared formula处理
  17. 临沂大学 计算机学院,2018临沂大学首届计算机文化节组织动员大会
  18. MIPS架构对比ARM架构
  19. python错误:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb5 in position 0: invalid start byte
  20. 单纤双向BIDI光模块的介绍

热门文章

  1. DotNetCore.Cap分布式事务实现最终一致性
  2. Android之PopupMenu
  3. 【FXCG】关于三重滤网
  4. wireshark过滤网段和域名
  5. 关于星际争霸2的发现
  6. 线程的概念函数EnterCriticalSection和LeaveCriticalSection的用法
  7. pythonocc_曲面生成
  8. 教学思路SQL之入门习题《学生成绩》 五、使用视图完成多表查询
  9. 纯前端将Html导出word
  10. 摩根大通扩大区块链系统的使用