Внутренний функционал питона довольно мощный, и его вполне достаточно для реализации многих проектов.
Однако питон не был бы таким популярным среди программистов, если бы не мог расширять свой функционал за счет дополнительных модулей (ещё их называют библиотеками или пакетами) с помощью всего лишь одной строчки кода.
Каждый существующий модуль написан для решения задач в конкретной области.
И первым модулем, который не включён в стандартную библиотеку питона, с которым мы познакомимся, будет модуль drawzero.
drawzero — это простая и удобная графическая библиотека, в которой есть функции для рисования простых фигур.
Чтобы получить к ним доступ, надо в начале программы написать строку
from drawzero import *
Установка drawzero
Перед первым использованием модуль drawzero нужно установить.
Для этого в терминале нужно выполнить команду
pip install drawzero --upgrade --user
Под linux и MacOS вместо pip нужно вводить pip3.
Если слово «терминал» непонятно, то можно запустить вот такую программу:
import os, sys
python = sys.executable
user = '--user' if 'venv' not in python else ''
cmd = '"{}" -m pip install drawzero --upgrade {}'.format(python, user)
print(cmd)
os.system(cmd)
Если в результате её запуска вывод будет примерно такой как ниже, то у вас успех!
C:\some\path\Python38\python.exe -m pip install drawzero --upgrade --user
Collecting drawzero
... что-то про downloading или Using cached
Collecting pygame
... что-то про downloading или Using cached
Installing collected packages: pygame, drawzero
Successfully installed drawzero-0.1.4 pygame-1.9.6
A. Основы основ
Итак, приступим к рисованию!
Скопируйте и запустите программу ниже.
В результате запуска должно открыться окно с нарисованной по диагонали красной линией.
Сдавать код этой задачи не нужно :)
from drawzero import *
line('red', (0, 0), (1000, 1000))
Осваиваем геометрию с помощью кода
Система координат в программировании и система координат в математике немного отличаются.
В программировании точка с координатами (0, 0) находится в верхнем левом углу.
Ось x направлена от неё вправо, а ось y — вниз.
Любая точка имеет позицию (координату) относительно оси x и относительно оси y, поэтому координаты каждой точки это пара чисел — сначала x, потом y.
Эти координаты указываются через запятую и записываются в круглых скобках.
Рисование отрезка выполняется, как мы уже знаем, с помощью команды line.
В скобках указываются параметры: цвет и две точки — концы отрезка.
Именно в таком порядке.
Цвет пока можно выбирать из следующих вариантов: "black", "white", "red", "green", "blue",
"yellow", "brown".
Скоро мы научимся выбирать любые цвета.
Например:
line('red', (300, 200), (700, 400))
# 'red' — цвет линии,
# (300, 200) — один конец отрезка,
# (700, 400) — второй конец отрезка
Новость: строчки кода, начинающиеся с символа "#" называются в Python комментариями.
Эти строчки предназначены для пояснения частей кода, чтобы в нём было проще разобраться.
Особенно когда этот код читает не тот, кто его писал.
Всё, что написано в такой строке, не считается программой и не выполняется.
Закомментировать сразу несколько строк кода можно, предварительно выделив эти строки, нажать Ctrl-/ (нажав и удерживая клавишу Ctrl, нажать клавишу /).
Повторное нажатие той же комбинации клавиш убирает комментарии в блоке кода, если он был перед этим закомментирован.
Рисование окружности выполняется с помощью команды circle.
В скобках указываются параметры: цвет, координаты центра окружности и радиус:
circle('yellow', (500, 300), 200)
# 'yellow' — цвет окружности,
# (500, 300) — координаты центра окружности,
# 200 — радиус
Рисование прямоугольника выполняется с помощью команды rect.
В скобках указываются параметры: цвет, координаты левой верхней вершины, ширина (вдоль оси x), высота (вдоль оси y).
То есть, при помощи такой функции можно рисовать только прямоугольники, параллельные осям координат.
Нарисуйте три линии так, чтобы получился треугольник (любой).
C. Три окружности
Теперь нарисуйте три окружности.
Все три центра должны быть разными точками, а окружности вложены друг в друга и не пересекаться.
То есть вторая окружность должна быть строго внутри первой, а третья — внутри второй.
Примерно вот так:
D. Два прямоугольника
Нарисуйте прямоугольник внутри другого прямоугольника так, чтобы между ними получилась ровная "рамка".
Создание более сложных фигур
Рисуя треугольник линиями, можно заметить, что каждую точку мы выписывали дважды, потому что она была концом двух отрезков.
Может быть можно сделать то же самое экономнее?
Нам поможет функция рисования многоугольника polygon.
Первый параметр это уже знакомый нам цвет, после которого надо перечислить координаты вершин многоугольника.
polygon('blue', (300, 200), (700, 300), (500, 400))
# 'blue' — цвет,
# (300, 200) — первая точка многоугольника,
# (700, 300) — вторая точка многоугольника,
# (500, 400) — третья точка многоугольника
Если в многоугольнике больше трёх вершин, нужно учесть, что перечислять вершины в произвольном порядке нельзя.
Представьте, что вы обходите эту фигуру по часовой стрелке или против часовой стрелки.
В функции polygon надо перечислять вершины одним из этих способов, начиная с любой вершины.
Если порядок вершин неверный, то может получиться, например, что-то такое:
Пока мы рисовали только контуры.
Теперь научимся рисовать закрашенные фигуры.
Это может быть круг, прямоугольник и многоугольник.
Для получения закрашенной фигуры есть команды: filled_circle, filled_rect, filled_polygon с такими же параметрами, как и
у неокрашенных фигур.
Нарисуйте три треугольника так, чтобы два из них не пересекались и находились внутри третьего.
Примерно вот так:
F. Фоторамка
Теперь нарисуйте прямоугольную рамку зелёного цвета ('green').
Размер "внешней" части 700x400.
Ширина рамки 100.
Внутренность рамки должна быть чёрной ('black').
Постарайтесь обойтись всего двумя командами из библиотеки drawzero.
Использование переменных
Мы познакомились с основными возможностями библиотеки drawzero.
Теперь пора вспомнить про переменные — они нам скоро пригодятся.
Попробуем нарисовать какую-нибудь простенькую фигуру, например прямоугольник с закруглёнными концами.
Координаты центра окружности это середины левой и правой (вертикальных) сторон прямоугольника и их можно посчитать.
Это и правда несложно.
Но что, если эту картинку надо перерисовать в другом месте или, скажем, сделать исходный прямоугольник чуть выше или шире?
Это по-прежнему будет несложно сделать, но придётся пересчитывать координаты центров окружностей. А если картинка такая?
Всего-то — сделали полоски чуть шире.
Пришлось пересчитать почти все координаты.
Теперь представим себе, что это всё надо будет пересчитать несколько раз.
Напишем ту же программу по шагам, но для вычисления координат станем использовать переменные.
Что нам нужно знать об этой фигуре, для того, чтобы её нарисовать?
Нам надо знать где она находится и её главные размеры.
Место можно задать по-разному.
Мы запомним координаты левого верхнего угла.
Размеры фигуры определяются размерами прямоугольника.
А радиус круга это половина его высоты, поэтому размеров прямоугольника достаточно.
Не поленимся ввести для радиуса отдельную переменную, код так будет лучше читаться.
left = 300
top = 500
w = 500
h = 150
r = h // 2
Итак, всё готово для рисования.
Теперь пишем те же самые вызовы функций рисования прямоугольников и кругов, но для вычисления всех координат используем только переменные.
Надо только придумать — как вычислить координаты вертикального прямоугольника, используя имеющиеся переменные?
Очень полезно нарисовать картинку на бумаге и разобраться, откуда берутся формулы в программе, представленной ниже.
from drawzero import *
# left, top — координаты левого верхнего угла прямоугольника
left = 300
top = 500
# w, h — ширина и высота прямоугольника; r — радиус окружности
w = 500
h = 150
r = h // 2
filled_rect('yellow', (left, top), w, h)
filled_circle('yellow', (left, top + r), r)
filled_circle('yellow', (left + w, top + r), r)
filled_rect('yellow', (left + w // 2 - r, top - w // 2 + r), h, w)
filled_circle('yellow', (left + w // 2, top - w // 2 + r), r)
filled_circle('yellow', (left + w // 2, top + w // 2 + r), r)
В нашей программе стало в 2 раза больше строк, зато перерисовать эту фигуру в другом месте или поменять её размер стало проще простого.
Надо только изменить нужные переменные.
И всё!
Все координаты и размеры пересчитаются автоматически.
G. Два пластыря
В аптечке есть два пластыря в форме креста со скруглёнными краями.
В коде ниже есть пример одного из них, размер второго (ширина) равен 300.
Подберите место, куда надо «наклеить» эти два пластыря, чтобы закрыть все порезы, которые отмечены красными треугольниками.
Используйте для перемещения переменные, объявленные в коде.
Пропорции должны быть сохранены (меньшая сторона в 5 раз меньше большей).
from drawzero import *
# это порезы, их не нужно трогать
filled_polygon('red', (260, 340), (310, 310), (320, 390))
filled_polygon('red', (510, 295), (620, 305), (590, 405))
filled_polygon('red', (720, 600), (655, 700), (722, 730))
filled_polygon('red', (550, 550), (510, 350), (570, 430))
filled_polygon('red', (510, 70), (517, 134), (580, 200))
filled_polygon('red', (630, 340), (730, 360), (630, 390))
filled_polygon('red', (690, 820), (710, 760), (680, 780))
filled_polygon('red', (750, 690), (830, 710), (730, 720))
filled_polygon('red', (520, 620), (590, 610), (550, 640))
# left, top — координаты левого верхнего угла прямоугольника
# w, h — большая и меньшая стороны прямоугольника r — радиус окружности
# параметры ниже нужно подобрать
left = 220
top = 650
w = 500
h = w // 5
r = h // 2
filled_rect('yellow', (left, top), w, h)
filled_circle('yellow', (left, top + r), r)
filled_circle('yellow', (left + w, top + r), r)
filled_rect('yellow', (left + w // 2 - r, top - w // 2 + r), h, w)
filled_circle('yellow', (left + w // 2, top - w // 2 + r), r)
filled_circle('yellow', (left + w // 2, top + w // 2 + r), r)
H. Скруглим углы
Давайте теперь сделаем не такие острые углы.
Нарисуйте такую картинку:
Только "скруглить" угол можно по-разному.
В идеальной фоторамке ширина должна быть одинаковой и в углах тоже.
Но как понять, что такое "ширина рамки в углу"?
Давайте так: ширина это расстояние от точки на внешней границы к ближайшей к ней точке на внутренней.
Изучите картинку со схемой и вы поймёте, что надо нарисовать (и в какой последовательности).
А ещё хорошо бы сделать всё на белом фоне!
Для того, чтобы залить весь экран одним цветом, используйте команду `fill`.
Например, заливка красным выглядит так:
fill('red')
I. Мишень
Хм, простая картинка — колечки одинаковой ширины.
Ясно, что рисовать чёрные 'black' и белые 'white' круги, но в какой последовательности?
Справитесь?
Тут, кстати, и циклы могут пригодиться :)
Все числовые данные в этой и следующих программах "спрячьте" в переменные, которые должны быть определены в начале программы. Постарайтесь дать переменным такие названия, чтобы по ним можно было определить, что именно обозначает данная переменная. Используйте английские слова или их сокращения.
J. Забор
Хорошо, мишень нарисовали, а куда её повесить?
Может на забор?
Все числовые данные в этой и следующих программах "спрячьте" в переменные, которые должны быть определены в начале программы. Постарайтесь дать переменным такие названия, чтобы по ним можно было определить, что именно обозначает данная переменная. Используйте английские слова или их сокращения.
JA. Клеточки
Разбейте всё окно на одинаковые прямоугольные клетки. Программа считывает два числа: $N1$ - число вертикальных линий и $N2$ - число горизонтальных линний.
Размер окна - $1000 \times 1000$ (его тоже нужно запомнить в переменной). Лишние линии рисовать не надо.
Картинка для $N1 = 10, N2 = 7$ должна выглядеть так:
А если нацело не делится?
Если для вычисления расстояния между линиями мы будем использовать целочисленное деление, то может оказаться ненулевой остаток, и линии будут распределены неравномерно. Если же расстояние между линиями будет дробным числом, то линии распределятся равномерно. При рисовании координаты концов будут округляться до целого числа пикселей, но от расчётного значения будут отличаться не более, чем на полпикселя.
JB. Парабола
Картинка нарисована с помощью отрезков, их огибающие - фрагменты парабол. Программа получает на вход число
$N$ - количество отрезков с одной стороны картинки (вторая - симметричная). Расстояния между концами отрезков по одной стороне одинаковы. На картинке для $N = 5$ видно, как нужно рисовать отрезки.
Размер окна - $1000 \times 1000$.
JC. Наклонные клеточки
Расчертите окно наклонными квадратиками.
Программа получает на вход число $D$ - диагональ квадратика. Если рисовать отрезки, концы которых находятся за пределами окна, то тоже получится такая картинка. Но в этой задаче требуется, чтобы концы всех отрезков были ровно на границе окна.
Размер окна - $1000 \times 1000$.
JD. Прямоугольники
Программа получает на вход три числа: $X < 500$, $Y < 500$ - координаты верхнего левого угла самого большого прямоугольника, $D$ - расстояние между прямоугольниками.
Размер окна - $1000 \times 1000$.
Работа с цветами
Пора научиться создавать свои цвета.
Каждый цвет состоит из трёх компонентов: красного, зелёного и синего.
Наверняка вам встречалась аббревиатура RGB (сокращение от Red, Green и Blue).
Представьте, что в абсолютно тёмной комнате вы светите на стену тремя фонариками: красным, зелёным и синим.
У каждого есть регулировка интенсивности — число от 0 (фонарик выключен) до 255 (фонарик светит максимально ярко).
Все фонарики светят в одну и ту же точку стены и в зависимости от настроек интенсивности всех трёх фонариков на стене получается пятно определённого цвета. Вот
несколько примеров:
R = 0, G = 0, B = 0 — все фонарики выключены, на стене чёрное пятно (которое и так не видно, потому что в комнате темно);
R = 255, G = 255, B = 255 — все фонарики включены на максимальную мощность, на стене яркое белое пятно;
R = 100, G = 100, B = 100 — все фонарики включены, имеют одинаковую (но небольшую) интенсивность, на стене тёмно-серое пятно;
R = 255, G = 0, B = 0 — красный фонарик включен полностью, остальные выключены, на стене яркое красное пятно;
R = 255, G = 0, B = 255 — красный и синий фонарики включены полностью, зелёный выключен, на стене яркое фиолетовое пятно;
В библиотеке drawzero можно определить свой цвет при помощи тройки чисел, взятой в скобки.
Эту тройку можно запомнить в переменной и использовать при вызове всех функций рисования из модуля drawzero.
Цвета, приведённые в примере выше можно было сохранить так:
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
violet = (255, 0, 255)
Нарисуем картинку из предыдущего параграфа, определив свои цвета:
Задайте свои цвета с помощью переменных и нарисуйте радугу.
L. Даже так можно?
Нарисуйте такую фигуру:
Надо обойтись 5 вызовами функций из модуля drawzero.
LA. Шахматная доска
Программа получает на вход три числа: N - число клеток (по горизонтали и по вертикали одинаковое), SIZE - размер одной клетки, MARGIN - ширина внешней рамки. Цвета выберите на свой вкус.
Каждый квадратик - отдельный прямоугольник.
Внутри цикла должен быть ровно один вызов функции из библиотеки drawzerow.
LB. Цветные прямоугольники
Программа получает на вход три числа: $X < 500$, $Y < 500$ - координаты верхнего левого угла самого большого прямоугольника, $N$ - число прямоугольников. Цвета равномерно меняются от синего (0, 0, 255) до голубого (0, 255, 255).
Размер окна - $1000 \times 1000$.
На первой картинке $X = 100, Y = 200, N = 5$, на второй $X = 250, Y = 50, N = 25$.
Как сделать так, чтобы цвета менялись равномерно?
Надо найти, на какую величину должна меняться яркость зелёного цвета на каждом шаге, и добавлять её к яркости текущего цвета. Вычисленная так яркость будет действительным числом, поэтому при указании цвета её необходимо округлять с помощью функции round (эта функция с одним параметром даёт в ответе целое число).
Что-то всё равно не получается...
При вычислении длины интервала надо не забывать, что число интервалов не равно числу их граничных точек (в данном случае числу разных раскрашенных прямоугольников).
LC. Цветная лесенка - 1
Программа получает на вход три числа: $W, H$ - ширина и высота лестницы, $N$ - число ступенек. Цвета равномерно меняются от лилового (255, 0, 255) до синего (0, 0, 255).
Размер окна - $1000 \times 1000$.
На первой картинке $W = 700, H = 600, N = 5$, на второй $W = 900, H = 800, N = 25$.
Как сделать так, чтобы цвета менялись равномерно?
Надо найти, на какую величину должна меняться яркость красного цвета на каждом шаге, и вычитать её из яркости текущего цвета. Вычисленная так яркость будет действительным числом, поэтому при указании цвета её необходимо округлять с помощью функции round (эта функция с одним параметром даёт в ответе целое число).
Что-то всё равно не получается...
При вычислении длины интервала надо не забывать, что число интервалов не равно числу их граничных точек (в данном случае числу разных раскрашенных прямоугольников).
LD. Цветная лесенка - 2
Программа получает на вход два числа: $N$ - число ступенек, $W$ - ширина одной ступеньки. Цвета равномерно меняются от красного (255, 0, 0) до жёлтого (255, 255, 0), потом до зелёного (0, 255, 0).
Размер окна - $1000 \times 1000$.
На первой картинке $N = 5, W = 200$, на второй $N = 15, W = 100$.