Если вы запустите alien_invasion.py, то увидите, что корабль может непрерывно двигаться влево и вправо. Если же нажать обе клавиши, корабль останавливается.
Следующий шаг — доработка движения корабля. Внесем изменения в скорость и ограничим величину перемещения, чтобы корабль не выходил за края экрана.
Регулировка скорости корабля
В настоящий момент корабль смещается на один пиксел за каждый проход цикла while, но для повышения точности управления скоростью можно добавить в класс Settings атрибут ship_speed_factor. Этот атрибут определяет величину смещения корабля при каждом проходе цикла. Новый атрибут settings.py выглядит так:
settings.py
class Settings():
"""Класс для хранения всех настроек игры Alien Invasion."""
def __init__(self):
...
. . . .# Настройки корабля
Переменной ship_speed_factor присваивается значение 1.5. При перемещении корабля его позиция изменяется на 1,5 пиксела вместо 1. Дробные значения скорости позволят лучше управлять скоростью корабля при последующем повышении темпа игры. Однако атрибуты прямоугольников (такие, как centerx) принимают только целочисленные значения, поэтому в Ship необходимо внести ряд изменений:
ship.py
class Ship():
(1) . .def __init__(self, ai_settings, screen):
"""Инициализирует корабль и задает его начальную позицию."""
self.screen = screen
(2) . . . .self.ai_settings = ai_settings
...
# Каждый новый корабль появляется у нижнего края экрана
...
. . . .
. . . .# Сохранение вещественной координаты центра корабля.
(3) . . . .self.center = float(self.rect.centerx)
. . . .
# Флаги перемещения
self.moving_right = False
self.moving_left = False
. . . .def update(self):
"""Обновляет позицию корабля с учетом флагов."""
. . . .# Обновляется атрибут center, не rect.
if self.moving_right:
(4) . . . . . .self.center += self.ai_settings.ship_speed_factor
if self.moving_left:
. . . . . .self.center -= self.ai_settings.ship_speed_factor
. . . .
. . . .# Обновление атрибута rect на основании self.center.
(5) . . . .self.rect.centerx = self.center
def blitme(self):
...
В точке (1) в список параметров __init__() добавляется параметр ai_settings, чтобы для корабля была доступна величина его скорости. Затем параметр ai_settings преобразуется в атрибут для использования в update() (2). Так как позиция корабля изменяется с нецелым приращением пикселов, она должна храниться в переменной, способной хранить дробные значения. Формально атрибутам rect можно присвоить дробные значения, но rect сохранит только целую часть этого значения. Для точного хранения позиции корабля определяется новый атрибут self.center, способный хранить дробные значения (3). Функция float() используется для преобразования значения self.rect.centerx в вещественный формат и сохранения этого значения в self.center.
После изменения позиции корабля в update() значение self.center изменяется на величину, хранящуюся в ai_settings.ship_speed_factor (4). После обновления self.center новое значение используется для обновления атрибута self.rect.centerx, управляющего позицией корабля (5). В self.rect.centerx будет сохранена только целая часть self.center, но для отображения корабля этого достаточно.
Значение ai_settings должно передаваться в аргументе при создании экземпляра Ship в alien_invasion.py:
alien_invasion.py
...
def run_game():
...
# Создание корабля.
. .ship = Ship(ai_settings, screen)
...
Теперь с любым значением ship_speed_factor, бульшим 1, корабль будет двигаться быстрее. Эта возможность ускорит реакцию корабля на действия игрока, а также позволит нам изменить темп игры с течением времени.
Ограничение перемещений
Если удерживать какую-нибудь клавишу со стрелкой достаточно долго, корабль выйдет за край экрана. Давайте сделаем так, чтобы корабль останавливался при достижении края экрана. Задача решается изменением метода update() в классе Ship:
ship.py
def update(self):
"""Обновляет позицию корабля с учетом флагов."""
# Обновляется атрибут center, не rect.
(1) . . . .if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
(2) . . . .if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor
. . . .
# Обновление атрибута rect на основании self.center
self.rect.centerx = self.center
Этот код проверяет позицию корабля перед изменением значения self.center. Выражение self.rect.right возвращает координату x правого края прямоугольника корабля. Если это значение меньше значения, возвращаемого self.screen_rect.right, значит, корабль еще не достиг правого края экрана (1) . То же относится и к левому краю: если координата x левой стороны прямоугольника больше 0, значит, корабль еще не достиг левого края экрана (2). Проверка гарантирует, что корабль будет оставаться в пределах экрана, перед изменением значения self.center.
Если вы запустите alien_invasion.py сейчас, то движение корабля будет останавливаться у края экрана.
Рефакторинг check_events()