Добавить в корзинуПозвонить
Найти в Дзене

День 160. Стрельба. Добавление настроек. Создание класса Bullet. Группировка пуль.

Python. Стрельба. Добавление настроек. Сначала добавим в settings.py новые настройки для значений, управляющих поведением класса Bullet. Эти настройки добавляются в конец метода __init__(): Эти настройки создают темно-серые пули с шириной 3 пиксела и высотой 15 пикселов. Python. Создание класса Bullet. Теперь создадим файл bullet.py для хранения класса Bullet. Первая часть файла bullet.py выглядит так: Класс Bullet наследует от класса Sprite, импортируемого из модуля pygame.sprite. Работая со спрайтами (sprite), разработчик группирует связанные элементы в своей игре и выполняет операцию со всеми сгруппированными элементами одновременно. Чтобы создать экземпляр пули, методу __init__() необходимо передать экземпляры ai_settings, screen и ship, а вызов super() необходим для правильной реализации наследования от Sprite. Создается атрибут rect пули. Пуля не создается на основе готового изображения, поэтому прямоугольник приходится строить «с нуля» при помощи класса pygame.Rect(). При создан

Python. Стрельба. Добавление настроек.

Сначала добавим в settings.py новые настройки для значений, управляющих поведением класса Bullet. Эти настройки добавляются в конец метода __init__():

-2

Эти настройки создают темно-серые пули с шириной 3 пиксела и высотой 15 пикселов.

Python. Создание класса Bullet.

Теперь создадим файл bullet.py для хранения класса Bullet. Первая часть файла bullet.py выглядит так:

-3

Класс Bullet наследует от класса Sprite, импортируемого из модуля pygame.sprite. Работая со спрайтами (sprite), разработчик группирует связанные элементы в своей игре и выполняет операцию со всеми сгруппированными элементами одновременно. Чтобы создать экземпляр пули, методу __init__() необходимо передать экземпляры ai_settings, screen и ship, а вызов super() необходим для правильной реализации наследования от Sprite.

Создается атрибут rect пули. Пуля не создается на основе готового изображения, поэтому прямоугольник приходится строить «с нуля» при помощи класса pygame.Rect(). При создании экземпляра этого класса необходимо задать координаты левого верхнего угла прямоугольника, его ширину и высоту. Прямоугольник инициализируется в точке (0, 0), но в следующих двух строках он перемещается в нужное место, так как позиция пули зависит от позиции корабля. Ширина и высота пули определяются значениями, хранящимися в ai_settings. Атрибуту centerx пули присваивается значение rect.centerx корабля. Пуля должна появляться у верхнего края корабля, поэтому верхний край пули совмещается с верхним краем прямоугольника корабля для имитации «выстрела» из корабля.

Координата y пули хранится в вещественной форме для внесения более точных изменений в скорость пули. Настройки цвета и скорости пули сохраняются в self.color и self.speed_factor. А вот как выглядит вторая часть bullet.py, update() и draw_bullet():

-4

Метод update() управляет позицией пули. Когда происходит выстрел, пуля двигается вверх по экрану, что соответствует уменьшению координаты y; следовательно, для обновления позиции пули следует вычесть величину, хранящуюся в self.speed_factor, из self.y. Затем значение self.y используется для изменения значения self.rect.y . Атрибут speed_factor позволяет увеличить скорость пуль по ходу игры или при изменении ее поведения. Координата x пули после выстрела не изменяется, поэтому пуля летит вертикально по прямой линии. Для вывода пули на экран вызывается функция draw_bullet(). Она заполняет часть экрана, определяемую прямоугольником пули, цветом из self.color.

Python. Группировка пуль.

Класс Bullet и все необходимые настройки готовы; можно переходить к написанию кода, который будет выпускать пулю каждый раз, когда игрок нажимает клавишу «пробел». Сначала мы создадим в alien_invasion.py группу для хранения всех летящих пуль, чтобы программа могла управлять их полетом. Эта группа будет представлена экземпляром класса pygame.sprite.Group, который напоминает список с расширенной функциональностью, которая может быть полезна при построении игр. Мы воспользуемся группой для прорисовки пуль на экране при каждом проходе основного цикла и обновления текущей позиции каждой пули:

-5

Класс Group импортируется из pygame.sprite. Создается экземпляр Group с именем bullets. Эта группа создается за пределами цикла while, чтобы новая группа пуль не создавалась при каждом проходе цикла. Объект bullets передается методам check_events() и update_screen(). В check_events() он используется при обработке клавиши «пробел», а в update_screen() необходимо перерисовать выводимые на экран пули. Вызов update() для группы приводит к автоматическому вызову update() для каждого спрайта в группе. Строка bullets.update() вызывает bullet.update() для каждой пули, включенной в группу bullets.

Python. Обработка выстрелов.

В файле game_functions.py необходимо внести изменения в метод check_keydown_events(), чтобы при нажатии клавиши «пробел» происходил выстрел. Изменять check_keyup_events() не нужно, потому что при отпускании клавиши ничего не происходит. Также необходимо изменить update_screen() и вывести каждую пулю на экран перед вызовом flip(). Ниже представлены соответствующие изменения в game_functions.py:

-6
-7

Группа bullets передается check_keydown_events(). Когда игрок нажимает пробел, создается новая пуля (экземпляр Bullet с именем new_bullet), которая добавляется в группу bullets методом add(); код bullets.add(new_bullet) сохраняет новую пулю в группе bullets. Группу bullets необходимо добавить в число параметров в определении check_events(), а также передать в аргументе при вызове check_keydown_events(). Параметр bullets передается функции update_screen(), которая рисует пули на экране. Метод bullets.sprites() возвращает список всех спрайтов в группе bullets. Чтобы нарисовать все выпущенные пули на экране, программа перебирает спрайты в bullets и вызывает для каждого draw_bullet() . Если запустить alien_invasion.py сейчас, вы сможете двигать корабль влево и вправо и выпускать сколько угодно пуль. Пули перемещаются вверх по экрану и исчезают при достижении верхнего края. Размер, цвет и скорость пуль можно изменить при помощи настроек в settings.py.

Python. Удаление старых пуль.

От старых пуль необходимо избавиться, иначе игра замедлится из-за большого объема лишней работы. Для этого необходимо определить момент, когда атрибут bottom прямоугольника пули достигнет 0, — это означает, что пуля вышла за верхний край экрана:

-8

Удалять элементы из списка или группы в цикле for не следует, поэтому перебирать нужно копию группы. Метод copy() используется для создания цикла for , в котором возможно изменять содержимое bullets. Программа проверяет каждую пулю и определяет, вышла ли она за верхний край экрана . Если пуля пересекла границу, она удаляется из bullets. Добавляется команда print, которая сообщает, сколько пуль сейчас существует в игре; по выведенному значению можно убедиться в том, что пули действительно были удалены. Если код работает правильно, вы можете понаблюдать за выводом на терминале и убедиться в том, что количество пуль уменьшается до 0 после того, как очередной залп уходит за верхний край экрана. После того как вы запустите игру и убедитесь в том, что пули правильно удаляются из группы, удалите команду print. Если команда останется в программе, она существенно замедлит игру, потому что вывод на терминал занимает больше времени, чем отображение графики в игровом окне.

Python. Ограничение количества пуль.

Сначала сохраним максимально допустимое количество пуль в settings.py:

-9

В любой момент времени на экране может находиться не более трех пуль. Эта настройка будет использоваться в game_functions.py для проверки количества существующих пуль перед созданием новой пули в check_keydown_events():

-10

Python. Создание функции update_bullets().

Необходимо, чтобы главный файл программы alien_invasion.py был как можно более простым, поэтому после написания и проверки кода управления пулями этот код можно переместить в модуль game_functions. Создадим новую функцию update_bullets() и добавим ее в конец game_functions.py:

-11

Код update_bullets() вырезается и вставляется из alien_invasion.py; единственным необходимым параметром функции является группа bullets. Цикл while в alien_invasion.py снова выглядит просто:

-12

Python. Создание функции fire_bullet().

Переместим код стрельбы в отдельную функцию, чтобы выстрел выполнялся всего одной строкой кода, а блок elif в check_keydown_events() оставался простым:

-13
-14

Функция fire_bullet() просто содержит код, который использовался для выстрела при нажатии клавиши «пробел»; вызов fire_bullet() добавляется в check_keydown_events() при нажатии клавиши «пробел».

Python. Быстрое завершение игры.

Добавим возможность быстрого завершения игры при нажатии клавиши Q, пропишем в game_functions.py:

-15