Продолжаем свое путешествие в мир программируемой графики. Давайте вместо кругов используем квадраты. Посмотрим насколько сильно это изменит нашу графику. Кстати, кому интересно узнать поскорее какие еще готовые 2D фигуры доступны «из коробки», то загляните на эту страницу. В разделе 2D Primitives вы найдете описание всех фигур и примеры кода. Уберем все лишнее из кода. Оставим только суть. А чтобы квадрат рисовался из центра курсора, мы добавили строку rectMode(center).
def setup(): size(1000,200) background(0) stroke(0) def draw(): if mousePressed: strokeWeight(1) fill(255) rectMode(CENTER) rect(mouseX, mouseY,100,100)
Линия
До сих пор мы рисовали последовательность простых фигур, не связанных друг с другом. Давайте теперь попробуем рисовать так, чтобы новая фигура начиналась там, где закончилась предыдущая. Так мы сможем нарисовать непрерывную линию. Правда, для этого нам придется помнить предыдущее положение курсора. Для этого создадим две переменных oldX и oldY. Эти переменные нам понадобятся внутри функций draw и внутри функции mousePressed. Но изначально, внутри любых функций внешние переменные не видны. Поэтому, нам нужно явно заставить их видеть эти переменные. Для этого просто напишем слово global (глобальный), а после, через запятую, перечислим все, что хотим видеть.
oldX = 0; oldY = 0; def setup(): size(1000,200) background(0) stroke(255) strokeWeight(2) def draw(): global oldX, oldY if mousePressed: line(mouseX, mouseY, oldX, oldY) oldX = mouseX oldY = mouseY def mousePressed(): global oldX, oldY oldX = mouseX oldY = mouseY
Цветная линия
Давайте посмотрим какие возможности нам открывает этот код. Попробуем что-нибудь изменить в нем. Например толщину линии и цвет.
oldX = 0; oldY = 0; def setup(): size(1000,200) background(0) def draw(): global oldX,oldY if mousePressed: stroke(random(255),random(255),random(255)) strokeWeight(30) line(mouseX, mouseY,oldX,oldY) oldX = mouseX oldY = mouseY def mousePressed(): global oldX,oldY oldX = mouseX oldY = mouseY
Не перестаю удивляться результату, осознавая, что это вектор. Т.е. графика, которая не теряет качества при любом масштабировании. И не могу вспомнить ни одну графическую программу, которая дает такую свободу в работе с кистью.
Шарф Гарри Поттера
У линии в процессинге есть несколько свойств. Давайте что-нибудь поменяем. Например свойство strokeCap(). Это свойство может принимать три параметра (SQUARE, ROUND и PROJECT). Я поставил SQUARE. Возмем код из примера «Цветная линия» и поменяем только одну строчку (строка 7). Но как все изменилось!
oldX = 0; oldY = 0; def setup(): size(1000,200) background(0) strokeCap(SQUARE) def draw(): global oldX,oldY if mousePressed: stroke(random(255),random(255),random(255)) strokeWeight(30) line(mouseX, mouseY,oldX,oldY) oldX = mouseX oldY = mouseY def mousePressed(): global oldX,oldY oldX = mouseX oldY = mouseY
Можно попробовать менять один канал (например red) каждый раз, когда мы двигаем мышкой (внутри функции draw, строчка 15), а другие два (green, blue) только один раз, при нажатии мышкой на холст (внутри функции mousePressed).
oldX = 0; oldY = 0; r=0 g=0 b=0 def setup(): size(1000,200) background(0) strokeCap(SQUARE) def draw(): global oldX,oldY,r,g,b if mousePressed: stroke(random(255),g,b) strokeWeight(30) line(mouseX, mouseY,oldX,oldY) oldX = mouseX oldY = mouseY def mousePressed(): global oldX,oldY,r,g,b oldX = mouseX oldY = mouseY g=random(200)+150 b=random(200)+150
Или давайте сразу зададим два цвета. Только будем менять их в случайном порядке. Для этого у нас есть функция random(1). Она выдает на числа от 0 до 1. И если это число больше 0.5, то берем один цвет, а если меньше, то другой.
oldX = 0; oldY = 0; def setup(): size(1000,200) background(0) strokeCap(SQUARE) def draw(): global oldX,oldY garry = color(247, 218, 58) potter = color(77, 28, 42) if mousePressed: if random(1)>.5: stroke(garry) else: stroke(potter) strokeWeight(50) line(mouseX, mouseY,oldX,oldY) oldX = mouseX oldY = mouseY def mousePressed(): global oldX,oldY oldX = mouseX oldY = mouseY
Настроение
И еще один пример того, что можно сделать с линией. Для этого снова, вместо random() воспользуемся функцией noise(). И не забудем, что для ее работы нам нужна постоянно увеличивающаяся переменная (строчки 2 и 10).
oldY = 0; xoff = 0.0 def setup(): size(1000,200) background(0) def draw(): global oldX,oldY,xoff xoff = xoff + .01 if mousePressed: stroke(noise(xoff+1)*255,noise(xoff)*255,200) strokeWeight(noise(xoff+1)*30) line(mouseX, mouseY,oldX,oldY) oldX = mouseX oldY = mouseY def mousePressed(): global oldX,oldY oldX = mouseX oldY = mouseY
Получилась вполне себе такая настроенческая кисточка. Вы рисуете, а программа сама плавно меняет оттенок. Интересная идея для графического редактора.
Творческое задание
Возьмите код из раздела «Шарф Гарри Поттера» и измените его по своему вкусу. Наша задача с помощью этой кисточки нарисовать какую-нибудь абстрактную композицию размером (1000x1200px, вертикальную). Я подобрал для вас немного примеров для вдохновения. Подробнее их можно посмотреть здесь на доске Pinterest. Ниже приведу несколько вариантов готовых композиций.
Размер кисточки
Вам здесь понадобится менять по ходу ширину кисточки. Этого мы еще не обсуждали. Давайте это исправим. Пусть, при нажатии на цифр от 1-9, у нас будет меняться размер кисточки. Возьмем, например, код из «Шарф Гарри Поттера». Добавим в него глобальную переменную brushSize (строка 3). И начнем «слушать» клавиатуру (строка 29). Здесь мы проверяем, что нажата именно цифра, а затем умножаем ее на 10px и присваеваем переменной brushSize. Ну и, конечно, поставим эту переменную в качестве параметра strokeWieght(brushSize).
oldX = 0; oldY = 0; brushSize=10 def setup(): size(1000,200) background(0) strokeCap(SQUARE) def draw(): global oldX,oldY,brushSize garry = color(247, 218, 58) potter = color(77, 28, 42) if mousePressed: if random(1)>.5: stroke(garry) else: stroke(potter) strokeWeight(brushSize) line(mouseX, mouseY,oldX,oldY) oldX = mouseX oldY = mouseY def mousePressed(): global oldX,oldY oldX = mouseX oldY = mouseY def keyPressed(): global brushSize if(key.isnumeric()): brushSize = int(key)*10
Теперь, в процессе рисования, мы можем нажимать на клавиатуре цифры и наша кисточка будет менять размер.
Сохранение в pdf
Для уменьшения размера кода, я не добавляю в него строчки для сохранения в pdf. Но вам необходимо эти строки добавить, чтобы сохранить готовую работу. Привожу код полностью, вместе с возможностью сохранения. За сохранение отвечают строки 1, 8 и 36.
add_library('pdf') oldX = 0; oldY = 0; brushSize=10 def setup(): beginRecord(PDF, "everything-##.pdf"); size(1000,200) background(0) strokeCap(SQUARE) def draw(): global oldX,oldY,brushSize garry = color(247, 218, 58) potter = color(77, 28, 42) if mousePressed: if random(1)>.5: stroke(garry) else: stroke(potter) strokeWeight(brushSize) line(mouseX, mouseY,oldX,oldY) oldX = mouseX oldY = mouseY def mousePressed(): global oldX,oldY oldX = mouseX oldY = mouseY def keyPressed(): global brushSize if(key.isnumeric()): brushSize = int(key)*10 if(key == 's'): endRecord() exit()
Продолжение. Создадим свой Painter. Часть 3.