Продолжаем создание космической аркады. Управление кораблем
В прошлых статьях по созданию игры с Python и Pygame мы добились отображения корабля на фоне изображения космического пространства. Но что можно делать с неподвижным кораблем. Само собой игроки должны иметь возможность поворачивать его влево и вправо. Сейчас же наш корабль направлен носом вверх. Хорошо бы хоть иметь хоть какое-то управление над ним. И в сегодняшней статье мы реализуем данную возможность.
Pygame есть встроенные методы вращения спрайтов, но есть небольшая проблема.
В общем, поворот изображения-это сложный процесс, требующий пересчета пикселей в новом изображении. Во время этого пересчета информация об исходных пикселях теряется, и изображение немного деформируется. С каждым вращением деформация становится все более заметной.
Из-за этого, возможно, было бы лучше сохранить исходный спрайт в классе космического корабля и иметь другой спрайт, который будет обновляться каждый раз, когда космический корабль вращается.
Чтобы такой подход сработал, нам нужно знать угол, на который вращается космический корабль. Поскольку положение и скорость космического корабля уже являются векторами, имеет смысл использовать другой вектор для представления направления. К счастью, класс Vector2 можно очень легко повернуть, и результат не будет деформирован.
Давайте, для начала, создадим константный вектор, вызываемый в файле space_rocks/models.py. Мы будем использовать его немного позже:
UP = Vector2(0, -1)
Заметим, что ось y Pygame идет сверху вниз, поэтому отрицательное значение на самом деле указывает вверх:
Затем изменим класс космического корабля:
# models.py
class Spaceship(GameObject):
MANEUVERABILITY = 3
Значение MANEUVERABILITY(МАНЕВРЕННОСТЬ) определяет, насколько быстро может вращаться космический корабль. Мы уже говорили, что векторы в Pygame можно поворачивать, и это значение представляет угол в градусах, на который направление вашего космического корабля может поворачивать каждый кадр. Использование большего числа позволит вращать космический корабль быстрее, в то время как меньшее число позволит более точно контролировать вращение.
Далее добавим аттрибут direction(направление) в класс космического корабля, для чего изменим конструктор:
def __init__(self, position):
self.direction = Vector2(UP)
super().__init__(position, load_sprite("spaceship"), Vector2(0))
Вектор направления изначально будет таким же, как и вектор UP. Однако позже он будет изменен, поэтому нам необходимо создать его копию.
Затем создадим новый метод в классе Spaceship под названием rotate():
def rotate(self, clockwise=True):
sign = 1 if clockwise else -1
angle = self.MANEUVERABILITY * sign
self.direction.rotate_ip(angle)
Этот метод изменит направление, вращая его по часовой стрелке или против часовой стрелки. Метод rotate_ip() класса Vector2 поворачивает его на заданный угол в градусах. Длина вектора не изменяется во время этой операции.
Все, что осталось, - это обновить чертеж космического корабля. Для этого сначала нужно импортировать rotozoom, который отвечает за масштабирование и поворот изображений:
from pygame.math import Vector2
from pygame.transform import rotozoom
from utils import load_sprite
Затем переопределим метод draw() в классе Spaceship:
def draw(self, surface):
angle = self.direction.angle_to(UP)
rotated_surface = rotozoom(self.sprite, angle, 1.0)
rotated_surface_size = Vector2(rotated_surface.get_size())
blit_position = self.position - rotated_surface_size * 0.5
surface.blit(rotated_surface, blit_position)
Переменная angle использует метод angle_to() класса Vector2 для вычисления угла,на который необходимо повернуть один вектор, чтобы указать в том же направлении, что и другой вектор.
Переменная rotated_surface вращает спрайт с помощью rotozoom(). Он принимает исходное изображение, угол, на который оно должно быть повернуто, и масштаб, который должен быть применен к спрайту. В нашем случае масштаб равен 1.0.
Переменная blit_position содержит операцию rotated_surface_size * 0.5. Операция вернет вектор равный половине длины оригинала.
Последняя строка использует только что рассчитанную позицию blit для размещения изображения на экране.
Обработку ввода с клавиатуры.
Текущее состояние клавиатуры хранится в Pygame и может быть получено с помощью pygame.key.get_pressed(). Он возвращает словарь, в котором ключевые константы являются ключами, и значение True, если клавиша нажата, или False в противном случае.
Далее отредактируем файл space_rocks/game.py и обновим метод _handle_input() класса SpaceRocks. Константы, которые мы будем использовать для клавиш со стрелками, - это pygame.K_RIGHT и pygame.K_LEFT:
def _handle_input(self):
for event in pygame.event.get():
if event.type == pygame.QUIT or (
event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE
):
quit()
is_key_pressed = pygame.key.get_pressed()
if is_key_pressed[pygame.K_RIGHT]:
self.spaceship.rotate(clockwise=True)
elif is_key_pressed[pygame.K_LEFT]:
self.spaceship.rotate(clockwise=False)
Теперь наш корабль намного маневренее:
-
- Михаил Русаков
Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.