Pygame: пытаясь понять класс Sprite - PullRequest
2 голосов
/ 07 апреля 2020

Я нашел в документации Pygame класс с именем Sprite. Я прочитал объяснение, но я не понял, для чего этот класс используется.

Я понял, что мы использовали его для наследования других классов с помощью конструктора, но это все.

Если кто-то имеет четкое объяснение полезности класса и , как правильно его использовать , мне интересно.

1 Ответ

3 голосов
/ 08 апреля 2020

Правильно, поэтому наведите курсор мыши. Это спрайт.

Это квадратное растровое изображение с некоторой прозрачностью. Но только видимые части ничего не значат - вам все равно, если прозрачная часть переместилась поверх какого-либо элемента экрана, например.

Спрайты в PyGame похожи.

В былые времена;) в большинстве аркадных игр использовалась спрайт-анимация. Подумайте о Па c -Ман (около 1980); существо, которое является большим желтым ртом. Это реализовано как Sprite. Итак, давайте сделаем одно:

Zoomed Pac Man Pac Man

Теперь эту вещь нужно перемещать по экрану, пиксели, которые прозрачный (светло-тёмно-серый) нужно показать фон. Важно отметить, что не только для PacMan, но и для более неровных изображений все прозрачное должно , а не быть частью обнаружения столкновений. Это еще один важный аспект «Спрайтов».

Скажите, что призраки противника в пулях, выпущенных PacMan (вау, это страшная мысль!), Вы бы очень расстроились, если бы пуля прошла сквозь прозрачный угол спрайта PacMan, но это все еще считалось "хитом". Для правильной реализации используется маска . По сути, это еще одно логическое растровое изображение, которое сообщает, какие пиксели следует считать частью Sprite для столкновения, а какие нет.

Существует также код, необходимый для рисования этого растрового изображения на экране. В настоящее время использование процессора для этого является лишь незначительным соображением. Скромный P C с PyGame может легко нарисовать 1000 спрайтов на экране со скоростью 60FPS. Но в прежние времена это требовало значительного времени обработки и, как мы надеемся, было сделано с помощью какого-то аппаратного обеспечения. Даже в 1990-х годах некоторые видеокарты рекламировались с поддержкой аппаратного курсора мыши. Sprite Class в PyGame имеет очень эффективный код для рисования растровых изображений на экране.

Итак, подведем итог, зачем использовать спрайты:

  • Простота реализации
  • Прозрачность и маски
  • Быстрое обнаружение столкновений
  • Ваше оборудование 1980-х годов не может даже мечтать об аппаратном 3D

Зачем использовать спрайты PyGame:

  • Они уже написаны
  • Они быстрые , эффективны и не содержат ошибок
  • Они могут использовать маски
  • Они уже иметь эффективный код обнаружения столкновений
  • Поддерживающий класс спрайтов очень полезен

Итак ... Как мне создать спрайт?

Вот эталонный класс. Я прокомментирую код.

class Pacman( pygame.sprite.Sprite ):               # parent class is Sprite

    def __init__( self, x, y, pacman_bitmap ):      # New PacMan at (x,y)
        pygame.sprite.Sprite.__init__( self )       # Init the parent obj too
        self.image = pacman_bitmap                  # it MUST be self.image for sprites
        self.rect  = self.image.get_rect()          # it MUST be self.rect for sprites
        self.rect.center = ( x, y )                 # move the sprite
        self.move_dir_x  = 0                        
        self.move_dir_y  = 0                        # This pacman never stops

    # Semi-optional Part 
    def update( self ):                             # called to somehow effect the sprite.  
        # Move pacman                               # MUST be named "update"
        x, y = self.rect.center
        x += self.move_dir_x
        y += self.move_dir_y
        self.rect.center = ( x, y )                 # move the sprite

    # Optional Part
    def setDirection( self, dir ):                  # Called when user sends
        if ( dir == 'up' ):                         # input to change direction
            self.move_dir_x = 0
            self.move_dir_y = -1
        elif ( dir == 'right' ):
            self.move_dir_x = 1
            self.move_dir_y = 0
        #elif ... TODO - rest of direction changes

И это все. Базовый объект Sprite ожидает, что подкласс "перезапишет" переменные-члены image и rect. Группа Sprite использует функцию update() для изменения спрайта. Этот просто перемещается в любом направлении, которое было установлено (которое будет меняться в зависимости от ввода пользователя).

Таким образом, мы можем использовать это как:

pacman_image   = pygame.image.load( 'pacman.png' ).convert()
pacman_sprite  = Pacman( 100, 100, pacman_image )
player1_sprite = pygame.sprite.GroupSingle()           # Just 1 player for now
player_sprites.add( pacman_sprite )

# Imagine a similar sprite class for ghosts
ghost_image   = pygame.image.load( 'blue_ghost.png' ).convert()
...
ghost_sprites = pygame.sprite.Group()
for i in range( 4 ):
    ghost_sprites.add( Ghost( 10, 50, ghost_image ) )

И затем в Main L oop:

game_over = False
while not game_over:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            game_over = True

    # Movement keys too (not event driven)
    keys = pygame.key.get_pressed()
    if ( keys[pygame.K_UP] ):
        player_sprite.setDirection( 'up' )
    elif ( keys[pygame.K_RIGHT] ):
        player_sprite.setDirection( 'right' )
    #elif  TODO - rest of keys

    # re-position all the players and ghosts
    player_sprites.update()
    ghost_sprites.update()

    # Paint the background
    paintPacmanEnvironment( window )

    # Paint all the sprites
    player_sprites.draw( window )
    ghost_sprites.draw( window )

    # Did the player hit a ghost? 
    # spritecollide(sprite, group, dokill, collided = None) -> Sprite_list
    if ( pygame.sprite.spritecollide( player_sprite, ghost_sprites, False ) ):
        # TODO: handle hitting a ghost

Так что да , это немного связано с первоначальной настройкой спрайтов. Но посмотрите на это главное l oop! С помощью всего лишь нескольких вызовов функций вы получаете рисование и столкновения практически даром, при чуть большей настройке (около 1 строки) вы также получаете растровые маски. Вот почему вы должны использовать PyGame Sprites.

EDIT: Быстрая заметка о Sprite.update():

Функция update() является хорошим местом для обработки не только движения, но и анимации. Очевидно, что нам нужно несколько кадров анимации, чтобы заставить рота Пакмана двигаться. Чтобы реализовать это, Pacman.update() будет смотреть на текущее время и использовать его для перехода к следующему кадру анимации. Таким образом, вместо создания Pacman только с одним растровым изображением, мы могли бы создать его со списком изображений, и тогда Pacman.image будет установлено на правильное изображение внутри .udpate(). Это работает действительно хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...