Модуль pygame.draw
Функции модуля pygame.draw
рисуют геометрические примитивы на поверхности – экземпляре класса Surface
. В качестве первого аргумента они принимают поверхность. Поэтому при создании той или иной поверхности ее надо связать с переменной, чтобы потом было что передать в функции модуля draw
. Поскольку мы пока используем только одну поверхность – главную оконную, то ее будем указывать в качестве первого параметра, а при создании свяжем с переменной:
import pygame as pg import sys sc = pg.display.set_mode((300, 200)) # здесь будут рисоваться фигуры pg.display.update() while 1: for i in pg.event.get(): if i.type == pg.QUIT: sys.exit() pg.time.delay(1000)
В большинстве случаев фигуры прорисовывают внутри главного цикла, так как от кадра к кадру картинка на экране должна меняться. Поэтому на каждой итерации цикла в функции модуля draw
передаются измененные аргументы (например, каждый раз меняется координата x).
Однако у нас пока не будет никакой анимации, и нет смысла перерисовывать фигуры на одном и том же месте на каждой итерации цикла. Поэтому создавать примитивы будем в основной ветке программы. На данном этапе цикл while
нужен лишь для того, чтобы программа самопроизвольно не завершалась.
После прорисовки, чтобы увидеть изменения в окне игры, необходимо выполнить функцию update()
или flip()
модуля display
. Иначе окно не обновится. Рисование на поверхности – одно, а обновление состояния главного окна – другое. Представьте, что в разных местах тела главного цикла на поверхности прорисовываются разные объекты. Если бы каждое такое действие приводило к автоматическому обновлению окна, то за одну итерацию оно обновлялось бы несколько раз. Это приводило бы как минимум к бессмысленной трате ресурсов, так как скорость цикла связана с FPS.
Итак, первый аргумент функций рисования – поверхность, на которой размещается фигура. В нашем случае это будет sc. Вторым обязательным аргументом является цвет. Цвет задается в формате RGB, используется трехэлементный целочисленный кортеж. Например, (255, 0, 0) определяет красный цвет.
Далее идут специфичные для каждой фигуры аргументы. Последним у большинства является толщина контура.
Все функции модуля draw
возвращают экземпляры класса Rect
– прямоугольные области, имеющие координаты, длину и ширину. Не путайте функцию rect()
модуля draw
и класс Rect
, это разные вещи.
Начнем с функции rect()
модуля draw
:
pygame.draw.rect(sc, (255, 255, 255), (20, 20, 100, 75)) pygame.draw.rect(sc, (64, 128, 255), (150, 20, 100, 75), 8)
Если указывается толщина контура (последний аргумент второго прямоугольника), то фигура окажется незаполненной, а цвет определит цвет рамки. Третьим аргументом является кортеж из четырех чисел. Первые два определяют координаты верхнего левого угла прямоугольника, вторые – его ширину и высоту.
Следует отметить, что в функцию draw.rect()
и некоторые другие третьим аргументом можно передавать не кортеж, а заранее созданный экземпляр Rect
. В примере ниже показан такой вариант.
Обычно цвета выносят в отдельные переменные-константы. Это облегчает чтение кода:
WHITE = (255, 255, 255) BLACK = (0, 0, 0) GRAY = (125, 125, 125) LIGHT_BLUE = (64, 128, 255) GREEN = (0, 200, 64) YELLOW = (225, 225, 0) PINK = (230, 50, 230) r1 = pygame.Rect((150, 20, 100, 75)) pygame.draw.rect(sc, WHITE, (20, 20, 100, 75)) pygame.draw.rect(sc, LIGHT_BLUE, r1, 8)
Чтобы нарисовать линию, а точнее – отрезок, надо указать координаты его концов. При этом функция line()
рисует обычную линию, aaline()
– сглаженную (толщину для последней указать нельзя):
pygame.draw.line(sc, WHITE, [10, 30], [290, 15], 3) pygame.draw.line(sc, WHITE, [10, 50], [290, 35]) pygame.draw.aaline(sc, WHITE, [10, 70], [290, 55])
Координаты можно передавать как в виде списка, так и кортежа.
Функции lines()
и aalines()
рисуют ломанные линии:
pygame.draw.lines(sc, WHITE, True, [[10, 10], [140, 70], [280, 20]], 2) pygame.draw.aalines(sc, WHITE, False, [[10, 100], [140, 170], [280, 110]])
Координаты определяют места излома. Количество точек может быть произвольным. Третий параметр (True
или False
) указывает замыкать ли крайние точки.
Функция polygon()
рисует произвольный многоугольник. Задаются координаты вершин.
pygame.draw.polygon(sc, WHITE, [[150, 10], [180, 50], [90, 90], [30, 30]]) pygame.draw.polygon(sc, WHITE, [[250, 110], [280, 150], [190, 190], [130, 130]]) pygame.draw.aalines(sc, WHITE, True, [[250, 110], [280, 150], [190, 190], [130, 130]])
Сглаженная ломаная здесь повторяет контур многоугольника, чем сглаживает его ребра.
Так же как в случае rect()
функция polygon()
может принимать толщину контура.
Функция circle()
рисует круги. Указывается центр окружности и радиус:
pygame.draw.circle(sc, YELLOW, (100, 100), 50) pygame.draw.circle(sc, PINK, (200, 100), 50, 10)
В случае эллипса передается описывающая его прямоугольная область:
pygame.draw.ellipse(sc, GREEN, (10, 50, 280, 100))
Наконец, дуга:
pi = 3.14 pygame.draw.arc(sc, WHITE, (10, 50, 280, 100), 0, pi) pygame.draw.arc(sc, PINK, (50, 30, 200, 150), pi, 2*pi, 3)
Указывается прямоугольник, описывающий эллипс, из которого вырезается дуга. Четвертый и пятый аргументы – начало и конец дуги, выраженные в радианах. Нулевая точка справа.
Практическая работа. Анимация
На данном этапе мы уже готовы создать анимацию. Никакого движения объектов на экране монитора нет. Просто от кадра к кадру изменяются цвета пикселей экрана. Например, пиксель с координатами (10, 10) светится синим цветом, в следующем кадре синим загорается пиксель (11, 11), в то время как (10, 10) становится таким же как фон. В следующем кадре синей будет только точка (12, 12) и так далее. При этом человеку будет казаться, что синяя точка движется по экрану по диагонали.
Суть алгоритма в следующем. Берем фигуру. Рисуем ее на поверхности. Обновляем главное окно, человек видит картинку. Стираем фигуру. Рисуем ее с небольшим смещением от первоначальной позиции. Снова обновляем окно и так далее.
Как "стереть" старую фигуру? Для этого используется метод fill()
объекта Surface
. В качестве аргумента передается цвет, т. е. фон можно сделать любым, а не только черным, который задан по-умолчанию.
Ниже в качестве примера приводится код анимации круга. Объект появляется с левой стороны, доходит до правой, исчезает за ней. После этого снова появляется слева. Ваша задача написать код анимации квадрата, который перемещается от левой границе к правой, касается ее, но не исчезает за ней. После этого возвращается назад – от правой границы к левой, касается ее, опять двигается вправо. Циклы движения квадрата повторяются до завершения программы.
import pygame import sys FPS = 60 WIN_WIDTH = 400 WIN_HEIGHT = 100 WHITE = (255, 255, 255) ORANGE = (255, 150, 100) clock = pygame.time.Clock() sc = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) # радиус будущего круга r = 30 # координаты круга # скрываем за левой границей x = 0 - r # выравнивание по центру по вертикали y = WIN_HEIGHT // 2 while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() # заливаем фон sc.fill(WHITE) # рисуем круг pygame.draw.circle(sc, ORANGE, (x, y), r) # обновляем окно pygame.display.update() # Если круг полностью скрылся за правой границей, if x >= WIN_WIDTH + r: # перемещаем его за левую x = 0 - r else: # Если еще нет, # на следующей итерации цикла # круг отобразится немного правее x += 2 clock.tick(FPS)
Курс с примерами решений практических работ:
pdf-версия