В этом задании вы нарисуете человечка и единорога с помощью языка программирования JavaScript, блокнота, браузера и удобной библиотеки.

Сдавать задание нужно на уроке.

0) Поднятие окружения

Скачайте архив библиотечки отсюда и разархивируйте его в какую-нибудь папку.

Там куда вы разархивировали библиотечку зайдите в подпапку p5-zip/empty-example. Откройте sketch.js любым текстовым редактором, например Notepad++ или Sublime Text:

function setup() {

}

function draw() {
  
}

Это две пока что пустые функции:

  • Первая функция setup выполняется в начале работы приложения, например она может что-то настроить или подготовить для работы вашей программы (setup переводится как “настроить”).
  • Вторая функция draw - выполняется каждый раз для отображения нового кадра вашей программы, т.е. эта функция рисует новый кадр (draw переводится как “рисовать”).

Итак, в setup хочется настроить экран (так называемый холст, на котором будем рисовать) и зарисовать весь фон одним цветом. А в draw нарисовать какие-нибудь геометрические фигуры:

function setup() {
    createCanvas(640, 480);   // Указываем размер холста на котором будем рисовать
    background(50, 50, 100);  // Зарисовываем фон одним цветом
}

function draw() {
    var ellipseColor = color(255, 255, 0); // Создаем переменную хранящую цвет
    fill(ellipseColor);                    // Указываем цветом заливки - цвет из переменной ellipseColor
    var centerX = 320;                     // Пример того, как можно объявлять переменные 
    var centerY = 240;                     // Ключевое слово var перед названием переменной - от слова variable (в переводе - переменная)
    ellipse(centerX, centerY, 200, 100);   // Рисуем эллипс с центром в точке (centerX, centerY)=(320, 240) и размером 200x100
}

Это уже полноценная программа, которая создает холст размера 640x480 и рисует на нем эллипс.

Чтобы увидеть результат - достаточно открыть p5-zip/empty-example/index.html в браузере (например дважды кликнув по этому файлу). По мере редактирования sketch.js чтобы увидеть новый результат: нужно сохранить файл sketch.js и обновить страничку в браузере (Ctrl+R или F5).

Обратите внимание, что в системе координат холста ось абсцисс (X) идет вправо, а ось ординат (Y) - вниз:

Unicorn

1) Функции

Допустим мы хотим сделать функцию “нарисовать человечка”:

function setup() {
    // Здесь нужно указать размер холста на котором вы будете рисовать
    // А так же заполнить холст одним фоновым цветом
}

function draw() {
    drawHuman(320, 240);      // Рисуем человечка вызовом функции, которая объявлена ниже, при этом мы передаем в функцию два аргумента - координаты центра человечка
}

function drawHuman(x, y) {
    translate(x, y);          // Смещаем начало отсчета координат из текущего положения (верхний левый угол) на x пикселей вправо и y пикселей вниз
    ellipse(0, -40, 20, 20);  // Голова относительно текущей системы координат в точке (0, -40), т.е. на 40 пикселей выше чем (x, y) и с диаметром 20
    line(0, -30, 0, 30);      // Тело идет от нижней точки головы (0, -30) до точки (0, 30)
    line(0, -20, -20, -10);   // Рука слева
    // Доделайте эти вызовы:
    // line(...); // Рука справа
    // line(...); // Нога слева
    // line(...); // Нога справа
}

Доделайте функцию drawHuman, чтобы получился человечек.

Если добавить после вызова translate вызов rotate(PI / 4), то текущая система координат повернется на 45 градусов по часовой стрелке, а значит и дальнейшая отрисовка человечка в этой системе приведет к тому, что человечек повернулся на эти же 45 градусов по часовой стрелке.

Убедитесь что вы поняли, как работает translate и rotate. Что будет если отрисовка частей человечка не симметрична относительно точки (0, 0)? Как он будет крутиться в таком случае?

2) Единорог

Теперь создайте функцию drawUnicorn, которая рисует Единорога из палочек и эллипсов, похожего на этого:

Unicorn

Т.е. у вас должны быть нарисованы:

  • Тело
  • Шея и голова
  • Рог
  • Четыре ноги
  • Хвост

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

3) Много людей, много единорогов

Теперь когда у вас есть функция рисующая человека и функция рисующая единорога, попробуйте нарисовать обоих примерно таким образом:

function draw() {
    var canvasWidth  = 640; // Ширина холста
    var canvasHeight = 480; // Высота холста
    drawHuman(canvasWidth/4, canvasHeight/2);     // Рисуем человечка слева
    drawUnicorn(canvasWidth*3/4, canvasHeight/2); // Рисуем единорога справа
}

Что произойдет если вы поменяете местами вызовы drawHuman и drawUnicorn?

Что произойдет если вы оставите лишь вызов drawUnicorn-функции?

Почему так произошло?

Дело в том, что когда вы в функции делаете вызов translate(...), то сдвигается весь холст. И не только на время выполнения этой функции, но и на все остальное время работы программы.

Поэтому чтобы функция не двигала холст и не мешала таким образом другой функции - нужно вернуть холст в изначальное положение. Т.е. если в начале функции было сделано например translate(x, y), то в конце функции надо сдвинуть холст обратно: translate(-x, -y).

Но т.к. менять и откатывать изменения в состоянии холста (точка отсчета, поворот) нужно часто, то есть более удобный способ:

для сохранения и восстановления состояния есть метод push и pop соответственно:

        push();                      // Сохраняем текущую систему координат
        translate(239, 478);         // Сдвигаем точку отсчета системы координат
        rotate(PI / 2);              // Поворачиваем систему координат на 90 градусов (т.к. PI радиан = 180 градусов)
        ...
        Какое-то рисование с текущей системой координат
        ...
        pop();                       // Восстанавливаем состояние системы координат (точку отсчета и ориентацию) к моменту вызова соответсвующего push()

4) Очень много людей и единорогов (введение в for)

Чтобы создать очень много людей и единорогов - можно воспользоваться циклами. Вот пример простейшего цикла:

var canvasWidth = 640;
var canvasHeight = 480;

function setup() {
    createCanvas(canvasWidth, canvasHeight);
    background(50, 50, 100);
}

function draw() {
    var i;
    for (i = 1; i <= 10; i++) { 
        line(i*10, canvasHeight*1/4, i*10, canvasHeight*3/4);
    }
}

Сделайте так, чтобы линии занимали холст равномерно (подсказка: используйте переменную canvasWidth по аналогии с canvasHeight*1/4).

Создайте по хотя бы два ряда из людей и единорогов.

5) Бегущий единорог (введение в if)

Давайте теперь добавим анимации. Вот простой вариант

var canvasWidth = 640;
var canvasHeight = 480;

function setup() {
    createCanvas(canvasWidth, canvasHeight);
    background(50, 50, 100);

    x = 10; // Изначальное положение шарика
}

var x; // Так как положение шарика от кадра к кадру будет меняться, то нужно хранить его в глобальной переменной

function draw() {
    ellipse(x, canvasHeight/2, 24, 24);
    x += 1;
}

Возникло две проблемы:

  • Шарик оставляет за собой след
  • Шарик уходит за пределы холста
  1. Чтобы очищать экран каждый раз - нужно перед тем как рисовать эллипс вызывать функцию background (она заливает весь экран цветом и пока что вызывалась лишь на этапе настройки программы, но теперь она нужна нам в начале каждого кадра чтобы очищать экран от предыдущего кадра).

  2. Чтобы возвращать шарик в начало как только он выходит за пределы экрана, можно добавить в конец draw:

    if (x > canvasWidth) {
        x = 0;
    }

Сделайте теперь:

  • Бегущего человечка
  • Бегущего единорога
  • Сценку в которой бежит много единорогов и человечков в разные стороны