Python. Обнаружение коллизий с кораблем.
Начнем с проверки коллизий между пришельцами и кораблем, чтобы мы могли правильно обработать столкновения с пришельцами. Коллизии «пришелец-корабль» проверяются немедленно после обновления позиции каждого пришельца в game_functions.py
Метод spritecollideany() получает два аргумента: спрайт и группу. Метод пытается найти любой элемент группы, вступивший в коллизию со спрайтом, и останавливает цикл по группе сразу же после обнаружения столкнувшегося элемента. В данном случае он перебирает группу aliens и возвращает первого пришельца, столкнувшегося с кораблем. Если ни одна коллизия не обнаружена, spritecollideany() возвращает None, и блок if не выполняется. Если же будет обнаружен пришелец, столкнувшийся с кораблем, метод возвращает этого пришельца, и выполняется блок if: выводится сообщение Ship hit!!! . Команда print всего лишь позволяет легко проверить правильность обнаружения коллизий. Далее необходимо передать ship функции update_aliens() в alien_invasion.py:
Если вы запустите Alien Invasion, при столкновении пришельца с кораблем в терминальном окне появляется сообщение Ship hit!!!.
Python. Обработка столкновений с кораблем.
Напишем новый класс GameStats для ведения статистики и сохраним его в файле game_stats.py:
На все время работы Alien Invasion будет создаваться один экземпляр GameStats, но часть статистики должна сбрасываться в начале каждой новой игры. Для этого бульшая часть статистики будет инициализироваться в методе reset_stats() вместо __init__(). Этот метод будет вызываться из __init__(), чтобы статистика правильно инициализировалась при первом создании экземпляра GameStats, а метод reset_stats() будет вызываться в начале каждой новой игры. Пока в игре используется всего один вид статистики — значение ships_left, изменяющееся в ходе игры. Количество кораблей в начале игры хранится в settings.py под именем ship_limit:
Также необходимо внести ряд изменений в alien_invasion.py для создания экземпляра GameStats:
Импортируем новый класс GameStats , создаем экземпляр stats , а затем добавляем аргументы stats, screen и ship в вызов update_aliens() . Эти аргументы будут использоваться для отслеживания количества кораблей, оставшихся у игрока, и построения нового флота при столкновении пришельца с кораблем. Когда пришелец сталкивается с кораблем, программа уменьшает количество оставшихся кораблей на 1, уничтожает всех существующих пришельцев и пули, создает новый флот и возвращает корабль в середину экрана. (Также игра ненадолго приостанавливается, чтобы игрок заметил столкновение и перестроился перед появлением нового флота.) Бульшая часть этого кода будет включена в функцию ship_hit() в game_functions.py:
Сначала мы импортируем функцию sleep() из модуля time, чтобы приостановить игру. Новая функция ship_hit() управляет реакцией игры на столкновение корабля с пришельцем. Внутри ship_hit() число оставшихся кораблей уменьшается на 1, после чего происходит очистка групп aliens и bullets. Затем программа создает новый флот и выравнивает корабль по центру нижнего края . (Вскоре мы добавим метод center_ship() в класс Ship.) На экране делается короткая пауза, чтобы игрок увидел, что его корабль столкнулся с пришельцем . После завершения паузы sleep() код переходит к функции update_screen(), которая перерисовывает новый флот на экране. Также необходимо обновить определение update_aliens() и добавить параметры stats, screen и bullets , чтобы эти значения можно было передать при вызове ship_hit(). Ниже приведен новый метод center_ship(); добавьте его в конец ship.py:
Чтобы выровнять корабль по центру, мы задаем атрибуту center корабля значение, соответствующее центру экрана (полученное при помощи атрибута screen_rect).
Python. Достижение нижнего края экрана.
Если пришелец добирается до нижнего края экрана, программа будет реагировать так же, как при столкновении с кораблем. Добавьте game_functions.py для проверки этого условия новую функцию, которая будет называться check_aliens_bottom():
Функция check_aliens_bottom() проверяет, есть ли хотя бы один пришелец, добравшийся до нижнего края экрана. Условие выполняется, когда атрибут rect.bottom пришельца больше или равен атрибуту rect.bottom экрана . Если пришелец добрался до низа, вызывается функция ship_hit(). Если хотя бы один пришелец добрался до нижнего края, проверять остальных уже не нужно, поэтому после вызова ship_hit() цикл прерывается. Функция check_aliens_bottom() вызывается после обновления позиций всех пришельцев и после проверки столкновений «пришелец-корабль». Теперь новый флот будет появляться как при столкновении корабля с пришельцем, так и в том случае, если кто-то из пришельцев смог добраться до нижнего края экрана.
Python. Конец игры.
Программа Alien Invasion уже на что-то похожа, но игра длится бесконечно. Значение ships_left просто продолжает уходить в отрицательную бесконечность. Добавим в GameStats новый атрибут — флаг game_active, который завершает игру после потери последнего корабля в game_stats.py:
Добавим в ship_hit() код, который сбрасывает флаг game_active в состояние False при потере игроком последнего корабля в game_functions.py:
Бульшая часть кода ship_hit() осталась неизменной. Весь существующий код был перемещен в блок if, который проверяет, что у игрока остался хотя бы один корабль. Если корабли не кончились, программа создает новый флот, делает паузу и продолжает игру. Если же игрок потерял последний корабль, флаг game_active переводится в состояние False.
Python. Определение исполняемых частей игры.
В файле alien_invasion.py необходимо определить части игры, которые должны выполняться всегда, и те части, которые должны выполняться только при активной игре:
В основном цикле всегда должна вызываться функция check_events(), даже если игра находится в неактивном состоянии. Например, программа все равно должна узнать о том, что пользователь нажал клавишу Q для завершения игры или щелкнул на кнопке закрытия окна. Также экран должен обновляться в то время, пока игрок решает, хочет ли он начать новую игру. Остальные вызовы функций должны происходить только при активной игре, потому что в то время, когда игра не активна, обновлять позиции игровых элементов не нужно. В обновленной версии игра должна останавливаться после потери игроком последнего корабля.