Модуль 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.

Практическая работа

Допустим, у вас есть такое изображение вида сверху машины:

Напишите программу управления ее движением с помощью стрелок клавиатуры (вверх, вниз, влево, вправо) так, чтобы объект всегда двигался головой вперед.

Pygame. Введение в разработку игр на Python




Все разделы сайта