Глава 20 · Разработка игр с Pygame

Столкновения и хитбоксы

colliderect() под капотом — четыре сравнения чисел, а хитбокс не обязан совпадать с видимой картинкой пиксель в пиксель.

Столкновение — момент, когда два игровых объекта пересекаются в пространстве, и игра должна на это отреагировать: мяч отскакивает от стены, персонаж подбирает монету, снаряд поражает врага. У pygame.Rect для этого есть готовый метод:

colliderect.py
if igrok_rect.colliderect(vrag_rect):
    print("Столкновение!")

Как это устроено на самом деле

colliderect() проверяет пересечение двух прямоугольников, выровненных по осям (AABB, axis-aligned bounding box) — метод, который под капотом сводится к четырём простым сравнениям чисел:

aabb_vruchnuyu.py
def pryamougolniki_peresekayutsya(a, b):
    ax1, ay1, aw, ah = a
    bx1, by1, bw, bh = b
    ax2, ay2 = ax1 + aw, ay1 + ah
    bx2, by2 = bx1 + bw, by1 + bh
    return ax1 < bx2 and ax2 > bx1 and ay1 < by2 and ay2 > by1

Два прямоугольника не пересекаются, если один полностью левее, правее, выше или ниже другого — проверка выше как раз убеждается, что ни одно из этих четырёх условий не выполняется.

Реальное окно: голубой и жёлтый квадраты частично перекрываются — colliderect() возвращает True
Реальное окно: перекрывающиеся прямоугольники — второй закрашен жёлтым, потому что colliderect() вернула True.
Реальное окно: голубой и красный квадраты далеко друг от друга — colliderect() возвращает False
Реальное окно: прямоугольники не пересекаются — второй остался красным.

Хитбокс — не всегда то же самое, что рисунок

«Хитбокс» — прямоугольник (или другая фигура), который используется именно для проверки столкновений, и он не обязан по размеру совпадать с видимым рисунком персонажа один в один. У круглого мяча с прозрачными краями изображение обычно квадратное — если считать столкновение по полному квадрату изображения, игрок будет видеть несправедливые «попадания мимо» там, где на глаз ничего не коснулось.

Хитбокс не совпадает с картинкой — столкновения ощущаются "нечестными"
Частая причина: Rect берут напрямую из размера всего загруженного изображения, включая прозрачные поля вокруг самого персонажа. Решение — уменьшить хитбокс относительно видимой картинки через rect.inflate(-20, -20): inflate() меняет общий размер прямоугольника, сохраняя центр, поэтому -20 по ширине и высоте убирает ровно по 10 пикселей с каждой стороны, а не 20. Конкретный отступ подбирают на глаз под каждый спрайт.
Реальное окно: красный мяч с двумя рамками поверх — большой красной по границе изображения и меньшей зелёной внутри неё
Реальное окно: красная рамка — полный размер изображения, зелёная — уменьшенный хитбокс, ближе к реальным видимым краям мяча.
Практика: проверка пересечения прямоугольников
Проверяется прямо в браузере — установка Pygame не требуется
Открыть практику →