Модуль pygame.transform. Трансформации поверхностей
Часто в играх требуется изменять изображение игрового персонажа. Одни метаморфозы предполагают загрузки немного иной картинки. Например, при анимации движения ног, изменения выражения лица. Другие проще, не меняют детали исходного изображения и связаны с поворотами, изменением размера, затенением и др.
Например, жук в игре может ползать вверх и вниз. Его голова всегда должна быть повернута по направлению движения. Это значит, надо запрограммировать переворот изображения по вертикали или поворот на 180 градусов.
Для таких целей в Pygame предназначен модуль pygame.transform
, который содержит функции для изменения поверхностей. Некоторые трансформации (например, изменение размера) приводят к ухудшению изображения из-за потери части пикселей. В таких случаях следует не терять исходную поверхность и повторные трансформации выполнять от нее. Обычно функции модуля transform
возвращают новую поверхность, а не изменяют переданный им первым аргументом экземпляр Surface
.
В этом уроке будут упомянуты не все функции модуля transform
, а наиболее используемые и простые. Другие более специфичны и предполагают знания, как вычислительная машина работает с графикой.
Проверять работу функций будем в рамках нижеследующего шаблона, в котором на главной поверхности сначала прорисовывается исходное изображение:
import pygame import sys W = 800 H = 600 BG = (100, 170, 220) # голубой цвет фона sc = pygame.display.set_mode((W, H)) sc.fill(BG) # отрисовываем исходную поверхность-изображение (собака в центре окна) origin_surf = pygame.image.load('dog.png').convert_alpha() origin_rect = origin_surf.get_rect(center=(W/2, H/2)) sc.blit(origin_surf, origin_rect) pygame.display.update() # ждем 1 секунду перед изменением pygame.time.wait(1000) # ЗДЕСЬ ВЫПОЛНЯЕМ ТРАНСФОРМАЦИЮ new_surf = origin_surf # отрисовываем новую поверхность-изображение sc.fill(BG) new_rect = new_surf.get_rect(center=(W/2, H/2)) sc.blit(new_surf, new_rect) pygame.display.update() while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() pygame.time.delay(1000)
Функция flip
переворачивает Surface
по горизонтали и вертикали. Передается поверхность и булевыми значениями оси переворота.
new_surf = pygame.transform.flip(origin_surf, True, False)
В данном случае собака повернется слева направо. Если бы третий аргумент был True
, то она также перевернулась бы с ног на голову. Так как flip
не приводит к потере качества изображения, то возвращаемую функцией новую поверхность можно присваивать той же переменной, с которой была связана исходная. Это удобно, если в процессе игры при нажатии определенных клавиш "герой" должен разворачиваться туда-сюда (реализуется в основном цикле игры). Кроме того, не обязательно пересоздавать экземпляр Rect
. При таких переворотах занимаемая поверхностью прямоугольная область не меняется.
Функция rotate
вращает поверхность либо против часовой стрелки (положительное значение градусов), либо по часовой (отрицательные значения).
new_surf = pygame.transform.rotate(origin_surf, -45)
Если поверхность поворачивается не с шагом в 90 градусов, то содержащаяся в нем картинка может увеличиться или ухудшиться качество изображения.
С помощью scale
меняют размер через ширину и высоту:
new_surf = pygame.transform.scale(origin_surf, (origin_surf.get_width()/2, origin_surf.get_height()/2))
При этом можно изменить пропорции изображения (вытянуть его вдоль или поперек), если менять размер по одной оси не в такое же количество раз, как по другой.
Подобного нюанса лишена функция scale_by
, которой передается коэффициент-множитель размера. Например, значение 2 увеличит, а 0.5 уменьшит изображение в два раза.
new_surf = pygame.transform.scale_by(origin_surf, 1.15)
Обе функции приводят к ухудшению качества изображения. Немного лучший результат могут дать функции smoothscale
и smoothscale_by
, которые подобны двум предыдущим.
Одновременно повернуть и масштабировать позволяет функция rotozoom
. Вторым аргументом ей передаются градусы поворота, третьим ‒ во сколько раз менять размер.
new_surf = pygame.transform.rotozoom(origin_surf, -35, 0.9)
Функция laplacian
оставляет только края изображения:
new_surf = pygame.transform.laplacian(origin_surf)
Функция grayscale
замещает по определенному алгоритму цвета исходной картинки на оттенки серого:
pygame.transform.grayscale(origin_surf)
Функция chop
удаляет часть, заданную с помощью экземпляра Rect
(его аргументы задаются относительно картинки, а не главной поверхности). После этого оставшиеся части объединяются.
new_surf = pygame.transform.chop(origin_surf, pygame.Rect((100, 0, 30, 0)))
Здесь вырезается вертикальная часть шириной 30 пикселей, начиная с координаты 100 по оси x.
Практическая работа
Допустим, у вас есть такое изображение вида сверху машины:
Напишите программу управления ее движением с помощью стрелок клавиатуры (вверх, вниз, влево, вправо) так, чтобы объект всегда двигался головой вперед.