11. Класс Rect

Еще одни ключевым классом в Pygame является Rect. Его экземпляры представляют собой прямоугольные области. Они не имеют графического представления в окне игры. Ценность класса заключается в свойствах и методах, позволяющих управлять размещением поверхностей, выполнять проверку их перекрытия и др.

Rect'ы можно передавать в функцию display.update(). В этом случае будут обновляться только соответствующие им области.

Экземпляры Rect создаются не только напрямую от класса. Однако начнем с этого варианта.
rect1 = Rect((0, 0, 30, 30))
rect2 = Rect((30, 30, 30, 30))
конструктор класса Rect передаются четыре числа – координаты x и y, ширина и высота. Мы создаем два квадрата со сторонами в 30 пикселей. Верхний левый угол первого находится в точке (0, 0), второго – (30, 30).

У объектов Rect есть более десятка свойств, связанных с их координатами и размерами. Свойство bottomright одно из них, в нем хранится координата нижнего правого угла. Понятно, что если второй квадрат начинается в точке (30, 30) и его сторона равна 30, то нижний правый угол будет в точке (60, 60).

Кроме свойств, у объектов Rect есть множество методов. Метод move_ip() смещает прямоугольную область по оси x (первый аргумент) и y (второй аргумент) на указанное количество пикселей. В данном случае если второй прямоугольник смещается на 10 пикселей по обоим осям, то его левый верхний угол окажется в точке (40, 40).

Метод union_ip() присоединяет к тому прямоугольнику, к которому применяется, другой – который передается аргументом. Когда мы отодвинули второй прямоугольник на 10 пикселей, то область, заключающая в себе оба, уже будет шириной 70 пикселей, а не 60.

Методы, у которых есть суффикс _ip, изменяют тот экземпляр Rect, к которому применяются. Есть аналогичные методы без _ip (например, move(), union()), которые возвращают новый экземпляр, т. е. старый остается без изменений.

В метод blit() можно передавать не координаты места размещения Surface, а экземпляр Rect. Метод blit() сам возьмет из Rect координаты его верхнего левого угла:

from pygame import *
import sys
 
window = display.set_mode((300, 300))
window.fill((200, 255, 200))
 
surf1 = Surface((200, 200))
surf1.fill((220, 200, 0))  # желтая
surf2 = Surface((100, 100))
surf2.fill((255, 255, 255))  # белая
 
rect = Rect((70, 20, 0, 0))
 
surf1.blit(surf2, rect)
window.blit(surf1, rect)
 
display.update()
 
while 1:
    for i in event.get():
        if i.type == QUIT:
            sys.exit()
Мы размещаем желтую поверхность на зеленой, а белую – на желтой. В обоих случаях – в координатах (70, 20). Однако в каждом случае точка берется относительно своей родительской поверхности.

Еще один момент, на который надо обратить внимание. Прямоугольная область была определена нулевой размерностью. При этом поверхности отобразились соответственно своим собственным размерам. Это значит, что поверхности не располагаются внутри rect'ов. Они к ним никакого отношения не имеют. Из прямоугольников blit() взял только координаты.

С другой стороны, экземпляры Rect предназначены для хранения не только координат, но и размеров поверхностей. Размеры в основном нужны для проверки коллизий. В большинстве случаев сначала создается поверхность. Далее с нее снимается "маска", т. е. создается экземпляр Rect, который будет иметь те же размеры, что и она. Все дальнейшее "взаимодействие" поверхности с другими объектами (размещение, проверка столкновений и вхождений) происходит через "связанный" с ней Rect.
rect = surf2.get_rect()  # создается Rect
 
print(surf2.get_width())  # вывод 100
print(rect.width)  # 100
print(rect.x, rect.y)  # 0 0
Задачи
Напишите программу по следующему описанию. В центре окна находится круг, изменяющий свой цвет на каждой итерации цикла. Окно условно поделено на четверти: верхнюю левую, верхнюю правую, нижнюю левую, нижнюю правую. Если нажимается клавиша 1, то обновляются только две четверти по диагонали. Если 2 – то только две другие. Нажатие нуля возобновляет обновление всей поверхность.

Примечание. Функция pygame.display.update() может принимать не только один экземпляр Rect, но и список таковых.