Как работать с изображениями. Модули image и transform
Ссылка на проект занятия (lesson 8.car_move.zip): https://github.com/selfedu-rus/pygame
На этом занятии мы с вами узнаем как использовать изображения в библиотеке Pygame. Здесь сразу следует знать одну вещь: родной формат графических данных для Pygame – это
bmp (от англ. Bitmap Picture)
Существуют и другие форматы представления изображений, но они применяются гораздо реже, чем PNG или JPEG.
Как же нам понять: какой формат данных выбирать? В действительности, все просто. Во-первых, нужно узнать: поддерживает ли Pygame на текущем устройстве какие-либо форматы, кроме BMP. Для этого следует выполнить функцию:
и если она вернет значение True (то есть 1), то в программе можно использовать PNG, JPEG, GIF и другие известные форматы. А, иначе, только BMP. Далее, при выборе между PNG и JPEG руководствуются следующим правилом:
Для фотореалистичных изображений лучше всего использовать JPEG, т.к. незначительные потери практически не скажутся на визуальном восприятии, но изображение будет хорошо сжато.
Для искусственных изображений с большим наличием однотонных областей (например, клип-арт) где четкость границ и однотонность заливки имеет первостепенное значение, лучше выбирать формат PNG. Кроме того, этот формат хранит альфа-канал для прозрачного фона (в JPEG такой возможности нет).
Программа ниже инициализирует Pygame и выводит в консоль значение функции get_extended():
Как видите, в данном случае Pygame возвращает 1, значит, можно использовать форматы PNG и JPEG.
Теперь загрузим в программе изображение машинки:
Здесь используется функция load(), в которой указывается путь к изображению (относительно исполняемого файла на Питоне) и на выходе она формирует поверхность с изображением машинки. Далее, мы можем отобразить содержимое этой поверхности уже знакомым нам способом:
После выполнения программы увидим в центре окна изображение машины:
Выглядит не очень. Добавим фон в виде изображения песка:
Стало лучше, но белый фон у машинки явно выделяется на фоне песка. Давайте укажем Pygame, что белый цвет следует воспринимать как прозрачный:
Теперь намного лучше. Однако, если имеется файл с альфа-каналом (прозрачным фоном), то оно будет сразу отображаться нужным образом:
Следующий важный момент, особенно при разработке динамических игр, перевод пикселей загруженных изображений в формат пикселей главной поверхности:
В этом случае, перерисовка поверхностей будет выполняться быстрее. Причем, обратите внимание, изображение в формате PNG с альфа-каналом преобразуется методом convert_alpha(), а не convert().
Вообще, эти строчки равносильны следующей операции:
То есть, методы convert() и convert_alpha() – это методы класса Surface, которые возвращают новую поверхность с измененным представлением пикселей. При этом прежняя поверхность остается без изменений. Например, если переписать последнюю строчку вот так:
то пиксели car_surf2 будут приведены к формату главной поверхности, а пиксели car_surf останутся прежними – без изменений.
Трансформация поверхностей
Предположим, что мы теперь хотели бы уменьшить масштаб изображения фона, чтобы песок был более мелкий. Это можно сделать с помощью модуля
содержащий различные функции трансформации поверхностей. Подробное их описание можно посмотреть на странице официальной документации:
Итак, мы воспользуемся функцией:
Здесь первый параметр – преобразуемая поверхность; (width, height) – ее новые значения ширины и высоты. В нашей программе вызовем эту функцию так:
Мы здесь уменьшаем размеры bg_surf в три раза по обеим координатам. Теперь, при отображении песок выглядит более мелким.
Давайте теперь сделаем так, чтобы машинка перемещалась при нажатии на курсорные клавиши. Для начала мы сформируем изображения машинки при движении вверх, влево, вправо и вниз:
Далее, определим переменные для хранения текущего вида машинки и ее скорости:
А внутри главного цикла будем выполнять перерисовку главного окна с текущим видом и положением машинки:
Смотрите, мы здесь проверяем: нажата ли какая-либо курсорная клавиша, и если срабатывает одно из условий, то переменная car ссылается на нужное изображение машинки и происходит изменение ее текущих координат на величину скорости. Далее, выполняется перерисовка главного окна и мы видим машинку с новым положением. Так происходит ее перемещение в пределах клиентского окна приложения.
Эти модули содержат множество полезных функций, с которыми подробнее можно ознакомиться на страницах документации:
Использование функций этих модулей достаточно просто и очевидно, поэтому нет смысла подробно о них говорить. Все делается по аналогии с рассмотренными на этом занятии.
Видео по теме
Что такое Pygame? Каркас приложения, FPS | Pygame #1
Рисование графических примитивов | Pygame #2
Как обрабатывать события от клавиатуры | Pygame #3
Как обрабатывать события от мыши | Pygame #4
Создание поверхностей (Surface) и их анимация. Метод blit | Pygame #5
Класс Rect. Его роль, свойства и методы | Pygame #6
Как рисовать текст различными шрифтами | Pygame #7
Как работать с изображениями. Модули image и transform | Pygame #8
Что такое спрайты и как с ними работать | Pygame #9
Как делать контроль столкновений | Pygame #10
Добавляем звук в игровой процесс. Модули mixer и music | Pygame #11
© 2021 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта
Стрелялка с Pygame №4: графика
Четвертая часть проект «Стрелялка с Pygame». Если пропустили, обязательно вернитесь и начините с первой части. В этот раз речь пойдет об использовании заготовленной графики.
В этой серии уроков будет создана полноценная игра на языке Python с помощью библиотеки Pygame. Она будет особенно интересна начинающим программистам, которые уже знакомы с основами языка и хотят углубить знания, а также узнать, что лежит в основе создания игр.
Выбор графики
В уроке, посвященном спрайтами, затрагивалась тема Opengameart.org — источника бесплатного арта для игр; и популярного местного автора, Kenney. Kenney создал набор арта, который прекрасно подойдет для этой стрелялки. Он называется «Space Shooter Pack». Найти его можно здесь:
Он включает массу качественных изображений с космическими кораблями, лазерами, астероидами и так далее.
Архив содержит несколько папок. Для этого проекта нужно папка PNG со всеми изображениями по отдельности. Для спрайтов пока что нужно только три, а также изображение звездного неба для фона. 


Изображения необходимо скопировать туда, где игра сможет их найти. Лучше всего создать новую папку в том же месте, где хранится код игры. Назовем ее «img».
Загрузка изображений
В верхней части программы необходимо определить местоположение папки img :
Прорисовка фона
Теперь можно приступать к загрузке фонового изображения. Загрузку ассетов необходимо производить до игрового цикла и кода запуска:
Теперь можно прорисовать фон в разделе Draw игрового цикла до прорисовки любого из спрайтов:
blit — это олдскульный термин из компьютерной графики, который обозначает прорисовку пикселей одного изображения на другом. В этом случае — прорисовку фона на экране. Теперь фон выглядит намного лучше:
Изображения спрайтов:
Теперь можно загрузить изображения спрайтов:
Вторая проблема — черный прямоугольник вокруг корабля. Чтобы это исправить, нужно назначить прозрачный цвет с помощью set_colorkey :
Если повторить то же самое для классов Bullet и Mob (хотя их размер менять не нужно), игра будет выглядеть намного лучше:
Итого
Теперь в игре есть графика, и это помогает заметить новую проблему: астероиды уничтожают корабль, даже когда не касаются его. В следующем уроке поработаем над тем, чтобы столкновения работали корректно.
PyGame — шпаргалка для использования
Основные модули пакета Pygame
| Модуль | Назначение |
|---|---|
| pygame.cdrom | Доступ к CD-приводам и управление ими |
| pygame.cursors | Загружает изображения курсора |
| pygame.display | Доступ к дисплею |
| pygame.draw | Рисует фигуры, линии и точки |
| pygame.event | Управление внешними событиями |
| pygame.font | Использует системные шрифты |
| pygame.image | Загружает и сохраняет изображение |
| pygame.joystick | Использует джойстики и аналогичные устройства |
| pygame.key | Считывает нажатия клавиш с клавиатуры |
| pygame.mixer | Загружает и воспроизводит мелодии |
| pygame.mouse | Управляет мышью |
| pygame.movie | Воспроизведение видеофайлов |
| pygame.music | Работает с музыкой и потоковым аудио |
| pygame.overlay | Доступ к расширенным видеоизображениям |
| pygame | Содержит функции Pygame высокого уровня |
| pygame.rect | Управляет прямоугольными областями |
| pygame.sndarray | Манипулирует звуковыми данными |
| pygame.sprite | Управление движущимися изображениями |
| pygame.surface | Управляет изображениями и экраном |
| pygame.surfarray | Манипулирует данными пикселей изображения |
| pygame.time | модуль pygame для управления временем и частотой кадров |
| pygame.transform | Изменение размера и перемещение изображений |
Окно Pygame
Цикл игры, выход из игры
Рисование базовых элементов
модуль pygame.draw
| pygame.draw.rect | нарисовать прямоугольную форму |
| pygame.draw.polygon | фигуру с любым количеством сторон |
| pygame.draw.circle | круг вокруг точки |
| pygame.draw.ellipse | нарисовать круглую форму внутри прямоугольника |
| pygame.draw.arc | нарисовать секцию эллипса |
| pygame.draw.line | нарисовать сегмент прямой линии |
| pygame.draw.lines | для рисования нескольких смежных отрезков |
| pygame.draw.aaline | рисовать тонкую линию |
| pygame.draw.aalines | нарисовать связанную последовательность сглаженных линий |
Загрузка изображения
Объект Rect
pygame.Rect
Pygame использует объекты Rect для хранения и манипулирования прямоугольными областями. Rect может быть создан из комбинации значений слева, сверху, ширины и высоты. Rect также могут быть созданы из объектов python, которые уже являются Rect или имеют атрибут с именем «rect».
Методы работы с Rect
| pygame.Rect.copy | Возвращает новый прямоугольник, имеющий ту же позицию и размер, что и оригинал. |
| pygame.Rect.move | Возвращает новый прямоугольник, перемещаемый данным смещением. Аргументы x и y могут быть любым целочисленным значением, положительным или отрицательным. |
| pygame.Rect.move_ip | То же, что и метод Rect.move (), но работает на месте. |
| pygame.Rect.inflate | увеличивать или уменьшать размер прямоугольника, на месте |
| pygame.Rect.inflate_ip | увеличивать или уменьшать размер прямоугольника, на месте |
| pygame.Rect.clamp | перемещает прямоугольник внутри другого |
| pygame.Rect.clamp_ip | перемещает прямоугольник внутри другого, на месте |
| pygame.Rect.clip | обрезает прямоугольник внутри другого |
| pygame.Rect.union | соединяет два прямоугольника в один |
| pygame.Rect.union_ip | соединяет два прямоугольника в один, на месте |
| pygame.Rect.unionall | объединение многих прямоугольников |
| pygame.Rect.unionall_ip | объединение многих прямоугольников, на месте |
| pygame.Rect.fit | изменить размер и переместить прямоугольник учмиывая соотношение сторон |
| pygame.Rect.normalize | корректировать отрицательные размеры |
| pygame.Rect.contains | проверить, находится ли один прямоугольник внутри другого |
| pygame.Rect.collidepoint | проверить, находится ли точка внутри прямоугольника |
| pygame.Rect.colliderect | тест, пересекаются ли два прямоугольника |
| pygame.Rect.collidelist | проверить, пересекается ли хоть один прямоугольник в списке |
| pygame.Rect.collidelistall | пересекаются ли все прямоугольники в списке |
| pygame.Rect.collidedict | проверить, если один прямоугольник в словаре пересекается |
| pygame.Rect.collidedictall | пересекаются ли все прямоугольники в словаре |
Обработка событий
Событие — это то, как Pygame сообщает о том, что что-то случилось за пределами кода программы. События создаются, например, при нажатии клавиш клавиатуры, мыши и размещаются в очереди, дожидаясь обработки.
Функция get в модуле pygame.event возвращает последнее событие, ожидающее в очереди и удаляет его из очереди.
Объект event
Модуль pygame.event для обработки очереди событий
| pygame.event.pump | Если вы не используете другие функции событий в своей игре, вы должны вызвать pygame.event.pump (), чтобы позволить pygame обрабатывать внутренние действия |
| pygame.event.get | получает события из очереди |
| pygame.event.poll | получить одно событие из очереди |
| pygame.event.wait | ждёт одиночного события из очереди |
| pygame.event.peek | проверить, ждут ли очереди события определённого типа |
| pygame.event.clear | удалить все события из очереди |
| pygame.event.event_name | возвращает имя для типа события. Строка находится в стиле WordCap |
| pygame.event.set_blocked | проверяет, какие события не разрешены в очереди |
| pygame.event.set_allowed | проверяет, какие события разрешены в очереди |
| pygame.event.get_blocked | проверить, заблокирован ли тип события из очереди |
| pygame.event.set_grab | проверяет совместное использование устройств ввода с другими приложениями |
| pygame.event.get_grab | проверить, работает ли программа на устройствах ввода данных |
| pygame.event.post | поместить новое событие в очередь |
| pygame.event.Event | создать новый объект события |
| pygame.event.EventType | Объект Python, представляющий событие SDL. Экземпляры пользовательских событий создаются с вызовом функции Event. Тип EventType не может быть напрямую вызван. Экземпляры EventType поддерживают назначение и удаление атрибутов. |
Pygame отслеживает все сообщения о событиях через очередь событий. Процедуры в этом модуле помогают управлять этой очередью событий. Входная очередь сильно зависит от модуля отображения (display) pygame. Если дисплей не был инициализирован и видеорежим не установлен, очередь событий не будет работать.
Существует множество способов доступа к очереди событий. Просто проверять существование событий, захватывать их непосредственно из стека.
Модуль pygame.mouse для работы с мышью
| pygame.mouse.get_pressed | получить состояние кнопок мыши |
| pygame.mouse.get_pos | получить позицию курсора мыши |
| pygame.mouse.get_rel | получить количество движений мыши |
| pygame.mouse.set_pos | установить позицию курсора мыши |
| pygame.mouse.set_visible | скрыть или показать курсор мыши |
| pygame.mouse.get_focused | проверяет, принимает ли дисплей ввод мыши |
| pygame.mouse.set_cursor | установить изображение для курсора мыши |
| pygame.mouse.get_cursor | получить изображение для курсора мыши |
Функции мыши можно использовать для получения текущего состояния устройства мышь. Эти функции также могут изменять курсор мыши.
Пример. Нарисовать курсор под текущей позицией мыши.
Определить какая кнопка была нажата на мышке можно используя значение event.button:
Пример. Перемещать картинку курсором мыши.
Клавиатура
Модуль pygame.key
Этот модуль содержит функции для работы с клавиатурой.Очередь событий получает события pygame.KEYDOWN и pygame.KEYUP при нажатии и отпускании клавиш клавиатуры.
Оба события имеют ключевой атрибут, который представляет собой целочисленный идентификатор, представляющий каждую клавишу на клавиатуре.Событие pygame.KEYDOWN имеет дополнительные атрибуты: unicode и scancode. unicode представляет собой одну символьную строку, которая соответствует введённому символу. Scancode представляет собой код для конкретной платформы.
Получить код клавиши:
Существует много клавиатурных констант, они используются для представления клавиш на клавиатуре. Ниже приведен список всех клавиатурных констант:
| KeyASCII | ASCII | CommonName |
|---|---|---|
| K_BACKSPACE | \b | backspace |
| K_TAB | \t | tab |
| K_CLEAR | clear | |
| K_RETURN | \r | return |
| K_PAUSE | pause | |
| K_ESCAPE | ^[ | escape |
| K_SPACE | space | |
| K_EXCLAIM | ! | exclaim |
| K_QUOTEDBL | « | quotedbl |
| K_HASH | # | hash |
| K_DOLLAR | $ | dollar |
| K_AMPERSAND | & | ampersand |
| K_QUOTE | quote | |
| K_LEFTPAREN | ( | leftparenthesis |
| K_RIGHTPAREN | ) | rightparenthesis |
| K_ASTERISK | * | asterisk |
| K_PLUS | + | plussign |
| K_COMMA | , | comma |
| K_MINUS | — | minussign |
| K_PERIOD | . | period |
| K_SLASH | / | forwardslash |
| K_0 | 0 | 0 |
| K_1 | 1 | 1 |
| K_2 | 2 | 2 |
| K_3 | 3 | 3 |
| K_4 | 4 | 4 |
| K_5 | 5 | 5 |
| K_6 | 6 | 6 |
| K_7 | 7 | 7 |
| K_8 | 8 | 8 |
| K_9 | 9 | 9 |
| K_COLON | : | colon |
| K_SEMICOLON | ; | semicolon |
| K_LESS | less-thansign | |
| K_EQUALS | = | equalssign |
| K_GREATER | > | greater-thansign |
| K_QUESTION | ? | questionmark |
| K_AT | @ | at |
| K_LEFTBRACKET | [ | leftbracket |
| K_BACKSLASH | \ | backslash |
| K_RIGHTBRACKET | ] | rightbracket |
| K_CARET | ^ | caret |
| K_UNDERSCORE | _ | underscore |
| K_BACKQUOTE | ` | grave |
| K_a | a | a |
| K_b | b | b |
| K_c | c | c |
| K_d | d | d |
| K_e | e | e |
| K_f | f | f |
| K_g | g | g |
| K_h | h | h |
| K_i | i | i |
| K_j | j | j |
| K_k | k | k |
| K_l | l | l |
| K_m | m | m |
| K_n | n | n |
| K_o | o | o |
| K_p | p | p |
| K_q | q | q |
| K_r | r | r |
| K_s | s | s |
| K_t | t | t |
| K_u | u | u |
| K_v | v | v |
| K_w | w | w |
| K_x | x | x |
| K_y | y | y |
| K_z | z | z |
| K_DELETE | delete | |
| K_KP0 | keypad0 | |
| K_KP1 | keypad1 | |
| K_KP2 | keypad2 | |
| K_KP3 | keypad3 | |
| K_KP4 | keypad4 | |
| K_KP5 | keypad5 | |
| K_KP6 | keypad6 | |
| K_KP7 | keypad7 | |
| K_KP8 | keypad8 | |
| K_KP9 | keypad9 | |
| K_KP_PERIOD | . | keypadperiod |
| K_KP_DIVIDE | / | keypaddivide |
| K_KP_MULTIPLY | * | keypadmultiply |
| K_KP_MINUS | — | keypadminus |
| K_KP_PLUS | + | keypadplus |
| K_KP_ENTER | \r | keypadenter |
| K_KP_EQUALS | = | keypadequals |
| K_UP | uparrow | |
| K_DOWN | downarrow | |
| K_RIGHT | rightarrow | |
| K_LEFT | leftarrow | |
| K_INSERT | insert | |
| K_HOME | home | |
| K_END | end | |
| K_PAGEUP | pageup | |
| K_PAGEDOWN | pagedown | |
| K_F1 | F1 | |
| K_F2 | F2 | |
| K_F3 | F3 | |
| K_F4 | F4 | |
| K_F5 | F5 | |
| K_F6 | F6 | |
| K_F7 | F7 | |
| K_F8 | F8 | |
| K_F9 | F9 | |
| K_F10 | F10 | |
| K_F11 | F11 | |
| K_F12 | F12 | |
| K_F13 | F13 | |
| K_F14 | F14 | |
| K_F15 | F15 | |
| K_NUMLOCK | numlock | |
| K_CAPSLOCK | capslock | |
| K_SCROLLOCK | scrollock | |
| K_RSHIFT | rightshift | |
| K_LSHIFT | leftshift | |
| K_RCTRL | rightcontrol | |
| K_LCTRL | leftcontrol | |
| K_RALT | rightalt | |
| K_LALT | leftalt | |
| K_RMETA | rightmeta | |
| K_LMETA | leftmeta | |
| K_LSUPER | leftWindowskey | |
| K_RSUPER | rightWindowskey | |
| K_MODE | modeshift | |
| K_HELP | help | |
| K_PRINT | printscreen | |
| K_SYSREQ | sysrq | |
| K_BREAK | break | |
| K_MENU | menu | |
| K_POWER | power | |
| K_EURO | Euro |
Направленное движение с помощью клавиш
Можно перемещать изображение на экране с клавиатуры, назначая клавиши для перемещений: вверх, вниз, влево, вправо.
Создать картинку, например:
Проверить очередь событий:
Проверить, является ли полученное событие нажатием на клавиши со стрелками:
Если — да, то получмить код нажатой клавиши и сформировать новые координаты для картинки:
И нарисовать картинку в новом месте:
Объект Surface
pygame.Surface — объект pygame для представления изображений
Наложение поверхностей, прозрачность.
Управление временем
Модуль pygame.time содержит объект Clock, который можно использовать для отслеживания
времени. Чтобы создать объект типа: время, вызывается конструктор pygame.time.Clock:
clock = pygame.time.Clock()
Когда создан объект clock, можно вызвать его функцию tick один раз за кадр,
которая возвращает время, прошедшее со времени предыдущего вызова в миллисекундах:
time_passed = clock.tick ()
Функция tick может использовать необязательный параметр для установления максимальной частоты кадров. Этот параметр нужен, если игра запущена на рабочем компьютере и необходимо контролировать, чтобы она не использовала всю его вычислительная мощность на 100%:
# Игра будет работать со скоростью не более 30 кадров в секунду
time_passed = clock.tick (30)
Звуки
Загружаем звуковой файл в формате *.wav
sound = pygame.mixer.Sound(«sound.wav»)
(загружаем до игрового цикла, т.к. это очень долгая операция)
Столкновения (collisions)
При написании игр часто возникает необходимость проверять взаимное расположение объектов на экране, отслеживать моменты их столкновений, пересечений.
Эта задача может быть реализована разными способами.
Например, используя объект Rect
Или используя поверхности — surface



















