Текст и счёт на экране

Очки, жизни, таймер — игре нужно показывать цифры и текст. Шрифты в Pygame рендерят строку в картинку, которую мы рисуем как обычный спрайт.
Суть: текст в Pygame — это картинка. Шрифт через font.render превращает строку в Surface, которую рисуют через blit. Меняется счёт — пересоздаём картинку текста.

Любая игра показывает информацию: счёт, число жизней, время, надпись «Game Over». В Pygame нет привычного «вывести текст» как в консоли — здесь текст это картинка. Мы берём шрифт, говорим ему «нарисуй вот эту строку этим цветом», и получаем Surface — такую же поверхность, как загруженный спрайт. Её рисуем на экране через blit.

Сначала создаём объект шрифта: pygame.font.Font(None, 48) — None означает стандартный системный шрифт, 48 — размер. Затем рендерим: font.render("Счёт: 100", True, (255,255,255)). Второй аргумент True включает сглаживание (antialiasing) — буквы получаются гладкими, а не зубчатыми. Результат — картинка текста, которую можно blit-нуть в любую точку.

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

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

Шрифт превращает строку в набор пикселей-букв на прозрачной поверхности. Дальше это обычный blit, как со спрайтом:

   "Счёт: 100"
        |  font.render(text, True, color)
        v
   [картинка текста]  (Surface с буквами)
        |  screen.blit(img, (x, y))
        v
   текст на экране

   счёт изменился -> render заново -> новая картинка

В pygame (читаем):

pygame.font.init()
font = pygame.font.Font(None, 48)   # системный шрифт, размер 48

score = 0
# в цикле, когда рисуем:
text_img = font.render(f"Счёт: {score}", True, (255, 255, 255))
screen.blit(text_img, (20, 20))

# выровнять по центру:
rect = text_img.get_rect(center=(400, 50))
screen.blit(text_img, rect)

Форматирование строки счёта — обычный Python, проверяемый без графики. Соберём строки HUD (счёт, жизни, время). Попробуй сам:

def hud_lines(score, lives, seconds):
    return [
        f"Счёт: {score}",
        f"Жизни: {'<3 ' * lives}".strip(),
        f"Время: {int(seconds // 60)}:{int(seconds % 60):02d}",
    ]

for line in hud_lines(score=1250, lives=3, seconds=95):
    print(line)

Кастомные шрифты и кеширование текста

Системный шрифт (Font(None, 48)) хорош для прототипа, но выглядит казённо. Свой характер игре придаёт шрифт из файла: pygame.font.Font("pixel.ttf", 32) загружает любой TTF, например пиксельный для ретро-аркады. Шрифт — часть стиля игры наравне с цветами и спрайтами, и подобрать его стоит так же тщательно. Один удачный шрифт мгновенно делает интерфейс «своим», а не дефолтным.

Про производительность: рендер текста — операция не бесплатная, она каждый раз заново рисует все буквы. Если счёт меняется редко, глупо рендерить его 60 раз в секунду. Профессиональный приём — кешировать картинку текста и пересоздавать её только тогда, когда значение изменилось: if score != last_score: text_img = font.render(...). Для статичных надписей вроде «Пауза» рендери один раз при старте. Эти мелочи незаметны на простой игре, но входят в привычку и держат FPS высоким, когда интерфейс разрастётся до десятков надписей.

Текст в игре — это не только счёт, но и весь её «голос»: подсказки, диалоги, названия уровней, экраны победы и поражения. Поэтому стоит сразу сделать удобную функцию-помощник, например draw_text(surface, text, pos, size, color), которая рендерит строку и рисует её в нужном месте с нужным выравниванием. Один раз написал — и весь остальной код пишет текст одной короткой строкой, без повторения возни со шрифтом и get_rect. Это та же идея переиспользования, что и со словарём ассетов или константами цветов: вынеси рутину в одно место и пользуйся ей везде. Аккуратная работа с текстом делает интерфейс игры опрятным, а код — компактным и приятным для чтения.

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

  • Забыть font.init() (или общий pygame.init()) — шрифт не создастся.
  • Рендерить текст до создания строки счёта — увидишь старое значение.
  • Передать число вместо строки в render — нужна строка, оборачивай в str() или f-строку.

Best practices

  • Создавай объект Font один раз, переиспользуй каждый кадр.
  • Для выравнивания используй get_rect(center=...) — текст встанет ровно.
  • Если значение не меняется, не рендери его заново каждый кадр.

Итог: текст это картинка из шрифта. render превращает строку в Surface, blit рисует её. Меняется число — пересоздаём картинку.

Проверьте себя
1. Чем по сути является текст, выведенный через font.render?
AСтрокой в консоли
BКартинкой-поверхностью (Surface), которую рисуют через blit
CЧислом
DЗвуком
2. Когда нужно заново вызвать font.render для счёта?
AКаждый пиксель
BКогда значение счёта изменилось
CНикогда
DТолько при закрытии игры
py
Курс по теме
Пройдите курс «Python с нуля» — по шагам, с проверкой
8 уроков · ~14 ч · теория, упражнения и экзамен с бейджем
Открыть курс →