Стрелялка с Pygame №4: графика

Четвертая часть проект «Стрелялка с Pygame». Если пропустили, обязательно вернитесь и начините с первой части. В этот раз речь пойдет об использовании заготовленной графики.

В этой серии уроков будет создана полноценная игра на языке Python с помощью библиотеки Pygame. Она будет особенно интересна начинающим программистам, которые уже знакомы с основами языка и хотят углубить знания, а также узнать, что лежит в основе создания игр.

Выбор графики

В уроке, посвященном спрайтами, затрагивалась тема Opengameart.org — источника бесплатного арта для игр; и популярного местного автора, Kenney. Kenney создал набор арта, который прекрасно подойдет для этой стрелялки. Он называется «Space Shooter Pack». Найти его можно здесь:

https://opengameart.org/content/space-shooter-redux

Он включает массу качественных изображений с космическими кораблями, лазерами, астероидами и так далее.

Архив содержит несколько папок. Для этого проекта нужно папка PNG со всеми изображениями по отдельности. Для спрайтов пока что нужно только три, а также изображение звездного неба для фона.
Изображение игрока
Изображение врага
Изображение выстрела
Фон игры

Изображения необходимо скопировать туда, где игра сможет их найти. Лучше всего создать новую папку в том же месте, где хранится код игры. Назовем ее «img».

Загрузка изображений

Чтобы быть уверенными в том, что код будет работать в любой операционной системе, нужно использовать функцию os.path, которая определяет правильный путь к файлам вне зависимости от ОС.

В верхней части программы необходимо определить местоположение папки img:

from os import path

img_dir = path.join(path.dirname(__file__), 'img')

Прорисовка фона

Теперь можно приступать к загрузке фонового изображения. Загрузку ассетов необходимо производить до игрового цикла и кода запуска:

# Загрузка всей игровой графики
background = pygame.image.load(path.join(img_dir, 'starfield.png')).convert()
background_rect = background.get_rect()

Теперь можно прорисовать фон в разделе Draw игрового цикла до прорисовки любого из спрайтов:

# Рендеринг
screen.fill(BLACK)
screen.blit(background, background_rect)
all_sprites.draw(screen)

blit — это олдскульный термин из компьютерной графики, который обозначает прорисовку пикселей одного изображения на другом. В этом случае — прорисовку фона на экране. Теперь фон выглядит намного лучше:

Прорисовка фона

Изображения спрайтов:

Теперь можно загрузить изображения спрайтов:

# Загрузка всей игровой графики
background = pygame.image.load(path.join(img_dir, 'starfield.png')).convert()
background_rect = background.get_rect()
player_img = pygame.image.load(path.join(img_dir, "playerShip1_orange.png")).convert()
meteor_img = pygame.image.load(path.join(img_dir, "meteorBrown_med1.png")).convert()
bullet_img = pygame.image.load(path.join(img_dir, "laserRed16.png")).convert()

Начнем с игрока — необходимо заменить зеленый прямоугольник, то есть self.image и не забыть убрать параметр image.fill(GREEN), который больше не нужен:

class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = player_img
        self.rect = self.image.get_rect()

Изображения спрайтов

Тем не менее имеется пара проблем. Во-первых, картинка чуть больше, чем требуется. Есть два варианта: 1) открыть ее в графическом редакторе (Photoshop, GIMP) и отредактировать; 2) поменять размер прямо в коде. Выбираем второй вариант. Для этого понадобится функция Pygame под названием transform.scale(). Уменьшим изображение вдвое — до размера 50х30 пикселей.

Вторая проблема — черный прямоугольник вокруг корабля. Чтобы это исправить, нужно назначить прозрачный цвет с помощью set_colorkey:

self.image = pygame.transform.scale(player_img, (50, 38))
self.image.set_colorkey(BLACK)

Если повторить то же самое для классов Bullet и Mob (хотя их размер менять не нужно), игра будет выглядеть намного лучше:

Изображения спрайтов

Код урока — shmup-4.py

Итого

Теперь в игре есть графика, и это помогает заметить новую проблему: астероиды уничтожают корабль, даже когда не касаются его. В следующем уроке поработаем над тем, чтобы столкновения работали корректно.