Метод prep_level() создает изображение на базе значения, хранящегося в stats.level (1) , и приводит атрибут right изображения в соответствие с атрибутом right счета (2). Затем атрибут top сдвигается на 10 пикселов ниже нижнего края изображения текущего счета, чтобы между счетом и уровнем оставался пустой интервал (3).
В метод show_score() также необходимо внести изменения:
scoreboard.py
def show_score(self):
. ."""Выводит текущий счет, рекорд и число оставшихся кораблей."""
self.screen.blit(self.score_image, self.score_rect)
self.screen.blit(self.high_score_image, self.high_score_rect)
. .self.screen.blit(self.level_image, self.level_rect)
Добавленная строка выводит на экран изображение, представляющее уровень.
Увеличение stats.level и обновление изображения уровня выполняются в check_bullet_alien_collisions():
game_functions.py
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,
aliens, bullets):
...
if len(aliens) == 0:
. . . .# Если весь флот уничтожен, начинается следующий уровень.
bullets.empty()
ai_settings.increase_speed()
. . . .
. . . .# Увеличение уровня.
(1) . . . .stats.level += 1
(2) . . . .sb.prep_level()
. . . .
create_fleet(ai_settings, screen, ship, aliens)
Если все пришельцы уничтожены, программа увеличивает значение stats.level (1) и вызывает prep_level() для обновления уровня (2).
Чтобы убедиться в том, что изображения текущего счета и уровня правильно обновляются в начале новой игры, инициируйте сброс при нажатии кнопки Play:
game_functions.py
def check_play_button(ai_settings, screen, stats, sb, play_button, ship,
. . . .aliens, bullets, mouse_x, mouse_y):
"""Запускает новую игру при нажатии кнопки Play."""
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_clicked and not stats.game_active:
...
# Сброс игровой статистики.
stats.reset_stats()
stats.game_active = True
. . . .
. . . .# Сброс изображений счетов и уровня.
(1) . . . .sb.prep_score()
. . . .sb.prep_high_score()
. . . .sb.prep_level()
. . . .
# Очистка списков пришельцев и пуль.
aliens.empty()
bullets.empty()
. .
...
Определению check_play_button() необходим объект sb. Чтобы сбросить изображения на экране, после сброса игровых настроек следуют вызовы prep_score(), prep_high_score() и prep_level().
Затем объект sb передается check_events(), чтобы объект Scoreboard был доступен для check_play_button():
game_functions.py
def check_events(ai_settings, screen, stats, sb, play_button, ship, aliens,
. . . .bullets):
"""Обрабатывает нажатия клавиш и события мыши."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
...
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
(1) . . . . . .check_play_button(ai_settings, screen, stats, sb, play_ button,
. . . . . . . .ship, aliens, bullets, mouse_x, mouse_y)
Определение check_events() должно получать sb в параметре, чтобы при вызове check_play_button() можно было передать sb в аргументе (1) .
Остается обновить вызов check_events() в alien_invasion.py, чтобы в нем также передавался объект sb:
alien_invasion.py
# Запуск основного цикла игры.
while True:
. .gf.check_events(ai_settings, screen, stats, sb, play_button, ship,
. . . .aliens, bullets)
...
Теперь количество пройденных уровней отображается на экране (рис. 14.5).
примечание
В некоторых классических играх выводимая информация снабжается текстовыми метками: «Уровень», «Рекорд» и т.д. Мы эти метки опустили, потому что смысл каждого числа понятен каждому, кто сыграл в Alien Invasion. Если вы включите эти метки, добавьте их в строки непосредственно перед вызовами font.render() в Scoreboard.
Рис. 14.5. Текущий уровень выводится под текущим счетом
Вывод количества кораблей
Остается вывести количество кораблей, оставшихся у игрока, но на этот раз информация будет выводиться в графическом виде. Как во многих классических аркадных играх, в левом верхнем углу экрана программа рисует несколько изображений корабля. Каждый корабль обозначает одну оставшуюся попытку.
Для начала нужно сделать так, чтобы класс Ship наследовал от Sprite, — это необходимо для создания группы кораблей:
ship.py
import pygame
from pygame.sprite import Sprite
(1) class Ship(Sprite):
. .
def __init__(self, ai_settings, screen):
"""Инициализирует корабль и задает его начальную позицию."""
(2) . . . .super(Ship, self).__init__()
...
Здесь мы импортируем Sprite, объявляем о наследовании Ship от Sprite (1) и вызываем super() в начале __init__() (2).
Далее необходимо изменить Scoreboard и создать группу кораблей для вывода на экран. Команды import и метод __init__() выглядят так:
scoreboard.py
import pygame.font
from pygame.sprite import Group
from ship import Ship
class Scoreboard():
"""Класс для вывода игровой информации."""
def __init__(self, ai_settings, screen, stats):
...
self.prep_level()
. . . .self.prep_ships()
...
Так как мы собираемся создать группу кораблей, программа импортирует классы Group и Ship. Метод prep_ships() будет вызываться после prep_level(). Он выглядит так:
scoreboard.py
. .def prep_ships(self):