Sprite(精灵)是游戏中一个非常重要的概念。在游戏开发中,Sprite指的是一个可以移动、旋转或变换的二维图像,它负责管理游戏中的图像元素,使得开发者可以轻松地在游戏中创建各种动态效果和角色。pygame.sprite
模块提供了Sprite
类和Group
类,两者关系密切,一般同时出现。Group
其实就是Sprite
的容器,可以让我们更加方便的管理各个Sprite
对象。本节会详细介绍下这两个类。
项目代码下载地址: https://github.com/la-vie-est-belle/pygame_codes
8.1 Sprite
我们先来看下Sprite
类的常见属性和函数。
image
image
属性表示当前Sprite
精灵显示的图像,该属性的值是Surface
类型。
rect
rect
属性表示当前Sprite
精灵所在的矩形区域,该属性的值是Rect
类型。
注:当自定义类继承
Sprite
类时,我们必须让自定义类拥有image
和rect
实例属性,属性名称也不能修改。请看下方代码片段。
class MySprite(pygame.sprite.Sprite):
def __init__(self):
super(MySprite, self).__init__()
self.image = pygame.image.load('xxx.png')
self.rect = self.image.get_rect()
update()
继承Sprite
类后,我们可以重写这个函数,把Sprite
对象的状态更新操作都放在这里。
注:
Group
类也有个update()
函数,当某个Group
对象调用了自己的update()
函数时,就会触发所有被添加进来的Sprite
对象的update()
函数。
add(*groups)
将当前Spite
对象添加到指定的Group
对象中。一个Sprite
对象可以同时被添加到多个Group
对象中。
remove(*groups)
从指定的Group
对象中删除当前Spite
对象。
kill()
把当前Spite
对象从所有的Group
对象中删除。
alive()
判断当前Spite
对象是否有被添加到任何一个Group
对象中,有的话就返回True
,否则返回False
。
groups()
返回一个添加了当前Spite
对象的Group
对象列表。
示例代码8-1演示了Sprite
类的用法。
import sys
import pygame
class Dino(pygame.sprite.Sprite): # 1
def __init__(self):
super(Dino, self).__init__()
self.image = pygame.image.load('dino_start.png').convert_alpha()
self.rect = self.image.get_rect(topleft=(80, 450))
self.speed = 1
def draw(self, surface):
surface.blit(self.image, self.rect)
def update(self):
self.rect.x += self.speed
if self.rect.right >= 1100 or self.rect.left <= 0:
self.speed = -self.speed
self.image = pygame.transform.flip(self.image, True, False)
def main():
pygame.init()
clock = pygame.time.Clock() # 2
screen = pygame.display.set_mode((1100, 600))
pygame.display.set_caption('Dino Runner')
icon = pygame.image.load('icon.png')
pygame.display.set_icon(icon)
land = pygame.image.load('land.png').convert_alpha()
land_rect = land.get_rect()
land_rect.y = 520
dino = Dino() # 3
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill((255, 255, 255))
screen.blit(land, land_rect)
dino.draw(screen) # 4
dino.update()
pygame.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()
运行结果如下:
代码解释如下:
#1 定义一个Dino
类,继承Sprite
类,然后指定了必要的image
属性和rect
属性。speed
属性表示小恐龙的移动速度。draw()
函数是自定义的,在该函数中,我们让这个小恐龙显示在了传入的Surface
对象上。我们还重写了update()
函数,让小恐龙不断的向左或向右移动。pygame.transform.flip()
函数用来翻转图片,其参数解释如下。
flip(surface, flip_x, flip_y)
- surface: 要翻转的
Surface
对象。 - flip_x: bool类型,是否水平翻转。
- flip_y: bool类型,是否垂直翻转。
#2 通过创建一个Clock
对象,开发者可以精确地控制游戏循环的速度,确保游戏在不同计算机上以相同的速度运行,从而提供一致的游戏体验。Clock
对象的tick()
函数可以用来设置游戏帧率,tick(60)
就表示将游戏帧率设置为60帧。
#3 实例化一个Dino
对象。
#4 调用draw()
函数将小恐龙显示在屏幕上,调用update()
方法更新小恐龙的状态。
8.2 Group
现在我们来看下Group
类的常用函数。
sprites()
返回一个列表,其中包含所有被添加进来的Sprite
对象。
copy()
复制当前Group
对象,返回一个新的Group
对象,这个Group
对象包含所有的原始的Sprite
对象。
add(*sprites)
添加任意数量的Sprite
对象,已经添加过的无法再被添加。
remove(*sprites)
移除任意数量的Sprite
对象。
has(*sprites)
判断是否包含某个或某些Sprite
对象,是的话返回True
。
update()
会调用所有被添加进来的Sprite
对象的update()
函数。
draw(surface)
把所有Sprite
对象绘制到指定的Surface
对象上。该函数就是调用了Surface
对象的blit()
函数,并将Sprite
对象的image
和rect
属性用作参数。
示例代码8-2演示了Group
类的用法。
import sys
import pygame
class Dino(pygame.sprite.Sprite):
def __init__(self):
super(Dino, self).__init__()
self.image = pygame.image.load('dino_start.png').convert_alpha()
self.rect = self.image.get_rect(topleft=(80, 450))
self.speed = 1
def draw(self, surface):
surface.blit(self.image, self.rect)
def update(self):
self.rect.x += self.speed
if self.rect.right >= 1100 or self.rect.left <= 0:
self.speed = -self.speed
self.image = pygame.transform.flip(self.image, True, False)
class Bird(pygame.sprite.Sprite): # 1
def __init__(self, pos):
super(Bird, self).__init__()
self.image = pygame.image.load('bird.png').convert_alpha()
self.rect = self.image.get_rect()
self.rect.center = pos
self.speed = 1
def update(self):
self.rect.y += self.speed
if self.rect.top >= 300 or self.rect.bottom <= 0:
self.speed = -self.speed
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((1100, 600))
pygame.display.set_caption('Dino Runner')
icon = pygame.image.load('icon.png')
pygame.display.set_icon(icon)
land = pygame.image.load('land.png').convert_alpha()
land_rect = land.get_rect()
land_rect.y = 520
dino = Dino()
bird_group = pygame.sprite.Group() # 2
for i in range(5):
bird = Bird((80+i*220, i*10))
bird_group.add(bird)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill((255, 255, 255))
screen.blit(land, land_rect)
dino.draw(screen)
dino.update()
bird_group.draw(screen) # 3
bird_group.update()
pygame.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()
运行结果如下:
代码解释如下:
#1 定义一个Bird
类,继承Sprite
类。这个Bird
类在实例化的时候接收一个pos
参数,用来指定图片的中心位置。
#2 实例化一个Group
对象,并通过add()
函数将5个Bird
对象添加了进去。
#3 调用draw()
函数将所有Bird
对象绘制到屏幕上。调用update()
函数更新所有Bird
对象的状态。
8.3 小结
本节我们了解了Sprite
类和Group
类的用法以及两者之间的关系。使用这两个类,我们可以让游戏代码结构更加清晰易懂,方便修改。
如果你喜欢笔者的这部专栏,可以给笔者一些打赏,或者通过购买一些项目来支持作者,非常感谢!