Правильно, поэтому наведите курсор мыши. Это спрайт.
Это квадратное растровое изображение с некоторой прозрачностью. Но только видимые части ничего не значат - вам все равно, если прозрачная часть переместилась поверх какого-либо элемента экрана, например.
Спрайты в PyGame похожи.
В былые времена;) в большинстве аркадных игр использовалась спрайт-анимация. Подумайте о Па c -Ман (около 1980); существо, которое является большим желтым ртом. Это реализовано как Sprite. Итак, давайте сделаем одно:
Теперь эту вещь нужно перемещать по экрану, пиксели, которые прозрачный (светло-тёмно-серый) нужно показать фон. Важно отметить, что не только для 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()
. Это работает действительно хорошо.