Rect — главный кубик игры

Rect — самый важный объект в Pygame. Это и позиция, и размер, и инструмент проверки столкновений в одном флаконе.
Суть: pygame.Rect хранит прямоугольную область и даёт десятки удобных свойств — center, topleft, right — а ещё умеет проверять пересечения. Это рабочая лошадка всей игры.

Если бы пришлось выбрать один объект Pygame, который ты будешь использовать чаще всего, это был бы Rect. Почти всё в 2D-игре — прямоугольник: герой, враг, монетка, кнопка, область экрана. Rect не просто хранит четыре числа, он даёт удобные «ручки», чтобы за них браться.

Хочешь поставить объект по центру экрана? Не нужно считать вручную — просто присвой rect.center = (400, 300), и Rect сам пересчитает свой угол. Хочешь узнать, где правая грань? rect.right. Хочешь прижать объект к низу окна? rect.bottom = HEIGHT. Эти свойства экономят тонну арифметики и багов.

Как работает под капотом

Внутри Rect хранит четыре числа: x, y, width, height. Все остальные свойства — это вычисления поверх них. Когда ты меняешь center, Rect пересчитывает x и y так, чтобы центр оказался на месте. Вот карта «ручек» прямоугольника:

   topleft     midtop      topright
      +-----------+-----------+
      |           |           |
  midleft      center      midright
      |           |           |
      +-----------+-----------+
   bottomleft  midbottom  bottomright

   .x .y = topleft   .centerx .centery = center

В pygame это используется так:

player = pygame.Rect(0, 0, 50, 50)   # x,y,w,h
player.center = (400, 300)           # ставим по центру окна
print(player.topleft)                # (375, 275)

player.x += 5            # сдвиг вправо
player.bottom = 600      # прижать к низу окна

# проверка пересечения с другим Rect
coin = pygame.Rect(380, 280, 20, 20)
if player.colliderect(coin):
    print("Собрали монетку!")

Логику свойств Rect легко воспроизвести на чистом Python. Сделаем мини-версию, которая умеет ставить центр и считать грани. Попробуй сам:

class MiniRect:
    def __init__(self, x, y, w, h):
        self.x, self.y, self.w, self.h = x, y, w, h

    def set_center(self, cx, cy):
        self.x = cx - self.w // 2     # пересчитываем угол из центра
        self.y = cy - self.h // 2

    @property
    def center(self):
        return (self.x + self.w // 2, self.y + self.h // 2)

r = MiniRect(0, 0, 50, 50)
r.set_center(400, 300)
print("угол topleft:", (r.x, r.y))
print("center снова:", r.center)
print("right:", r.x + r.w, "bottom:", r.y + r.h)

Rect как универсальная зона

Rect полезен далеко за пределами «где находится спрайт». Им удобно описывать любую прямоугольную область с особым смыслом: зону, при входе в которую срабатывает ловушка; кнопку меню, по которой проверяют клик мыши; границы экрана, за которые нельзя выходить. Метод collidepoint(x, y) отвечает, попала ли точка (например, курсор) внутрь прямоугольника — так делают кликабельные кнопки. А contains проверяет, целиком ли один Rect внутри другого.

Ещё одна суперсила — методы движения. rect.move(dx, dy) возвращает новый сдвинутый прямоугольник, не меняя исходный, а rect.inflate(dx, dy) раздувает или сжимает его от центра — удобно делать хитбокс чуть меньше картинки. rect.clamp(area) возвращает Rect, втиснутый внутрь заданной области, — готовый способ не дать герою убежать за экран. Освоив эти методы, ты заметишь, что многие задачи, которые казались отдельными, на самом деле решаются одним вызовом Rect. Это и есть сила хорошо продуманного «кубика».

Привыкай читать код с Rect как предложения на русском. Строка enemy.rect.bottom = floor.top буквально говорит «поставь врага низом на верх пола» — и делает именно это, без единого вычисления вручную. Такой стиль самодокументирует логику: через месяц ты поймёшь свой код с одного взгляда. Ещё одна частая операция — держать объект внутри экрана: player.rect.clamp_ip(screen_rect) сам вернёт героя в границы, если тот выехал за край. Rect — это маленький, но удивительно богатый инструмент, и время, потраченное на изучение его свойств и методов, окупается в каждой следующей игре. Не зря говорят, что половина Pygame — это умелое обращение с прямоугольниками.

Частые ошибки

  • Двигать объект, меняя только x, но проверять center — путаница в том, что считается позицией.
  • Хранить float-позицию прямо в Rect — Rect округляет до целых, дробная часть теряется. Держи точную позицию отдельно.
  • Считать грани вручную вместо rect.right — лишний код и ошибки.

Best practices

  • Используй именованные свойства (center, bottom) — код читается как описание сцены.
  • Точную позицию храни во Vector2, а Rect синхронизируй для отрисовки и коллизий.
  • Для проверки столкновений всегда есть colliderect — не изобретай велосипед.

Итог: Rect — это позиция, размер и детектор столкновений в одном объекте. Освой его свойства, и половина рутины исчезнет.

Проверьте себя
1. Что произойдёт, если присвоить rect.center = (400, 300)?
AНичего, center только для чтения
BRect пересчитает свой угол x,y под новый центр
CОкно сместится
DRect удалится
2. Какой метод Rect проверяет пересечение с другим Rect?
Arect.overlap()
Brect.touch()
Crect.colliderect(other)
Drect.intersect()