Освой Processing играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Фигуры

Чтобы создавать красивые программы, нужно уметь рисовать фигуры. Начнём с основ. Сначала немного о системе координат. Нулевая точка окна в Processing находится в левом верхнем углу. Функция size() устанавливает размеры окна вашего скетча. Первый параметр присваивает значение встроенной переменной width (ширина), второй - встроенной переменной height (высота).

Для простых примеров мы пока временно не будем использовать функцию draw(), а весь код будем писать в функции setup().

Для рисования точки используется функция point(). Здесь также нужно указать два параметра - координаты точки.

Создадим окно размером 480 на 120 и поместим точку в центре (разделим размеры окна пополам).


void setup() {
  size(480, 120);
  point(240, 60);
}

Точка очень маленькая, разглядеть её сложно. Но вы постарайтесь. Зря что-ли старались.

Если вы хотите нарисовать точку в нижнем правом углу, то можете совершить ошибку, написав код.


point(480, 120);

На самом деле, нужно использовать координаты (479, 119), т.е. отнять единицу от размеров окна.

Чтобы нарисовать линию, нужно вызвать функцию line() c четырьмя параметрами - координаты начальной и конечной точки. А программа сама нарисует линию между ними. Разделим окно программы пополам. Удалим код для рисования точки, а вместо неё напечатаем другой код.


line(0, 60, 480, 60);

Получим следующую картинку.

line()

Подумайте, как нарисовать вертикальную линию. А по диагонали?

А что если нарисовать много параллельных линий по вертикали и горизонтали через одинаковые промежутки? Тогда получим сетку. Чтобы не повторять один и тот же код много раз, создадим отдельную функцию для рисования сетки, а в ней применим два цикла. Код получится намного короче.


void setup()
{
  size(500, 300);
} 

void draw()
{
  drawGrid();
} 

void drawGrid()
{
  stroke( 225 );

  for ( int i = 0; i < 64; i++ ) {
    line(i * 10, 0, i * 10, height );
  } 

  for ( int i = 0; 
    i < 48; 
    i++ ) {
    line( 0, i * 10, width, i * 10 );
  }
}
Grid

А мы идём дальше и попробуем нарисовать треугольник. Для этого существует функция triangle() с шестью параметрами - координаты вершин треугольника. Наугад выбираем различные числа. Получился треугольник. Захотелось нарисовать рядом близнеца. Как это сделать? Чтобы сдвинуть второй треугольник вправо, прибавляем к параметрам, которые относятся к координате X, некоторое значение. Это будет смещением. Проверяем.


void setup()
{
  size(480, 120);
  triangle(10, 10, 100, 20, 40, 90);
  // Сдвигаем второй треугольник вправо на 90 пикселей
  triangle(10 + 90, 10, 100 + 90, 20, 40 + 90, 90);
} 

void draw(){ } 
triangle()

Для многоугольников с четырьмя точками нужно уже восемь параметров. А функция называется quad().


void setup()
{
  size(480, 120);
  quad(20, 10, 30, 40, 90, 25, 20, 90);
} 

void draw(){} 
quad()

Мы могли бы с помощью этой функции нарисовать и прямоугольник. Но писать восемь параметров слишком утомительно. К счастью, Processing немного понимает в геометрии. Если указать только координату первой точки, а потом ширину и высоту, то дальше программа сама всё рассчитает и нарисует. Функция называется rect(). Проверим.


void setup()
{
  size(480, 120);
  rect(10, 10, 230, 100);
} 

void draw(){} 
rect()

Как нарисовать квадрат, вы сами догадаетесь.

Функция ellipse() нам уже знакома по первому уроку. Для рисования эллипса нужно указать центр, ширину и высоту. Стоит отметить, что можно указывать и отрицательные значения координат. Тогда может получиться, что в окне вы увидите только часть фигуры. Например, часть эллипса.


void setup()
{
  size(480, 120);
  ellipse(280, -100, 400, 400);
} 

void draw(){} 
ellipse()

Также можно нарисовать дугу (сектор) с помощью функции arc(). Опять указываем центр, а также ширину и высоту. И вдобавок указываем начальный и конечный угол в радианах. Но с радианами работать не очень удобно. Что будет если указать значения 0 и 2? Для величин 180, 45, 90 и 360 градусов можно использовать готовые константы в радианах: PI, QUARTER_PI, HALF_PI, TWO_PI. Попробуем несколько вариантов.


void setup() {
  size(480, 120);
  arc(50, 60, 170, 80, 0, 2);
  arc(150, 60, 170, 80, 0, HALF_PI);
  arc(350, 60, 170, 80, 0, PI + HALF_PI);
}
Arc

Если вам известно значение в градусах, то можете его перевести в радианы с помощью функции radians().


arc(90, 60, 80, 80, 0, radians(90));

Если вы рисуете много фигур, которые накладываются друг на друга, то сверху будет та фигура, чей код в вашей программе будет последним.

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


strokeWeight(3);
ellipse(175, 60, 90, 90);

Функция strokeJoin() определяет вид соединения линий (углы), а функция strokeCap() - начальную и конечную точки линий.


strokeJoin(ROUND); // скруглить
strokeJoin(BEVEL); // сделать откос
strokeCap(SQUARE); // концы линий - квадратные
strokeCap(ROUND); // скруглить концы линий

За сглаживание отвечает функция smooth(). Существует парная ей функция noSmooth(), отключающая сглаживание.

Для цветов используются функции background(), fill(), stroke(), у которых нужно указать цвет в пределах от 0 (чёрный) до 255 (белый). Промежуточные величины будут оттенками серого. Можно отключить обводку (функция noStroke()) или сделать фигуру прозрачной функцией noFill():


void setup() {
  size(480, 120);
  smooth();
  fill(153);
  ellipse(130, 80, 150, 150);
  noFill();
  ellipse(228, -16, 200, 200);
  noStroke();
  ellipse(268, 118, 200, 200);
}

Также можно указывать цвет. В этом случае используются три параметра:


background(0, 26, 51); // темно-синий цвет
fill(255, 0, 0); // красный

Первая функция закрасит окно, вторая - фигуру, которая будет рисоваться после этой функции.

Можно использовать цветовую палитру через меню Tools | Color Selector.

Если добавить четвёртый параметр, то можно управлять прозрачностью.

Также можно нарисовать сложную фигуру, например, стрелку. Начните создание фигуры с функции beginShape(). Функция vertex() используется для определения x и y-координат фигуры. Функция endShape() ставится в конце описания фигуры и сигнализирует об окончании создания фигуры.


void setup() {
  size(480, 120);
  smooth();
  beginShape();
  vertex(180, 82);
  vertex(207, 36);
  vertex(214, 63);
  vertex(407, 11);
  vertex(412, 30);
  vertex(219, 82);
  vertex(226, 109);
  endShape();
}
Arrow

Когда вы запустите пример, вы увидите, что первая и последняя точки не соединены. Чтобы сделать это, добавьте слово CLOSE как параметр функции endShape():


endShape(CLOSE);

Преимущество использования функции vertex() для создания фигур заключается в возможности построения фигур со сложной структурой. Одна программа на Processing может нарисовать тысячи линий для отображения на экране самых невероятных фигур.

Звезда и цветок

Нарисуем звезду. Для неё создадим отдельную функцию star().


void setup()
{
  size( 400, 400 );
  smooth();
  frameRate(1);
} 

void draw() {
  translate(200, 200);
  star(5, 90, 190);
} 

void star( int numSpikes, float innerRadius, float outerRadius )
{
  int numVertices = numSpikes * 2;
  float angleStep = TWO_PI / numVertices;
  beginShape();
  
  for ( int i = 0; i < numVertices; i++ ) {
    float x, y;
    if ( i % 2 == 0 ) {
      x = cos( angleStep * i ) * outerRadius;
      y = sin( angleStep * i ) * outerRadius;
    } else {
      x = cos( angleStep * i ) * innerRadius;
      y = sin( angleStep * i ) * innerRadius;
    } 
    vertex( x, y );
  } 
  endShape(CLOSE);
}

Функция звезды имеет три параметра: одно целое число для количества лучей и два параметра для внутреннего и внешнего радиуса звезды.

Star

Добавим функцию для рисования цветка.


void flower( int numLeafs, float innerRadius, float outerRadius )
{
  float angleStep = TWO_PI / numLeafs;
  beginShape();
  float startX = cos( 0 ) * innerRadius;
  float startY = sin( 0 ) * outerRadius;
  vertex( startX, startY );
  for ( int i = 0; i < numLeafs; i++ ) {
    float cx1 = cos( angleStep * i ) * outerRadius;
    float cy1 = sin( angleStep * i ) * outerRadius;
    float x2 = cos( angleStep * (i + 1) ) * innerRadius;
    float y2 = sin( angleStep * (i + 1) ) * innerRadius;
    float cx2 = cos( angleStep * (i + 1) ) * outerRadius;
    float cy2 = sin( angleStep * (i + 1) ) * outerRadius;
    bezierVertex( cx1, cy1, cx2, cy2, x2, y2 );
  } 
  endShape( CLOSE );
}

Вызовем вместо звезды.


void draw() {
  translate(200, 200);
  flower(5, 90, 190);
}
Flower

А теперь нарисуем звёзды и цветы вместе.


void draw() {
  background( 0 );
  noStroke();
  for ( int i = 0; i < 75; i++ ) {
    int numPoints = floor( random( 4, 8 ) );
    float innerRadius = random( 20, 40 );
    float outerRadius = random( 50, 100 );
    pushMatrix();
    translate( random( width ), random( height ) );
    if ( random( 100 ) < 50 ) {
      fill( 255, 255, 0, 64 );
      star( numPoints, innerRadius, outerRadius );
    } else {
      fill( 255, 0, 0, 64 );
      flower( numPoints, innerRadius, outerRadius );
    } 
    popMatrix();
  }
}

Мы получим анимацию из множества фигур. На скриншоте один из кадров.

Stars and flowers

На главную страницу Processing

Реклама