Рисование графических примитивов

На этом занятии рассмотрим функции модуля pygame.draw для рисования графических примитивов:

  • pygame.draw.rect(surface, …) – прямоугольник;
  • pygame.draw.line(surface, …) – линия;
  • pygame.draw.aaline(surface, …) – сглаженная линия;
  • pygame.draw.lines(surface, …) – ломаная линия;
  • pygame.draw.aalines(surface, …) – ломаная сглаженная линия;
  • pygame.draw.polygon(surface, …) – полигон;
  • pygame.draw.circle(surface, …) – круг;
  • pygame.draw.ellipse(surface, …) – эллипс;
  • pygame.draw.arc(surface, …) – дуга.

Обратите внимание у всех этих функций первым параметром идет surface – поверхность, на которой выполняется рисование. Забегая вперед отмечу, что таких поверхностей можно создавать множество, накладывая друг на друга. Но на этом занятии мы будем использовать базовую поверхность, представляющую клиентскую область окна приложения:

Ссылку на этот объект можно получить в момент создания окна:

sc = pygame.display.set_mode((600, 400))

(здесь sc – ссылка на базовый объект Surface). Давайте теперь нарисуем в окне прямоугольник с помощью функции rect:

pygame.draw.rect(sc, (255,255,255), (10,10, 50, 100))

Мы здесь первым параметром указали главную поверхность, затем, цвет прямоугольника и его размеры. Цвет определяется в формате (R, G, B). Причем, каждая цветовая компонента меняется в диапазоне от 0 до 255:

  • 0 – отсутствие цветовой составляющей;
  • 255 – полная насыщенность цветовой составляющей.

В данном случае мы включаем все три цветовые компоненты по максимуму и получаем белый цвет. Далее, размеры прямоугольника определяются по формату:

(x, y, width, height)

  • x, y – начальные координаты прямоугольника;
  • width, height – ширина и высота прямоугольника.

Обратите внимание, что координаты откладываются от верхнего левого угла и ось Oy направлена вниз (а не вверх, как мы привыкли по математике).

Итак, указание нарисовать прямоугольник даны. Но если сейчас выполнить программу, то мы ничего не увидим на экране. Почему? Это связано с тем, что базовый объект Surface использует механизм рисования, известный как буферизация вывода.

Ее принцип проще пояснить на таком рисунке. Представим, что объект Surface имеет две стороны A и B:

Изначально мы видим сторону B, но рисование выполняется на противоположной стороне – A. Затем, чтобы отобразить нарисованные объекты, мы должны перевернуть объект Surface другой стороной. В PyGame это делается с помощью функции flip():

pygame.display.flip()

Теперь при запуске программы мы видим сторону A с нарисованным прямоугольником. В этом заключается принцип буферизации вывода графической информации. Но спрашивается: зачем все это нужно? Почему бы сразу не рисовать на видимой стороне объекта? В этом случае при большом числе объектов и сложной анимации пользователь будет замечать процесс отрисовки текущего кадра игры. И это негативно скажется на визуальном восприятии игрового процесса. Чтобы перерисовка кадров проходила незаметно для человеческого глаза, как раз и используется механизм буферизации.

Помимо метода flip() можно использовать похожий метод:

pygame.display.update(rectangle)

Здесь rectangle – это прямоугольная область, которую требуется перерисовать (по умолчанию, если ничего не указано, то перерисовывается вся клиентская область и метод update повторяет метод flip).

Так как метод update более гибкий, то в дальнейшем я буду использовать именно его.

Итак, мы с вами нарисовали закрашенный прямоугольник. Если нужно нарисовать не закрашенный, то следует указать следующий параметр – толщину линии:

pygame.draw.rect(sc, (0, 0, 255), (100, 10, 50, 100), 2)

Разумеется, все функции рисования должны следовать до метода update. Наконец, последний важный штрих. Цвета заливки или линий обычно задаются вначале в виде констант, а затем, уже используются в функциях рисования:

WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
 
pygame.draw.rect(sc, WHITE, (10, 10, 50, 100))
pygame.draw.rect(sc, BLUE, (100, 10, 50, 100), 2)
pygame.display.update()

Так программа выглядит более читабельной. Давайте теперь посмотрим как рисуются остальные графические примитивы:

WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
pygame.draw.rect(sc, WHITE, (10, 10, 50, 100))
pygame.draw.rect(sc, BLUE, (100, 10, 50, 100), 2)
 
pygame.draw.line(sc, GREEN, (200, 20), (350, 50))
pygame.draw.aaline(sc, GREEN, (200, 40), (350, 70))
 
pygame.draw.lines(sc, RED, True, [(200, 80), (250, 80), (300, 200)], 2)
pygame.draw.aalines(sc, RED, True, [(300, 80), (350, 80), (400, 200)], 2)
 
pygame.draw.polygon(sc, WHITE, [[150, 210], [180, 250], [90, 290], [30, 230]])
pygame.draw.polygon(sc, WHITE, [[150, 310], [180, 350], [90, 390], [30, 330]], 1)
 
pygame.draw.circle(sc, BLUE, (300, 250), 40)
pygame.draw.ellipse(sc, BLUE, (300, 300, 100, 50), 1)
 
pi = 3.14
pygame.draw.arc(sc, RED, (450, 30, 50, 150), pi, 2*pi, 5)

Вот такие примитивы существуют в PyGame.