简体   繁体   中英

What is the purpose of the pygame sprite framework?

I am in the process of learning Pygame, and time and time again I have stumbled upon tutorials using the sprite framework in Pygame. It isn't apparent to me why they have chosen to use this framework as opposed to other methods; is using a sprite framework the only available method for movable objects, or is there another way? What exactly is the sprite framework and what makes it desirable? In one tutorial instance, I even heard the guy say "It just makes this whole thing a lot easier." So what qualities of the sprite framework make it superior to other methods (if they even exist)?

Thanks for reading :-)

While PyGame is a library that has lots of methods for drawing graphics, bitmaps, lines and shapes. One of the major game use-cases is drawing and moving bitmap images. These sorts of operations cover a large range of games, particularly early "arcade" games.

Typically a game is composed of movable & static parts, and eventually tests need to be made for collision. Things like walls, platforms, monsters, bullets, trees etc., at some time, need to collide with the player as part of the game mechanics.

Bitmap collision is superficially, quite easy. Just test if the rectangle occupied by the player bitmap intersects with the rectangles occupied by the collide-able rectangles. But what if your bitmap is not square, and the area around corners or some spiky-part is "not there". How do you collide then? (The code has to do a per-pixel test against the other bitmap).

The PyGame Sprite class already has a lot of the necessary infrastructure written for creating bitmap sprites, moving them, and testing for collisions. Furthermore it also supports colliding with object groups.

All the "grunt-work" coding has already been done in the library, written in an efficient manner. Many times I have answered questions here on SO, where the author has basically written tested and partially-debugged code they didn't need to write. That's good for learning to code, but if you really want to reach a finished product, you're better off using the Sprite library, and spending that saved time on game design. It's up to you, of course.

Just to round out the answer, here's a simple sprite example:

import pygame
import random

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

INKY_BLACK = ( 18, 18, 67)


class DemoSprite( pygame.sprite.Sprite ):

    def __init__( self, image_filename, x, y ):
        ### Called when the sprite is created.  Do initialisation here.
        pygame.sprite.Sprite.__init__(self)
        self.image       = pygame.image.load( image_filename ).convert_alpha()   # the image used
        self.rect        = self.image.get_rect()                                 # bounding rectangle for collision
        self.rect.center = ( x, y )                                              # Initial position
        self.movement    = ( random.randrange(-2, 3), random.randrange(-2, 3) )  # move randomly

    def update( self ):
        ### Called to move, or change the state of the sprite
        dx, dy = self.movement
        self.rect.x += dx
        self.rect.y += dy

        # make sure we're still on the screen, if not - wrap around
        if ( self.rect.x < 0 ):
            self.rect.x = WINDOW_WIDTH
        elif ( self.rect.x > WINDOW_WIDTH ):
            self.rect.x = 0
        if ( self.rect.y < 0 ):
            self.rect.y = WINDOW_HEIGHT
        elif ( self.rect.y > WINDOW_HEIGHT ):
            self.rect.y = 0




### MAIN
pygame.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("Sprite Demo")


# Add some sprites
sprite_group = pygame.sprite.Group()
for i in range( 30 ):
    # Random position within the middle 80% of screen 
    pos_x = random.randrange( WINDOW_WIDTH//10, WINDOW_WIDTH-WINDOW_WIDTH//10 )
    pos_y = random.randrange( WINDOW_HEIGHT//10, WINDOW_HEIGHT-WINDOW_HEIGHT//10 )
    sprite_group.add( DemoSprite( "alien.png", pos_x, pos_y ) )


clock = pygame.time.Clock()
done = False
while not done:
    # re-position all the cars
    sprite_group.update()

    # Handle any collisions
    # Simply removes the sprites if they collide
    for alien in sprite_group:
        collided_with = pygame.sprite.spritecollide( alien, sprite_group, False )
        collided_with.remove( alien ) # other than ourselves
        if ( len( collided_with ) > 0 ):
            sprite_group.remove( alien )   # it's now gone

    # Handle User-input Events
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.MOUSEBUTTONUP ):
            # On mouse-click, add a new sprite (at the cursor)
            mouse_pos = pygame.mouse.get_pos()
            sprite_group.add( DemoSprite( "alien.png", mouse_pos[0], mouse_pos[1] ) )

    # Handle User Movement keys
    keys = pygame.key.get_pressed()
    #if ( keys[pygame.K_UP] ):
    #    print("up")

    # Update the window, but not more than 60fps
    window.fill( INKY_BLACK )
    sprite_group.draw( window )
    pygame.display.flip()

    # Clamp FPS
    clock.tick_busy_loop(60)


pygame.quit()

Using the sprite library, we managed to collide every sprite against every other sprite in 5 lines of code. Sure it's a simple contrived case, but it could have easily been sprite_groups of bullets and aliens, or a player and platforms - there still wouldn't have been much more code.

It's simple, fast and already written .

If you want to write your own, good! If you want to use the library, that's great too. It's your code, do it how you like.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM