Improve Article
Save Article
Improve Article
Save Article
In this article, we are going to see how to Rotate and Scale the image. Image Scaling refers to the resizing of the original image and Image Rotation refers to the turning of an image with some angle. Rotations in the coordinate plane are counterclockwise. Let’s proceed with the methods used and the complete code to perform these tasks.
Scaling the Image
To scale the image we use the pygame.transform.scale(image, DEFAULT_IMAGE_SIZE) method where we pass the image that we are going to scale and the default image size that we will set manually according to our need.
Example:
Image Used:
Python3
import
pygame
pygame.init()
size
=
width,height
=
600
,
600
screen
=
pygame.display.set_mode(size)
clock
=
pygame.time.Clock()
image
=
pygame.image.load(
'gfg.png'
)
DEFAULT_IMAGE_SIZE
=
(
200
,
200
)
image
=
pygame.transform.scale(image, DEFAULT_IMAGE_SIZE)
DEFAULT_IMAGE_POSITION
=
(
200
,
200
)
running
=
False
while
not
running:
for
event
in
pygame.event.get():
if
event.
type
=
=
pygame.QUIT:
running
=
True
screen.fill((
0
,
0
,
0
))
screen.blit(image, DEFAULT_IMAGE_POSITION)
pygame.display.flip()
clock.tick(
30
)
Output:
Rotating the Image
To rotate the image we use the pygame.transform.rotate(image, degree) method where we pass the image that we are going to rotate and the degree by which rotation is to be done.
Example:
Python3
import
pygame
pygame.init()
size
=
width,height
=
600
,
600
screen
=
pygame.display.set_mode(size)
clock
=
pygame.time.Clock()
image
=
pygame.image.load(
'gfg.png'
)
DEFAULT_IMAGE_SIZE
=
(
200
,
200
)
image
=
pygame.transform.rotate(image,
180
)
DEFAULT_IMAGE_POSITION
=
(
200
,
200
)
running
=
False
while
not
running:
for
event
in
pygame.event.get():
if
event.
type
=
=
pygame.QUIT:
running
=
True
screen.fill((
0
,
0
,
0
))
screen.blit(image, DEFAULT_IMAGE_POSITION)
pygame.display.flip()
clock.tick(
30
)
Output:
Rotating and Scaling the Image
Let us see how to perform the Scaling and Rotation of an image given. We will set the default image size that is agreeable and the default image position where we want to see our image on the window screen. The same methods that are explained above will be used for scaling and rotation the image.
Example:
Python3
import
pygame
pygame.init()
size
=
width,height
=
600
,
600
screen
=
pygame.display.set_mode(size)
clock
=
pygame.time.Clock()
image
=
pygame.image.load(
'gfg.png'
)
DEFAULT_IMAGE_SIZE
=
(
200
,
200
)
image
=
pygame.transform.scale(image, DEFAULT_IMAGE_SIZE)
image
=
pygame.transform.rotate(image,
90
)
DEFAULT_IMAGE_POSITION
=
(
200
,
200
)
running
=
False
while
not
running:
for
event
in
pygame.event.get():
if
event.
type
=
=
pygame.QUIT:
running
=
True
screen.fill((
0
,
0
,
0
))
screen.blit(image, DEFAULT_IMAGE_POSITION)
pygame.display.flip()
clock.tick(
30
)
Output:
Improve Article
Save Article
Improve Article
Save Article
In this article, we are going to see how to Rotate and Scale the image. Image Scaling refers to the resizing of the original image and Image Rotation refers to the turning of an image with some angle. Rotations in the coordinate plane are counterclockwise. Let’s proceed with the methods used and the complete code to perform these tasks.
Scaling the Image
To scale the image we use the pygame.transform.scale(image, DEFAULT_IMAGE_SIZE) method where we pass the image that we are going to scale and the default image size that we will set manually according to our need.
Example:
Image Used:
Python3
import
pygame
pygame.init()
size
=
width,height
=
600
,
600
screen
=
pygame.display.set_mode(size)
clock
=
pygame.time.Clock()
image
=
pygame.image.load(
'gfg.png'
)
DEFAULT_IMAGE_SIZE
=
(
200
,
200
)
image
=
pygame.transform.scale(image, DEFAULT_IMAGE_SIZE)
DEFAULT_IMAGE_POSITION
=
(
200
,
200
)
running
=
False
while
not
running:
for
event
in
pygame.event.get():
if
event.
type
=
=
pygame.QUIT:
running
=
True
screen.fill((
0
,
0
,
0
))
screen.blit(image, DEFAULT_IMAGE_POSITION)
pygame.display.flip()
clock.tick(
30
)
Output:
Rotating the Image
To rotate the image we use the pygame.transform.rotate(image, degree) method where we pass the image that we are going to rotate and the degree by which rotation is to be done.
Example:
Python3
import
pygame
pygame.init()
size
=
width,height
=
600
,
600
screen
=
pygame.display.set_mode(size)
clock
=
pygame.time.Clock()
image
=
pygame.image.load(
'gfg.png'
)
DEFAULT_IMAGE_SIZE
=
(
200
,
200
)
image
=
pygame.transform.rotate(image,
180
)
DEFAULT_IMAGE_POSITION
=
(
200
,
200
)
running
=
False
while
not
running:
for
event
in
pygame.event.get():
if
event.
type
=
=
pygame.QUIT:
running
=
True
screen.fill((
0
,
0
,
0
))
screen.blit(image, DEFAULT_IMAGE_POSITION)
pygame.display.flip()
clock.tick(
30
)
Output:
Rotating and Scaling the Image
Let us see how to perform the Scaling and Rotation of an image given. We will set the default image size that is agreeable and the default image position where we want to see our image on the window screen. The same methods that are explained above will be used for scaling and rotation the image.
Example:
Python3
import
pygame
pygame.init()
size
=
width,height
=
600
,
600
screen
=
pygame.display.set_mode(size)
clock
=
pygame.time.Clock()
image
=
pygame.image.load(
'gfg.png'
)
DEFAULT_IMAGE_SIZE
=
(
200
,
200
)
image
=
pygame.transform.scale(image, DEFAULT_IMAGE_SIZE)
image
=
pygame.transform.rotate(image,
90
)
DEFAULT_IMAGE_POSITION
=
(
200
,
200
)
running
=
False
while
not
running:
for
event
in
pygame.event.get():
if
event.
type
=
=
pygame.QUIT:
running
=
True
screen.fill((
0
,
0
,
0
))
screen.blit(image, DEFAULT_IMAGE_POSITION)
pygame.display.flip()
clock.tick(
30
)
Output:
- Pygame
- Что такое Pygame? Каркас приложения, FPS
- Рисование графических примитивов
- Как обрабатывать события от клавиатуры
- Как обрабатывать события от мыши
- Создание поверхностей (Surface), их анимация, метод blit
- Класс Rect. Его роль, свойства и методы
- Как рисовать текст различными шрифтами
- Как работать с изображениями. Модули image и transform
- Что такое спрайты и как с ними работать
- Как делать контроль столкновений
- Добавляем звук в игровой процесс. Модули mixer и music
- Главная
- Модули
- Pygame
Ссылка на проект занятия (lesson 8.car_move.zip): https://github.com/selfedu-rus/pygame
На этом занятии
мы с вами узнаем как использовать изображения в библиотеке Pygame. Здесь сразу
следует знать одну вещь: родной формат графических данных для Pygame – это
bmp (от
англ. Bitmap Picture)
то есть, не
сжатые наборы пикселей изображения. Такие графические файлы занимают много
места по сравнению с другими распространенными форматами:
-
PNG (расширение png) – используется
сжатие без потерь с использованием алгоритмов ДИКМ и LZW; -
JPEG (расширение jpg) – используется
сжатие с потерями (алгоритм ДКП – аналог Фурье-преобразования с косинусными
гармониками).
Существуют и
другие форматы представления изображений, но они применяются гораздо реже, чем PNG или JPEG.
Как же нам
понять: какой формат данных выбирать? В действительности, все просто.
Во-первых, нужно узнать: поддерживает ли Pygame на текущем
устройстве какие-либо форматы, кроме BMP. Для этого следует выполнить
функцию:
pygame.image.get_extended()
и если она
вернет значение True (то есть 1), то в программе можно использовать PNG, JPEG, GIF и другие
известные форматы. А, иначе, только BMP. Далее, при выборе между PNG и JPEG руководствуются
следующим правилом:
Для
фотореалистичных изображений лучше всего использовать JPEG, т.к.
незначительные потери практически не скажутся на визуальном восприятии, но
изображение будет хорошо сжато.
Для
искусственных изображений с большим наличием однотонных областей (например,
клип-арт) где четкость границ и однотонность заливки имеет первостепенное
значение, лучше выбирать формат PNG. Кроме того,
этот формат хранит альфа-канал для прозрачного фона (в JPEG такой
возможности нет).
Программа ниже
инициализирует Pygame и выводит в консоль значение функции
get_extended():
import pygame pygame.init() W, H = 600, 400 sc = pygame.display.set_mode((600, 400)) pygame.display.set_caption("Изображения") pygame.display.set_icon(pygame.image.load("app.bmp")) clock = pygame.time.Clock() FPS = 60 WHITE = (255, 255, 255) RED = (255, 0, 0) YELLOW = (239, 228, 176) print( pygame.image.get_extended() ) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: exit() clock.tick(FPS)
Как видите, в данном
случае Pygame возвращает 1,
значит, можно использовать форматы PNG и JPEG.
Теперь загрузим
в программе изображение машинки:
car_surf = pygame.image.load("images/car.bmp")
Здесь
используется функция load(), в которой указывается путь к
изображению (относительно исполняемого файла на Питоне) и на выходе она
формирует поверхность с изображением машинки. Далее, мы можем отобразить
содержимое этой поверхности уже знакомым нам способом:
car_rect = car_surf.get_rect(center=(W//2, H//2)) sc.blit(car_surf, car_rect) pygame.display.update()
После выполнения
программы увидим в центре окна изображение машины:
Выглядит не
очень. Добавим фон в виде изображения песка:
bg_surf = pygame.image.load("images/sand.jpg") sc.blit(bg_surf, (0, 0))
Стало лучше, но
белый фон у машинки явно выделяется на фоне песка. Давайте укажем Pygame, что белый цвет
следует воспринимать как прозрачный:
car_surf.set_colorkey((255, 255, 255))
Теперь намного
лучше. Однако, если имеется файл с альфа-каналом (прозрачным фоном), то оно
будет сразу отображаться нужным образом:
finish_surf = pygame.image.load("images/finish.png") sc.blit(finish_surf, (0, 0))
Следующий важный
момент, особенно при разработке динамических игр, перевод пикселей загруженных
изображений в формат пикселей главной поверхности:
car_surf = pygame.image.load("images/car.bmp").convert() finish_surf = pygame.image.load("images/finish.png").convert_alpha() bg_surf = pygame.image.load("images/sand.jpg").convert()
В этом случае,
перерисовка поверхностей будет выполняться быстрее. Причем, обратите внимание,
изображение в формате PNG с альфа-каналом преобразуется методом convert_alpha(), а не convert().
Вообще, эти строчки
равносильны следующей операции:
car_surf = pygame.image.load("images/car.bmp") car_surf = car_surf.convert()
То есть, методы convert() и convert_alpha() – это методы
класса Surface, которые
возвращают новую поверхность с измененным представлением пикселей. При этом
прежняя поверхность остается без изменений. Например, если переписать последнюю
строчку вот так:
car_surf2 = car_surf.convert()
то пиксели car_surf2 будут
приведены к формату главной поверхности, а пиксели car_surf останутся
прежними – без изменений.
Трансформация поверхностей
Предположим, что
мы теперь хотели бы уменьшить масштаб изображения фона, чтобы песок был более
мелкий. Это можно сделать с помощью модуля
pygame.transform
содержащий
различные функции трансформации поверхностей. Подробное их описание можно
посмотреть на странице официальной документации:
https://www.pygame.org/docs/ref/transform.html
Итак, мы
воспользуемся функцией:
pygame.transform.scale(Surface, (width, height), DestSurface = None) -> Surface
Здесь первый
параметр – преобразуемая поверхность; (width, height) – ее новые значения
ширины и высоты. В нашей программе вызовем эту функцию так:
bg_surf = pygame.transform.scale(bg_surf, (bg_surf.get_width()//3, bg_surf.get_height()//3))
Мы здесь
уменьшаем размеры bg_surf в три раза по обеим координатам.
Теперь, при отображении песок выглядит более мелким.
Давайте теперь
сделаем так, чтобы машинка перемещалась при нажатии на курсорные клавиши. Для
начала мы сформируем изображения машинки при движении вверх, влево, вправо и
вниз:
car_up = car_surf car_down = pygame.transform.flip(car_surf, 0, 1) car_left = pygame.transform.rotate(car_surf, 90) car_right = pygame.transform.rotate(car_surf, -90)
Далее, определим
переменные для хранения текущего вида машинки и ее скорости:
А внутри
главного цикла будем выполнять перерисовку главного окна с текущим видом и
положением машинки:
while True: for event in pygame.event.get(): if event.type == pygame.QUIT: exit() bt = pygame.key.get_pressed() if bt[pygame.K_LEFT]: car = car_left car_rect.x -= speed if car_rect.x < 0: car_rect.x = 0 elif bt[pygame.K_RIGHT]: car = car_right car_rect.x += speed if car_rect.x > W-car_rect.height: car_rect.x = W-car_rect.height elif bt[pygame.K_UP]: car = car_up car_rect.y -= speed if car_rect.y < 0: car_rect.y = 0 elif bt[pygame.K_DOWN]: car = car_down car_rect.y += speed if car_rect.y > H-car_rect.height: car_rect.y = H-car_rect.height sc.blit(bg_surf, (0, 0)) sc.blit(finish_surf, (0, 0)) sc.blit(car, car_rect) pygame.display.update() clock.tick(FPS)
Смотрите, мы
здесь проверяем: нажата ли какая-либо курсорная клавиша, и если срабатывает
одно из условий, то переменная car ссылается на нужное изображение машинки
и происходит изменение ее текущих координат на величину скорости. Далее,
выполняется перерисовка главного окна и мы видим машинку с новым положением.
Так происходит ее перемещение в пределах клиентского окна приложения.
Фактически мы с
вами рассмотрели основы работы с изображениями в Pygame с помощью двух
модулей:
-
pygame.image –
загрузка/сохранение изображений; -
pygame.transform
– трансформация
поверхностей.
Эти модули
содержат множество полезных функций, с которыми подробнее можно ознакомиться на
страницах документации:
https://www.pygame.org/docs/ref/transform.html
https://www.pygame.org/docs/ref/image.html
Использование
функций этих модулей достаточно просто и очевидно, поэтому нет смысла подробно
о них говорить. Все делается по аналогии с рассмотренными на этом занятии.
Видео по теме
- Предыдущая
- Следующая
Загрузка и сохранение изображений в Pygame
Функция load() модуля pygame.image загружает изображение и создает экземпляр Surface, на котором отображено это изображение. В load() передается имя файла. «Родным» форматом является BMP, однако если функция pygame.image.get_extended() возвращает истину, то можно загружать ряд других форматов: PNG, GIF, JPG и др.
import pygame as pg import sys W = 400 H = 300 sc = pg.display.set_mode((W, H)) sc.fill((100, 150, 200)) dog_surf = pg.image.load('dog.bmp') dog_rect = dog_surf.get_rect( bottomright=(W, H)) sc.blit(dog_surf, dog_rect) pg.display.update() while 1: for i in pg.event.get(): if i.type == pg.QUIT: sys.exit() pg.time.delay(20)
Если у изображения нет прозрачного слоя, но он необходим, то следует воспользоваться методом set_colorkey() класса Surface:
dog_surf = pg.image.load('dog.bmp') dog_surf.set_colorkey((255, 255, 255))
Все пиксели, цвет которых совпадает с переданным в set_colorkey() значением, станут прозрачными.
У формата PNG с альфа-каналом (когда для точек можно настраивать степень прозрачности; обычно устанавливается полностью прозрачный фон) таких проблем нет:
sun_surf = pg.image.load('sun.png') sun_rect = sun_surf.get_rect() sc.blit(sun_surf, sun_rect)
Ко всем экземплярам Surface рекомендуется применять метод convert(), который, если не передавать аргументы, переводит формат кодирования пикселей поверхности в формат кодирования пикселей главной поверхности. При выполнении игры это ускоряет отрисовку поверхностей.
Если поверхность была создана на базе изображения с альфа-каналом, то вместо convert() надо использовать метод convert_alpha(), так как первый удаляет прозрачные пиксели (вместо них будет черный цвет). Таким образом, код загрузки и обработки изображений разных форматов должен выглядеть примерно так:
dog_surf = pg.image.load( 'dog.bmp').convert() sun_surf = pg.image.load( 'sun.png').convert_alpha()
Что по смыслу равносильно:
... dog_surf = pg.image.load('dog.bmp') dog_surf = dog_surf.convert() ...
Метод convert() возвращает новую, конвертированную, поверхность. Он не изменяет ту, к которой применяется.
В модуле pygame.image есть функция save(), которая позволяет сохранять переданную ей поверхность (не обязательно главную) в формат BMP, TGA, PNG, JPEG. Пример:
while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() elif i.type == pygame.KEYUP and i.key == pygame.K_s: pygame.image.save(sc, 'day.png') pygame.time.delay(20)
Изменение поверхностей
Модуль pygame.transform содержит функции для изменения поверхностей. Некоторые трансформации (например, изменение размера) приводят к ухудшению изображения из-за потери части пикселей. В таких случаях надо сохранять исходную поверхность и выполнять трансформации от нее.
Функции модуля transform, которые изменяют поверхности, возвращают новые. Первым аргументом им передается исходный Surface. Ниже приведены примеры использования наиболее востребованных функций.
Функция flip() переворачивает Surface по горизонтали и вертикали, к потери качества не приводит. Указывается поверхность и булевыми значениями оси переворота.
import pygame import sys sc = pygame.display.set_mode((400, 300)) sc.fill((100, 150, 200)) dog_surf = pygame.image.load( 'dog.bmp').convert() dog_surf.set_colorkey( (255, 255, 255)) dog_rect = dog_surf.get_rect( center=(200, 150)) sc.blit(dog_surf, dog_rect) pygame.display.update() while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() elif i.type == pygame.KEYUP and i.key == pygame.K_f: # собака перевернется # слева направо flip = pygame.transform.flip( dog_surf, True, False) sc.fill((100, 150, 200)) sc.blit(flip, dog_rect) pygame.display.update(dog_rect) pygame.time.delay(20)
Поворот и изменение размера:
import pygame import sys sc = pygame.display.set_mode((400, 300)) sc.fill((100, 150, 200)) dog_surf = pygame.image.load( 'dog.bmp').convert() dog_surf.set_colorkey( (255, 255, 255)) dog_rect = dog_surf.get_rect( center=(200, 150)) sc.blit(dog_surf, dog_rect) pygame.display.update() # ждем 1 секунду перед изменением pygame.time.wait(1000) sc.fill((100, 150, 200)) # уменьшаем в два раза scale = pygame.transform.scale( dog_surf, (dog_surf.get_width() // 2, dog_surf.get_height() // 2)) scale_rect = scale.get_rect( center=(200, 150)) sc.blit(scale, scale_rect) pygame.display.update(dog_rect) pygame.time.wait(1000) sc.fill((100, 150, 200)) # поворачиваем на 45 градусов rot = pygame.transform.rotate( dog_surf, 45) rot_rect = rot.get_rect( center=(200, 150)) sc.blit(rot, rot_rect) pygame.display.update() while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() pygame.time.delay(20)
Практическая работа
Допустим, у вас есть такое изображение вида сверху машины:
Напишите программу управления ее движением с помощью стрелок клавиатуры (вверх, вниз, влево, вправо) так, чтобы объект всегда двигался головой вперед.
Курс с примерами решений практических работ:
pdf-версия, android-приложение
python #pygame
#python #pygame
Вопрос:
Есть изображение, которое я импортирую :
look_1 = pygame.image.load('datapnglook1.png').convert_alpha()
И то, что я пытался уменьшить его размер, было следующим :
pygame.transform.scale()
Но, похоже, это неправильный способ сделать это.
Комментарии:
1.
pygame.transform.scale()
правильно. Какие аргументы вы передали?
Ответ №1:
Вы можете либо использовать pygame.transform.scale
или smoothscale
и передать новую ширину и высоту поверхности, либо pygame.transform.rotozoom
и передать значение с плавающей точкой, которое будет умножено на текущее разрешение.
import sys
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
IMAGE = pg.Surface((100, 60))
IMAGE.fill(pg.Color('sienna2'))
pg.draw.circle(IMAGE, pg.Color('royalblue2'), (50, 30), 20)
# New width and height will be (50, 30).
IMAGE_SMALL = pg.transform.scale(IMAGE, (50, 30))
# Rotate by 0 degrees, multiply size by 2.
IMAGE_BIG = pg.transform.rotozoom(IMAGE, 0, 2)
def main():
clock = pg.time.Clock()
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
screen.fill(pg.Color('gray15'))
screen.blit(IMAGE, (50, 50))
screen.blit(IMAGE_SMALL, (50, 155))
screen.blit(IMAGE_BIG, (50, 230))
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
main()
pg.quit()
sys.exit()
Комментарии:
1. Спасибо! Работает просто отлично! 🙂
Ответ №2:
Вы должны решить, хотите ли вы использовать Use pygame.transform.smoothscale
или pygame.transform.scale
. pygame.transform.scale
При быстром масштабировании с ближайшим пикселем pygame.transform.smoothscale
поверхность плавно масштабируется до любого размера с интерполяцией пикселей.
Масштабирование поверхности с pygame.transform.scale()
помощью приведет к неровному результату. При уменьшении масштаба вы теряете информацию (пиксели). Для сравнения, pygame.transform.smoothscale
размывает поверхность.
pygame.transform.scale()
и pygame.transform.smoothscale
используются таким же образом. Они не масштабируют саму входную поверхность. Он создает новую поверхность и выполняет масштабирование «blit» для новой поверхности. Новая поверхность возвращается возвращаемым значением. Они:
- Создает новую поверхность (
newSurface
) с размером(width, height)
. - Масштабируйте и копируйте
Surface
вnewSurface
. - Возврат
newSurface
.
look_1 = pygame.image.load('datapnglook1.png').convert_alpha()
look_1 = pygame.transform.scale(look_1, (new_width, new_height))
или
look_1 = pygame.image.load('datapnglook1.png').convert_alpha()
look_1 = pygame.transform.smoothscale(look_1, (new_width, new_height))
См. также Преобразование масштаба и поверхности масштабирования
Минимальный пример: replit.com/@Rabbid76/PyGame-ScaleCenter
import pygame
class ScaleSprite(pygame.sprite.Sprite):
def __init__(self, center, image):
super().__init__()
self.original_image = image
self.image = image
self.rect = self.image.get_rect(center = center)
self.mode = 1
self.grow = 0
def update(self):
if self.grow > 100:
self.mode = -1
if self.grow < 1:
self.mode = 1
self.grow = 1 * self.mode
orig_x, orig_y = self.original_image.get_size()
size_x = orig_x round(self.grow)
size_y = orig_y round(self.grow)
self.image = pygame.transform.scale(self.original_image, (size_x, size_y))
self.rect = self.image.get_rect(center = self.rect.center)
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
sprite = ScaleSprite(window.get_rect().center, pygame.image.load("Banana64.png"))
group = pygame.sprite.Group(sprite)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
group.update()
window.fill(0)
group.draw(window)
pygame.display.flip()
pygame.quit()
exit()
Ответ №3:
Вы можете сделать:
import pygame,sys
from pygame.locals import *
size = int(input("What is the size?"))
look_1 = pygame.image.load('datapnglook1.png')
win = pygame.display.set_mode((500,500),0,32)
while True:
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
win.blit(pygame.transform.scale(look_1, (size, size)), (x, y))
win.update()
Надеюсь, это поможет!
Ответ №4:
Сначала импортируйте изображение. Тогда мы можем использовать pygame.transform.scale
. Это операция быстрого масштабирования.
self.image = pygame.image.load('ship.bmp')
self.image = pygame.transform.scale(self.image,(35,35))
Четвертая часть проект «Стрелялка с Pygame». Если пропустили, обязательно вернитесь и начините с первой части. В этот раз речь пойдет об использовании заготовленной графики.
В этой серии уроков будет создана полноценная игра на языке Python с помощью библиотеки Pygame. Она будет особенно интересна начинающим программистам, которые уже знакомы с основами языка и хотят углубить знания, а также узнать, что лежит в основе создания игр.
Выбор графики
В уроке, посвященном спрайтами, затрагивалась тема Opengameart.org — источника бесплатного арта для игр; и популярного местного автора, Kenney. Kenney создал набор арта, который прекрасно подойдет для этой стрелялки. Он называется «Space Shooter Pack». Найти его можно здесь:
https://opengameart.org/content/space-shooter-redux
Он включает массу качественных изображений с космическими кораблями, лазерами, астероидами и так далее.
Архив содержит несколько папок. Для этого проекта нужно папка PNG со всеми изображениями по отдельности. Для спрайтов пока что нужно только три, а также изображение звездного неба для фона.
Изображения необходимо скопировать туда, где игра сможет их найти. Лучше всего создать новую папку в том же месте, где хранится код игры. Назовем ее «img».
Загрузка изображений
Чтобы быть уверенными в том, что код будет работать в любой операционной системе, нужно использовать функцию os.path
, которая определяет правильный путь к файлам вне зависимости от ОС.
В верхней части программы необходимо определить местоположение папки img
:
from os import path
img_dir = path.join(path.dirname(__file__), 'img')
Прорисовка фона
Теперь можно приступать к загрузке фонового изображения. Загрузку ассетов необходимо производить до игрового цикла и кода запуска:
# Загрузка всей игровой графики
background = pygame.image.load(path.join(img_dir, 'starfield.png')).convert()
background_rect = background.get_rect()
Теперь можно прорисовать фон в разделе Draw игрового цикла до прорисовки любого из спрайтов:
# Рендеринг
screen.fill(BLACK)
screen.blit(background, background_rect)
all_sprites.draw(screen)
blit
— это олдскульный термин из компьютерной графики, который обозначает прорисовку пикселей одного изображения на другом. В этом случае — прорисовку фона на экране. Теперь фон выглядит намного лучше:
Изображения спрайтов:
Теперь можно загрузить изображения спрайтов:
# Загрузка всей игровой графики
background = pygame.image.load(path.join(img_dir, 'starfield.png')).convert()
background_rect = background.get_rect()
player_img = pygame.image.load(path.join(img_dir, "playerShip1_orange.png")).convert()
meteor_img = pygame.image.load(path.join(img_dir, "meteorBrown_med1.png")).convert()
bullet_img = pygame.image.load(path.join(img_dir, "laserRed16.png")).convert()
Начнем с игрока — необходимо заменить зеленый прямоугольник, то есть self.image
и не забыть убрать параметр image.fill(GREEN)
, который больше не нужен:
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = player_img
self.rect = self.image.get_rect()
Тем не менее имеется пара проблем. Во-первых, картинка чуть больше, чем требуется. Есть два варианта: 1) открыть ее в графическом редакторе (Photoshop, GIMP) и отредактировать; 2) поменять размер прямо в коде. Выбираем второй вариант. Для этого понадобится функция Pygame под названием transform.scale()
. Уменьшим изображение вдвое — до размера 50х30 пикселей.
Вторая проблема — черный прямоугольник вокруг корабля. Чтобы это исправить, нужно назначить прозрачный цвет с помощью set_colorkey
:
self.image = pygame.transform.scale(player_img, (50, 38))
self.image.set_colorkey(BLACK)
Если повторить то же самое для классов Bullet
и Mob
(хотя их размер менять не нужно), игра будет выглядеть намного лучше:
Код урока — shmup-4.py
Итого
Теперь в игре есть графика, и это помогает заметить новую проблему: астероиды уничтожают корабль, даже когда не касаются его. В следующем уроке поработаем над тем, чтобы столкновения работали корректно.