2. Модуль рисования draw

Функции модуля draw рисуют геометрические примитивы на поверхности – экземпляре класса Surface. В качестве первого аргумента они принимают поверхность. Поэтому при создании той или иной поверхности ее надо связать с переменной, чтобы потом было что передать в функции модуля draw.

Поскольку мы пока используем только одну поверхность – главную оконную, то ее будем указывать в качестве первого параметра, а при создании свяжем с переменной:
Используем наш каркас создав объект "window"

import sys

from config_file.color import WHITE
from config_file.config import FPS, HEIGHT, WIDTH
from pygame import QUIT, Surface, display, event, init, time

# здесь происходит инициация,
# создание объектов
init()
window = display.set_mode((HEIGHT, WIDTH))
display.set_caption("Моя игра")
clock = time.Clock()

# Заливка фона
background = Surface(window.get_size())
background = background.convert()
background.fill(WHITE)
# если надо до цикла отобразить
# какие-то объекты, обновляем экран
window.blit(background, (0, 0))
display.flip()

# главный цикл
while True:
    # задержка
    clock.tick(FPS)

    # цикл обработки событий
    for player_event in event.get():
        if player_event.type == QUIT:
            sys.exit()

    # --------
    # изменение объектов
    # --------

    # обновление экрана
    display.flip()
В большинстве случаев фигуры прорисовывают внутри главного цикла, так как от кадра к кадру картинка на экране должна меняться. Поэтому на каждой итерации цикла в функции модуля draw передаются измененные аргументы (например, каждый раз меняется координата x).

Однако у нас пока не будет никакой анимации, и нет смысла перерисовывать фигуры на одном и том же месте на каждой итерации цикла. Поэтому создавать примитивы будем в основной ветке программы. На данном этапе цикл while нужен лишь для того, чтобы программа самопроизвольно не завершалась.

После прорисовки, чтобы увидеть изменения в окне игры, необходимо выполнить функцию flip() модуля display. Иначе окно не обновится. Рисование на поверхности – одно, а обновление состояния главного окна – другое. Представьте, что в разных местах тела главного цикла на поверхности прорисовываются разные объекты. Если бы каждое такое действие приводило к автоматическому обновлению окна, то за одну итерацию оно обновлялось бы несколько раз. Это приводило бы как минимум к бессмысленной трате ресурсов, так как скорость цикла связана с FPS.

Функция rect - прямоугольник

Итак, первый аргумент функций рисования – поверхность, на которой размещается фигура. В нашем случае это будет window. Вторым обязательным аргументом является цвет. Цвет задается в формате RGB, используется трехэлементный целочисленный кортеж. Например, (255, 0, 0) определяет красный цвет.

Далее идут специфичные для каждой фигуры аргументы. Последним у большинства является толщина контура.

Все функции модуля draw возвращают экземпляры класса Rect – прямоугольные области, имеющие координаты, длину и ширину.

Не путайте функцию rect() модуля draw и класс Rect, это разные вещи.
Начнем с функции rect() модуля draw:

import sys

from config_file.color import BLUE, RED1, WHITE
from config_file.config import FPS, HEIGHT, WIDTH
from pygame import QUIT, Surface, display, draw, event, init, time

# здесь происходит инициация,
# создание объектов
init()
window = display.set_mode((HEIGHT, WIDTH))
display.set_caption("Моя игра")
clock = time.Clock()

# Заливка фона
background = Surface(window.get_size())
background = background.convert()
background.fill(WHITE)
# если надо до цикла отобразить
# какие-то объекты, обновляем экран
window.blit(background, (0, 0))

draw.rect(window, BLUE, (20, 20, 100, 75))
draw.rect(window, RED1, (150, 20, 100, 75), 8)

display.flip()

# главный цикл
while True:
    # задержка
    clock.tick(FPS)

    # цикл обработки событий
    for player_event in event.get():
        if player_event.type == QUIT:
            sys.exit()

    # --------
    # изменение объектов
    # --------

    # обновление экрана
    display.flip()

Далее будем демонстрировать только основные команды, которые Вам необходимо вставить в "скелет" программы
Функция rect() - прямоугольник
rect ( объект, цвет, координаты и размер прямоугольника, размер рамки=0, радиус скругления=0, радиус верхнего левого угла=-1, радиус верхнего правого угла=-1, радиус нижнего левого угла=-1, радиус нижнего правого угла=-1)

Если указывается толщина контура (последний аргумент во второй строке), то прямоугольник будет незаполненным, а цвет определит цвет рамки. Третьим аргументом является кортеж из четырех чисел. Первые два определяют координаты верхнего левого угла прямоугольника, вторые – его ширину и высоту.

Следует отметить, что в функцию draw.rect() и некоторые другие третьим аргументом можно передавать не кортеж, а заранее созданный экземпляр Rect. В примере ниже показан такой вариант.

Обычно цвета выносят в отдельные переменные-константы. Это облегчает чтение кода:
Создание объекта Rect

r1 = Rect((150, 20, 100, 75))
 
draw.rect(window, WHITE, (20, 20, 100, 75))
draw.rect(window, RED1, r1, 8)
Функция line - отрезок
Чтобы нарисовать линию ( отрезок ), надо указать координаты его концов. При этом функция line() рисует обычную линию, aaline() – сглаженную (толщину для последней указать нельзя):
Наклонный отрезок

draw.line(window, RED1, [10, 30], [290, 15], 3)

draw.line(window, RED1, [10, 50],  [290, 35])

draw.aaline(window, RED1, [10, 70],  [290, 55]) #плавная линия
Функции lines() и aalines() рисуют ломанные линии. Координаты определяют места излома. Количество точек может быть произвольным. Третий параметр (True или False) указывает замыкать ли крайние точки.

draw.lines(window, RED1, True, [[10, 10], [140, 70], [280, 20]], 2)
draw.aalines(window, RED1, False, [[10, 100], [140, 170],  [280, 110]])
Функция polygon() - многоугольник
Функция polygon() рисует произвольный многоугольник. Задаются координаты вершин, область закрашивается.

Сглаженная ломаная здесь повторяет контур многоугольника, чем сглаживает его ребра.
Так же как в случае rect() для polygon() можно указать толщину контура.
Построение многоугольников

draw.polygon(window, RED1, [[150, 10], [180, 50], [90, 90], [30, 30]])
draw.polygon(window, RED1, [[250, 110], [280, 150], [190, 190], [130, 130]])
draw.aalines(window, RED1, True, [[250, 110], [280, 150], [190, 190], [130, 130]])
Функция circle() - круг
Функция circle() рисует круги. Указывается центр окружности и радиус
Построение окружностей

draw.circle(window, RED1, (100, 100), 50)

draw.circle(window, RED1, (200, 100), 50, 10)
Функция ellipse() - овал
В случае эллипса передается описывающая его прямоугольная область
Построение эллипсов

draw.ellipse( window, RED1, (10, 50, 280, 100) )
Функция arc() - дуга
Указывается прямоугольник, описывающий эллипс, из которого вырезается дуга. Четвертый и пятый аргументы – начало и конец дуги, выраженные в радианах. Нулевая точка справа.
Построение эллипсов

pi = 3.14
draw.arc(window, RED1, (10, 50, 280, 100), 0, pi)

draw.arc(window, RED1, (50, 30, 200, 150), pi, 2*pi, 3)
Задачи