pygame 的精灵使用
pygame.sprite.Sprite 是 pygame 中用来实现精灵的一个类,在使用时并不需要对它实例化,只需要继承它,然后按需写出自己的类,因此非常简单、使用。
1. 精灵
精灵可以被认为是一个个小图片(帧)序列(例如人物行走),它可以在屏幕上移动,并且可以与其他图形对象交互。精灵图像可以是用 pygame 绘制形状函数绘制的形状,也可以是图像文件。
2. Sprite 类的成员
pygame.sprite.Sprite 用来实现精灵类,Sprite 的数据成员和函数方法主要如下。
-
self.image
其负责显示什么图形。例如
self.image = pygame.Surface([x, y])
说明该精灵是一个 x * y 大小的矩形,self.image = pygame.image.load(filename)
说明该精灵显示 filename 这个图片文件。self.image.fill([color])
负责对 self.image 进行着色,例如:self.image = pygame.Surface([x, y]) self.image.fill((255, 0, 0)) # 对 x * y 大小的矩形填充红
-
self.rect
其负责在哪里显示。一般来说,先用
self.rect = self.image.get_rect()
来获取 image 的矩形区域,然后给 self.rect 设定显示的位置,一般用 self.rect.topleft 来确定左上角的位置,当然也可以 self.rect.topright、 self.rect.bottomleft 和 self.rect.bottomright 来确定其它几个角的位置。另外,self.rect.top 、self.rect.bottom 、self.rect.left 、self.rect.right 分别表示上、下、左、右。
-
self.update()
其负责使精灵行为生效。
-
Sprite.add()
添加精灵到 groups 中。
-
Sprite.remove()
从精灵组 groups 中删除。
-
Sprite.kill()
从精灵组 groups 中删除全部精灵。
-
Sprite.alive()
判断某个精灵是否属于精灵组 groups 。
3. 建立精灵
所有精灵在建立时都是从 pygame.sprite.Sprite 中继承的,建立精灵要设计自己的精灵类。
例——建立 Tank 精灵,代码如下:
import pygame
class Tank(pygame.sprite.Sprite):
def __init__(self, image, initial_position):
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.topleft = initial_position
if __name__ = '__main__':
pygame.init()
screen = pygame.display.set_mode((640, 480))
screen.fill((255, 255, 255))
filename = "../images/tank.png"
init_pos = (150, 100)
tank = Tank(filename, init_pos)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
screen.blit(tank.image, tank.rect)
pygame.display.update()
运行结果如下:
4. 建立精灵组
当程序中有大量实体的时候,操纵这些实体将会是一件相当麻烦的事,而精灵组可以作为一个实体精灵容器将这些精灵放在一起统一管理。
pygame 使用精灵组来管理精灵的绘制和更新,精灵组是一个简单的容器。
使用 pygame.sprite.Group()
可以创建一个精灵组:
group = pygame.sprite.Group()
group.add(sprite_one)
精灵组也有 update() 和 draw() 函数:
group.update()
group.draw()
pygame 还提供了精灵与精灵之间的冲突检测、精灵和组之间的冲突检测。
5. 精灵与精灵之间的碰撞检测
1. 两个精灵之间的矩形检测
在只有两个精灵的时候可以使用 pygame.sprite.collide_rect()
函数进行一对一的冲突检测。这个函数需要传递两个精灵,并且两个精灵都需要继承自 pygame.sprite.Sprite 。
这里举个例子:
sprite1 = Tank("sprite1.png", (150, 100)) # Tank 是上面3中例子创建的类。
sprite2 = Tank("sprite2.png", (120, 80))
result = pygame.sprite.collide_rect(sprite1, sprite2)
if result:
print("精灵碰撞了!")
2. 两个精灵之间的圆检测
矩形冲突检测并不适合所有形状的精灵,因此在 pygame 中还提供了圆形冲突检测。pygame.sprite.collide_circle()
函数是基于每个精灵的半径值来检测的,用户可以自己指定精灵半径,或者让函数计算精灵半径。
result = pygame.sprite.collide_circle(sprite1, sprite2)
if result:
print("精灵碰撞了!")
3. 两个精灵之间的像素遮罩检测
如果矩形检测和圆形检测都不能满足要求,pygame 还为用户提供了一个更加精确的检测——pygame.sprite.collide_mask()
。
这个函数接受精灵作为参数,返回值是一个 bool 变量。
if pygame.sprite.collide_mask(sprite1, sprite2):
print("精灵碰撞了!")
4. 精灵和精灵组之间的矩形冲突检测
在调用 pygame.sprite.spritecollide(sprite, sprite_group, bool)
函数的时候,一个组中所有的精灵都会逐个地对另外一个单个精灵进行冲突检测,发生冲突的精灵会作为一个列表返回。
这个函数的第1个参数是单个精灵,第2个参数是精灵组,第3个参数是一个 bool 值,最后这个参数起了很大的作用,当为 True 的时候会删除组中所有冲突的精灵,当为 False 的时候不会删除冲突的精灵。
list_collide = pygame.sprite.spritecollide(sprite, sprite_group, False)
另外,这个函数还有一个变体——pygame.sprite.spritecollideany()
,这个函数在判断精灵组和单个精灵冲突的时候会返回一个 bool 值。
5. 精灵组之间的矩形冲突检测
利用 pygame.sprite.groupcollide()
函数可以检测两个组之间的冲突,它返回一个字典(键值对)。