. . . .# Создание пули в позиции (0,0) и назначение правильной позиции.
(1) . . . .self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,
. . . . . .ai_settings.bullet_height)
(2) . . . .self.rect.centerx = ship.rect.centerx
(3) . . . .self.rect.top = ship.rect.top
. . . .
. . . .# Позиция пули хранится в вещественном формате.
(4) . . . .self.y = float(self.rect.y)
(5) . . . .self.color = ai_settings.bullet_color
. . . .self.speed_factor = ai_settings.bullet_speed_factor
Класс Bullet наследует от класса Sprite, импортируемого из модуля pygame.sprite. Работая со спрайтами (sprite), разработчик группирует связанные элементы в своей игре и выполняет операцию со всеми сгруппированными элементами одновременно. Чтобы создать экземпляр пули, методу __init__() необходимо передать экземпляры ai_settings, screen и ship, а вызов super() необходим для правильной реализации наследования от Sprite.
примечание
Вызов super(Bullet, self).__init__() использует синтаксис Python 2.7. В Python 3 этот синтаксис тоже работает, хотя вызов также можно записать в более простой форме super().__init__().
В точке (1) создается атрибут rect пули. Пуля не создается на основе готового изображения, поэтому прямоугольник приходится строить «с нуля» при помощи класса pygame.Rect(). При создании экземпляра этого класса необходимо задать координаты левого верхнего угла прямоугольника, его ширину и высоту. Прямоугольник инициализируется в точке (0, 0), но в следующих двух строках он перемещается в нужное место, так как позиция пули зависит от позиции корабля. Ширина и высота пули определяются значениями, хранящимися в ai_settings.
В точке (2) атрибуту centerx пули присваивается значение rect.centerx корабля. Пуля должна появляться у верхнего края корабля, поэтому верхний край пули совмещается с верхним краем прямоугольника корабля для имитации «выстрела» из корабля (3).
Координата y пули хранится в вещественной форме для внесения более точных изменений в скорость пули (4). В точке (5) настройки цвета и скорости пули сохраняются в self.color и self.speed_factor.
А вот как выглядит вторая часть bullet.py, update() и draw_bullet():
bullet.py
. .def update(self):
. . . ."""Перемещает пулю вверх по экрану."""
. . . .# Обновление позиции пули в вещественном формате.
(1) . . . .self.y -= self.speed_factor
. . . .# Обновление позиции прямоугольника.
(2) . . . .self.rect.y = self.y
. .def draw_bullet(self):
. . . ."""Вывод пули на экран."""
(3) . . . .pygame.draw.rect(self.screen, self.color, self.rect)
Метод update() управляет позицией пули. Когда происходит выстрел, пуля двигается вверх по экрану, что соответствует уменьшению координаты y; следовательно, для обновления позиции пули следует вычесть величину, хранящуюся в self.speed_factor, из self.y (1) . Затем значение self.y используется для изменения значения self.rect.y (2). Атрибут speed_factor позволяет увеличить скорость пуль по ходу игры или при изменении ее поведения. Координата x пули после выстрела не изменяется, поэтому пуля летит вертикально по прямой линии.
Для вывода пули на экран вызывается функция draw_bullet(). Она заполняет часть экрана, определяемую прямоугольником пули, цветом из self.color (3).
Группировка пуль
Класс Bullet и все необходимые настройки готовы; можно переходить к написанию кода, который будет выпускать пулю каждый раз, когда игрок нажимает клавишу «пробел». Сначала мы создадим в alien_invasion.py группу для хранения всех летящих пуль, чтобы программа могла управлять их полетом. Эта группа будет представлена экземпляром класса pygame.sprite.Group, который напоминает список с расширенной функциональностью, которая может быть полезна при построении игр. Мы воспользуемся группой для прорисовки пуль на экране при каждом проходе основного цикла и обновления текущей позиции каждой пули:
alien_invasion.py
import pygame
from pygame.sprite import Group
...
def run_game():
...
# Создание корабля.
ship = Ship(ai_settings, screen)
. .# Создание группы для хранения пуль.
(1) . .bullets = Group()
# Запуск основного цикла игры.
while True:
. . . .gf.check_events(ai_settings, screen, ship, bullets)
. . . .ship.update()
(2) . . . .bullets.update()
. . . .gf.update_screen(ai_settings, screen, ship, bullets)
run_game()
Класс Group импортируется из pygame.sprite. В точке (1) создается экземпляр Group с именем bullets. Эта группа создается за пределами цикла while, чтобы новая группа пуль не создавалась при каждом проходе цикла.
примечание
Если группа будет создаваться в цикле, в результате программа создает тысячи групп, и скорость игры упадет до минимума. Если ваша игра со временем начинает заметно «тормозить», внимательно проверьте, что происходит в основном цикле while.
Объект bullets передается методам check_events() и update_screen(). В check_events() он используется при обработке клавиши «пробел», а в update_screen() необходимо перерисовать выводимые на экран пули.