如何在 Pygame 中复制 Sprite?

How do I make clones of a Sprite in Pygame?

我在 Pygame 和 Python 2.7 中将草添加到滚动平台中。问题是,到目前为止我只有一根草,我想要更多。基本上我希望有克隆。

我听说 类 可以克隆 Sprites,但我不确定 类 是如何工作的,甚至不知道如何克隆。我在网上找到的所有教程只会让我更加困惑。

这部分调用了grass_rotate函数,也使得grass_rect:

grass_rect = grass.get_rect(topleft = (grass_x, 480 - player_y + 460))
grass_rotate(screen, grass_rect, (grass_x, 480 - player_y + 460), grass_angle)

这是grass_rotate函数:

def grass_rotate(screen, grass_rect, topleft, grass_angle):
    rotated_grass = pygame.transform.rotate(grass, grass_angle)
    rotated_grass_rect = rotated_grass.get_rect(center = grass_rect.center)
    screen.blit(rotated_grass, rotated_grass_rect)

为了回答您的问题,要制作精灵的旋转“克隆”,我认为最好基于 pygame.sprite.Sprite 制作精灵对象,并带有位图旋转选项。

首先让我们制作一个非常简单的精灵:

class Grass( pygame.sprite.Sprite ):
    """ Creates a tuft of grass at (x,y) """
    def __init__( self, image, x, y ):
        pygame.sprite.Sprite.__init__(self)
        self.image    = image
        self.rect     = self.image.get_rect()
        self.rect.center = ( x, y )

因为这个是在sprite library的基础上自动得到(继承)pygame.sprite.Sprite的函数Grass.draw().

编辑:以上段落是错误的。精灵不继承 draw(),这只是 精灵组的一部分。有必要实现自己的 draw(),如果不使用 Sprite 组:

    def draw( self, surface ):
        surface.blit( self.image, self.rect )

所以要将其显示在屏幕上,我们可以这样做:

grass_image = pygame.image.load( 'grass_clump.png' ).convert_alpha()
my_grass1 = Grass( grass_image, 10, 10 )
my_grass2 = Grass( grass_image, 50, 40 )

...

my_grass1.draw( window )
my_grass2.draw( window )

...

但是我们想稍微随机化角度,所以每一丛草都不是那么平坦和规则。一种方法是在 Grass 精灵初始化 (Grass.__init__()) 时创建图像的旋转副本。 PyGame 已经有一个 rotozoom function 可以做到这一点。

所以我们基本上有相同的东西,除了现在我们添加了一个额外的可选参数用于旋转。我默认它是 None,没有参数,class 可以自由选择它自己的随机角度。

### Creates a sprite that is rotated slightly to the left or right
class Grass( pygame.sprite.Sprite ):
    """ Creates a tuft of grass at a jaunty angle """
    def __init__( self, image, x, y, rotation=None ):
        pygame.sprite.Sprite.__init__(self)
        if ( rotation == None ):                                       # choose random angle if none
            angle = random.randrange( -15, 16 )                        # choose random angle if none
        self.image    = pygame.transform.rotozoom( image, angle, 1 )   # rotate the image
        self.rect     = self.image.get_rect()
        self.rect.center = ( x, y )

现在我们需要把所有这些放在一起。 PyGame 和 Pygame 的 Sprite 库的一个非常有用的功能是 Sprite Groups。我不想在这里详细介绍,但本质上它允许您同时对一大堆精灵进行操作,从而使代码更容易。

所以现在我们需要很多草的克隆,所以我们只做了 50 个,然后添加到一个新组中:

### create lots of grass sprites, adding them to a group
grass_image = pygame.image.load( 'grass_clump_48.png' ).convert_alpha()
all_grass_sprites = pygame.sprite.Group()
for i in range( 50 ):
    new_x     = random.randrange( WINDOW_WIDTH )
    new_y     = random.randrange( WINDOW_HEIGHT )
    new_grass = Grass( grass_image, new_x, new_y )
    all_grass_sprites.add( new_grass )

要将它们绘制到 window,您可以使用 for() 语句遍历组中的所有精灵。但这不是必需的,因为精灵组已经可以为我们做到这一点:

all_grass_sprites.draw( window )   # draws all the grass sprites

太简单了吧?!

这丛草来自 Open Clip Art(Public 域许可。)

参考代码如下:

import pygame
import random

# Window size
WINDOW_WIDTH    = 400
WINDOW_HEIGHT   = 400
WINDOW_SURFACE  = pygame.HWSURFACE|pygame.DOUBLEBUF

GREEN = ( 130, 220,   0 )  # background colour

### Creates a sprite that is rotated slightly to the left or right
class Grass( pygame.sprite.Sprite ):
    """ Creates a tuft of grass at a jaunty angle """
    def __init__( self, image, x, y, rotation=None ):
        pygame.sprite.Sprite.__init__(self)
        if ( rotation == None ):                                       # choose random angle if none
            angle = random.randrange( -15, 14 )                        # choose random angle if none
        self.image    = pygame.transform.rotozoom( image, angle, 1 )   # rotate the image
        self.rect     = self.image.get_rect()
        self.rect.center = ( x, y )


### Initialisation
pygame.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("Grass Sprite Clones")

### create lots of grass sprites, adding them to a group
grass_image = pygame.image.load( 'grass_clump_48.png' ).convert_alpha()
all_grass_sprites = pygame.sprite.Group()
for i in range( 50 ):
    new_x     = random.randrange( WINDOW_WIDTH )
    new_y     = random.randrange( WINDOW_HEIGHT )
    new_grass = Grass( grass_image, new_x, new_y )
    all_grass_sprites.add( new_grass )

### Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.MOUSEBUTTONUP ):
            # On mouse-click
            pass

    # Update the window, but not more than 60fps
    window.fill( GREEN )
    all_grass_sprites.draw( window )   # draws all the grass sprites
    pygame.display.flip()

    # Clamp FPS
    clock.tick(60)

pygame.quit()