Дидактические цели
Короткий курс творческого программирования с p5.js — библиотекой JavaScript для рисования и анимации на холсте. Ученик начинает с анимированного рисунка, на который уходит всего несколько строк кода, и от зала к зале осваивает элементы, из которых такое пишется: setup() и draw(), фигуры, цвета, переменные, условия, циклы, текст, собственные функции и массивы. Курс завершается двумя полноценными скетчами: системой частиц и рекурсивным фрактальным деревом.
В лабе 35 залов, и большинство идёт в трёх тактах: зал наблюдения, зал «Проверьте себя» и, по некоторым темам, зал «Напишите код».
- Наблюдение. Панель с кодом с одной стороны и работающим холстом с другой. Ученик двигает ползунки и видит, как одновременно меняются рисунок и числа в коде. Код он не правит: меняются только значения.
- Проверьте себя. Один-два вопроса с выбором ответа и, в большинстве залов, задача расставить строки короткой программы по порядку.
- Напишите код. Одно или несколько полей, где ученик вводит строку кода (вызов
функции p5.js, оператор, условие, заголовок
for, функцию), и она проверяется. Если верно, результат появляется на холсте, когда задание что-то рисует.
Ставок нет. В залах наблюдения нужно только смотреть и пробовать элементы управления; залы с вопросами и залы с вводом кода считаются пройденными, когда ученик выполнил всё, что в них требуется.
Залы по темам: 1 введение; 2-3 setup(); 4-5 draw(); 6-7 фигуры; 8-10 fill,
stroke и noStroke; 11-12 цвета RGB; 13-15 глобальные и локальные переменные;
16-17 системные переменные; 18-20 if; 21-23 for; 24-25 text(); 26-28
собственные функции; 29-31 массивы; 32-33 forEach, map и filter; 34-35
проекты.
Чему учимся
Ученик учится читать программу на p5.js и писать собственные фрагменты, усваивая идею, что код описывает происходящее в каждом кадре.
- Знать, когда выполняется каждая часть:
setup()один раз, в начале;draw()около 60 раз в секунду, аframeCountсчитает кадры (залы 2-5). - Рисовать с помощью
ellipse,rectиlineв системе координат с началом в левом верхнем углу и задавать цвет с помощьюfill,strokeиnoStroke(залы 6-10). - Понимать цвет RGB как три числа от 0 до 255 (залы 11-12).
- Различать глобальные переменные, которые сохраняются между кадрами, и локальные,
которые сбрасываются при каждом вызове, и пользоваться
+=,-=и*=(залы 13-15). - Использовать то, что p5.js уже знает об окружении:
mouseX,mouseY,width,height,mouseIsPressed(залы 16-17). - Принимать решения с помощью
ifи отличать=от==(залы 18-20). - Повторять действия циклом
forи узнавать три его части (залы 21-23). - Писать текст на холсте с помощью
text(),textSize()иtextAlign()(залы 24-25). - Определять функции с параметрами и с
return(залы 26-28). - Хранить много значений в массиве, добавлять и удалять элементы и обходить массив
с помощью
for...of,forEach,mapиfilter(залы 29-33). - Собрать всё вместе в двух более длинных скетчах с массивами, функциями и рекурсией (залы 34-35).
Ключевые математические идеи
Это лаб по программированию; математические идеи — те, на которых держится рисунок.
- Координаты. Холст — декартова плоскость с началом в левом верхнем углу и осью y, направленной вниз; эллипс или прямоугольник определяется положением и размером.
- Цвет RGB. Каждый цвет — тройка (R, G, B) со значениями от 0 до 255; (255, 0, 0) — чисто красный, а (0, 0, 255) — чисто синий.
- Остаток от деления. В зале 4 используется
x % 400: когдаxдостигает 400, остаток снова становится 0, и шар начинает движение слева. - Переменная как состояние. Счётчик, который растёт в каждом кадре и сравнивается с пределом (отскакивающий шар в зале 18).
- Условия и сравнения. Операторы
>,>=,==,!=;=присваивает, а не сравнивает. - Итерация. Цикл
forс началом, условием и шагом рисует ряд кругов с постоянным интервалом; изменение шага, начала или конца меняет их число. - Функция как преобразование. Функция с
returnвозвращает значение (cubo(3)равно 27);mapприменяет функцию к каждому элементу массива. - Индексы. Массив начинается с индекса 0: при
lista = [1, 2, 3]значениеlista[1]равно 2, аlista.indexOf(3)— 2. - Рекурсия. В дереве из зала 35 функция
rama(len, n)вызывает сама себя с меньшей длиной (коэффициент) и на один уровень меньше и останавливается, когдаnдостигает 0;push()иpop()сохраняют и восстанавливают положение.
Заметки для урока
- Ученик не пишет программу целиком: задания на ввод кода — это одна-две строки, а всё остальное — двигать элементы управления, выбирать варианты и расставлять строки. Это первое знакомство с p5.js, а не мастерская свободного программирования.
- Задания на ввод кода проверяют написанное (функцию и её аргументы или вид выражения) и при ошибке показывают пример; преподаватель видит, что пробовал ученик, в том числе неудачные попытки.
- Вопросы про
if (x = 5), который присваивает вместо сравнения, а JavaScript при этом не предупреждает, и про локальные и глобальные переменные — те места, где стоит остановиться вместе с классом. - Два последних зала хорошо работают на проекторе: ученик меняет гравитацию, отскок, угол или глубину и связывает каждый параметр со строкой кода.
Уровень: бахильерато (информатика). Предварительных знаний по программированию не
требуется. Используется JavaScript; в зале 20 отмечено, что, в отличие от
Python, скобки в if обязательны.
Содержание по залам
Зал 1 · Несколько строк — и вот что происходит
Анимированный рисунок из пяти колец разноцветных кругов, вращающихся вокруг центра, с панелью кода рядом. У рисунка симметрия 6-го порядка, а кода в нём всего несколько строк: два вложенных цикла, угол a = TWO_PI / n * i и цвет в зависимости от положения. Если двигать мышь по холсту, скорость вращения меняется. Это вводный зал, без вопросов: ученик просто смотрит на результат и на код, который его создаёт и который он освоит в следующих залах.
Задания для ученика
- Двигать мышь по холсту и видеть, как меняется скорость вращения.
- Прочитать код, создающий рисунок.
Зал 2 · setup(): готовим холст
Панель с кодом setup() и холст, который он создаёт. Три ползунка меняют ширину, высоту и цвет фона, и код одновременно обновляется, подсвечивая изменившееся число. Идея в том, что setup() выполняется всего один раз, в начале, и именно там задаются размер холста и фон. Только наблюдение.
Задания для ученика
- Двигать ползунки ширины, высоты и фона.
- Видеть, как одновременно меняются холст и аргументы createCanvas() и background().
Зал 3 · Проверьте себя: setup()
Два вопроса с выбором ответа по предыдущем зале: сколько раз выполняется setup() (60 раз в секунду, только один раз, только при щелчке или каждый раз, когда меняется мышь) и какая функция создаёт холст (drawCanvas(), createCanvas(), makeCanvas() или newSketch()). При ошибке даётся подсказка.
Задания для ученика
- Выбрать, сколько раз выполняется setup() (только один раз).
- Выбрать, какая функция создаёт холст (createCanvas()).
Зал 4 · draw(): магия движения
Круг движется по холсту с координатой x, растущей вместе с frameCount. Ползунок (от 1 до 8) меняет скорость. draw() выполняется 60 раз в секунду, и каждый раз frameCount увеличивается на 1. Примечание объясняет оператор %: это остаток от деления (7 % 3 = 1, 10 % 4 = 2), и когда x достигает 400, остаток снова равен 0 и шар начинает движение слева.
Задания для ученика
- Менять скорость и видеть, как это влияет на движение.
- Прочитать примечание об остатке от деления и связать его с шаром, который возвращается в начало.
Зал 5 · Проверьте себя: draw()
Два вопроса с выбором ответа: где находится код, который анимируется непрерывно (в setup(), в draw(), вне обеих функций или где угодно) и какая переменная p5.js считает кадры с начала (frameNumber, frameCount, counter или tick).
Задания для ученика
- Выбрать, где находится анимируемый код (в draw()).
- Выбрать, какая переменная считает кадры (frameCount).
Зал 6 · Основные фигуры: эллипс, прямоугольник, линия
Холст с эллипсом, прямоугольником и линией и код трёх вызовов: ellipse(x, y, ширина, высота), rect(x, y, ширина, высота) и line(x1, y1, x2, y2). Четыре ползунка меняют положение и размер эллипса. Все координаты отсчитываются от левого верхнего угла — это точка (0, 0). Только наблюдение.
Задания для ученика
- Двигать ползунки x, y, ширины и высоты эллипса.
- Замечать, как каждое число в коде меняет рисунок.
Зал 7 · Проверьте себя: базовые фигуры
Два вопроса с выбором ответа (какая функция рисует прямоугольник: square(), rect(), rectangle() или box(); и как записывается ellipse с её четырьмя аргументами) и задание расставить по порядку строки draw(), рисующей эллипс 100 × 60 в точке (200, 150) на сером фоне. Идея: ellipse(x, y, ширина, высота) принимает положение и размер.
Задания для ученика
- Выбрать функцию, рисующую прямоугольник (rect()).
- Выбрать сигнатуру ellipse (ellipse(x, y, ширина, высота)).
- Расставить четыре строки draw() так, чтобы нарисовать эллипс на сером фоне.
Зал 8 · fill(), stroke(), noStroke(): цвет фигур
Круг с заливкой и контуром и код с fill(), stroke() и noStroke(). Три ползунка меняют цвет заливки по R, G и B (каждый от 0 до 255), а четвёртый, strokeWeight, — толщину контура; при 0 контур исчезает. fill() закрашивает внутреннюю часть, stroke() задаёт контур, а noStroke() его убирает. Только наблюдение.
Задания для ученика
- Двигать ползунки R, G и B заливки.
- Менять толщину контура до 0 и видеть эффект.
Зал 9 · Проверьте себя: fill и stroke
Два вопроса с выбором ответа (какая функция убирает контур и какая задаёт заливку) и задание расставить шесть строк draw(), рисующей красный круг без контура: background(200), fill(255, 0, 0), noStroke() и circle(200, 150, 80).
Задания для ученика
- Выбрать функцию, убирающую контур (noStroke()).
- Выбрать функцию, задающую заливку (fill()).
- Расставить строки так, чтобы нарисовать красный круг без контура.
Зал 10 · Напишите код: цвет и фигуры
Первый зал, где ученик пишет код. Три задания, у каждого своё текстовое поле: закрасить заливку красным, нарисовать прямоугольник с заданными координатами (x = 20, y = 40, ширина 80, высота 30) и убрать контур. Проверяется, что совпадают функция и аргументы; если верно, результат появляется на холсте, а если нет, показывается пример.
Задания для ученика
- Написать fill(255, 0, 0);.
- Написать rect(20, 40, 80, 30);.
- Написать noStroke();.
Зал 11 · Цветовое пространство RGB: (R, G, B)
Холст с выбранным цветом фона и круг инвертированного цвета, три ползунка — по одному на канал (от 0 до 255). Каждый цвет задаётся тремя числами: красный (R), зелёный (G) и синий (B). Если двигать ползунки, видно, как смешиваются каналы и как меняется код. Только наблюдение.
Задания для ученика
- Двигать ползунки R, G и B и видеть, как они смешиваются.
- Обратить внимание на инвертированный цвет круга.
Зал 12 · Проверьте себя: цвета RGB
Задание с ползунками: получить чисто красный цвет; целевой цвет и текущий показаны рядом. Затем вопрос с выбором ответа: какой цвет даёт fill(0, 0, 255) (зелёный, синий, красный или белый). Идея: третье число — синий канал, а 255 — максимальная интенсивность.
Задания для ученика
- Подобрать ползунки так, чтобы получить чисто красный цвет (R = 255, G = 0, B = 0).
- Выбрать цвет, который даёт fill(0, 0, 255) (синий).
Зал 13 · Глобальные и локальные переменные
Скетч, где x — глобальная переменная, которая сохраняется между кадрами и растёт, а radio — локальная переменная, объявленная внутри draw(), которая сбрасывается при каждом вызове. Ползунок vel задаёт скорость, а счётчик показывает значение x. Идея: то, что объявлено вне функций, сохраняется между кадрами; то, что объявлено внутри, при каждом вызове начинается с нуля.
Задания для ученика
- Менять скорость и следить за значением x.
- Сравнить глобальную переменную x с локальной radio, которая сбрасывается.
Зал 14 · Проверьте себя: переменные
Два вопроса с выбором ответа: какое значение имеет let contador = 0, объявленная внутри draw(), в кадре 100 (0, потому что сбрасывается при каждом вызове) и что делает vel += 2 (прибавляет 2 к vel, как vel = vel + 2). И задание расставить по порядку программу с двумя глобальными переменными и draw(); порядок двух переменных и двух строк внутри draw() можно менять местами, и принимаются все допустимые варианты.
Задания для ученика
- Выбрать, какое значение имеет локальная переменная в кадре 100 (0).
- Выбрать, что делает vel += 2.
- Расставить код по порядку: сначала глобальные переменные, затем draw().
Зал 15 · Напишите код: изменение переменных
Два задания с операторами присваивания для заданных переменных: вычесть 20 из ancho и удвоить alto. Принимаются и составная, и развёрнутая записи (ancho -= 20 или ancho = ancho - 20; alto *= 2 или alto = alto * 2). При верном ответе прямоугольник на холсте меняет размер.
Задания для ученика
- Написать строку, вычитающую 20 из ancho (ancho -= 20).
- Написать строку, удваивающую alto (alto *= 2).
Зал 16 · Переменные, которые p5.js даёт бесплатно
Холст с кругом, который следует за мышью по mouseX и mouseY, ещё одним кругом неподвижно в центре с width/2 и height/2 и текстом с координатами мыши. Эти переменные p5.js обновляет сам. Зал показывает их, пока ученик двигает мышь и щёлкает; ползунков нет.
Задания для ученика
- Двигать мышь и смотреть на координаты и круг, который за ней следует.
- Щёлкнуть и связать увиденное с mouseIsPressed и другими переменными.
Зал 17 · Проверьте себя: системные переменные
Два вопроса с выбором ответа: какая переменная хранит горизонтальное положение мыши (mouseY, mouseX, posX или xMouse) и какая равна true, пока мышь нажата (mouseDown, mouseIsPressed, isClicked или pressed).
Задания для ученика
- Выбрать переменную горизонтального положения мыши (mouseX).
- Выбрать переменную, равную true, пока мышь нажата (mouseIsPressed).
Зал 18 · if: принятие решений в коде
Шар отскакивает, потому что два условия if определяют, когда он достигает края; рядом показан код. Ползунок (от 1 до 10) меняет скорость, а щелчок по холсту меняет цвет фона. Идея: if выполняет блок, только если условие истинно, и с двумя такими условиями скорость меняет знак на краях.
Задания для ученика
- Менять скорость и наблюдать отскок.
- Щёлкнуть по холсту, чтобы поменять фон.
- Связать каждый if в коде с краем, который он определяет.
Зал 19 · Проверьте себя: if
Три задания. Сначала вопрос-ловушка: что выполняет if (x = 5), который ничего не проверяет, а присваивает x значение 5 и почти всегда входит в блок, а JavaScript не предупреждает. Затем отметить операторы сравнения среди шести (>=, =>, ==, !=, = и >; сравнивают >=, ==, != и >). Наконец, расставить по порядку строки отскока от правого края.
Задания для ученика
- Выбрать, что делает if (x = 5) (присваивает x значение 5 и почти всегда входит в блок).
- Отметить операторы сравнения (>=, ==, !=, >).
- Расставить по порядку строки отскока от правого края.
Зал 20 · Напишите код: условия if
Два задания на дополнение условия if, показанного как if ___ { ... }: «x больше alto» и «x равно y». Условие записывается в скобках, которые в JavaScript обязательны (в отличие от Python), а второе задание заставляет отличать == от =. Принимаются и ==, и ===.
Задания для ученика
- Написать (x > alto).
- Написать (x == y).
Зал 21 · for: повторять без копирования
Один цикл for рисует ряд кругов. Три ползунка меняют шаг (x +=), начало (x =) и конец (x <=) цикла, и код обновляется. Идея: for повторяет тело, пока выполняется условие, и на каждом проходе изменяет переменную, поэтому шаг, начало и конец определяют, сколько кругов и где.
Задания для ученика
- Двигать ползунки шага, начала и конца.
- Смотреть, как меняются число кругов и интервал между ними.
Зал 22 · Проверьте себя: цикл for
Холст с циклом for (let x = 30; x <= 370; x += 40), который рисует ряд кругов. Один вопрос с выбором из четырёх ответов про цикл (начальное значение x, интервал между кругами, до какого значения доходит x и координата Y круга) и задание расставить строки, рисующие ряд. Идея: шаг цикла задаёт интервал между кругами.
Задания для ученика
- Выбрать верный ответ о цикле (интервал между кругами).
- Расставить строки по порядку, чтобы нарисовать ряд кругов.
Зал 23 · Напишите код: три части цикла for
У цикла for три части, разделённые знаком ;: инициализация, условие и приращение. Ученик заполняет каждую в своём поле, а остальная часть цикла остаётся на виду. Принимаются равнозначные записи, например x < 400 или x <= 350 для условия.
Задания для ученика
- Написать инициализацию (let x = 0).
- Написать условие (x < 400 или x <= 350).
- Написать приращение (x += 50).
Зал 24 · text(): пишем на холсте
Крупный текст по центру и маленький текст с переменной, нарисованные с помощью text("строка", x, y). Три ползунка меняют textSize, положение по x и по y, и код обновляется; используется и textAlign(). Только наблюдение.
Задания для ученика
- Двигать ползунки размера текста и положения по x и y.
- Смотреть, как одновременно меняются текст и аргументы text().
Зал 25 · Проверьте себя: text()
Два вопроса с выбором ответа (какая функция рисует текст на холсте: print(), text(), write() или draw(); и что делает textAlign(CENTER, CENTER): центрирует текст по горизонтали и по вертикали) и задание расставить строки draw(), показывающей «Hola p5.js!» белым цветом на тёмном фоне.
Задания для ученика
- Выбрать функцию, рисующую текст (text()).
- Выбрать, что делает textAlign(CENTER, CENTER).
- Расставить строки так, чтобы показать текст.
Зал 26 · Свои функции: flor(x, y)
Функция flor(x, y) задаёт цветок с центральным кругом и четырьмя лепестками и вызывается дважды с разными координатами. Четыре ползунка двигают каждый из двух цветков. Идея: функция определяется один раз и используется сколько угодно раз, а параметры меняют то, что она рисует.
Задания для ученика
- Двигать ползунки координат каждого цветка.
- Сравнить код определения с двумя вызовами.
Зал 27 · Проверьте себя: собственные функции
Вопрос с выбором ответа о том, что нужно сделать перед вызовом flor(100, 150) (определить function flor() до использования) и задание расставить строки определения flor(x, y) с центральным кругом и двумя лепестками.
Задания для ученика
- Выбрать, что нужно перед вызовом собственной функции (определить её).
- Расставить строки так, чтобы определить flor(x, y).
Зал 28 · Напишите код: определение функций
Два задания: определить функцию nada, которая ничего не делает (с полным синтаксисом и фигурными скобками), и определить cubo(n), возвращающую n в кубе. Второе проверяется запуском функции: cubo(3) должно дать 27. return заставляет функцию вернуть значение, которое можно использовать там, где она вызвана; без return она возвращает undefined.
Задания для ученика
- Написать function nada() {}.
- Написать функцию cubo(n), возвращающую n · n · n.
Зал 29 · Массивы: хранение множества значений
Массив хранит несколько элементов в одной переменной. Щелчок по холсту добавляет точку с помощью push(), а for...of рисует каждую; надпись показывает длину массива. Две кнопки удаляют последнюю точку (pop()) или очищают массив ([]).
Задания для ученика
- Щёлкать по холсту, добавляя точки с помощью push().
- Удалить последнюю точку кнопкой «pop» и очистить массив соответствующей кнопкой.
Зал 30 · Проверьте себя: массивы
Два вопроса с выбором ответа (что делает xs.push(50) и как обратиться к первому элементу xs: xs[0]) и задание расставить строки программы, которая объявляет массив, добавляет позицию и рисует её с помощью for...of. Идея: индексы начинаются с 0.
Задания для ученика
- Выбрать, что делает push() (добавляет элемент в конец).
- Выбрать, как обратиться к первому элементу (xs[0]).
- Расставить строки по порядку: объявить массив, добавить элемент и нарисовать его.
Зал 31 · Напишите код: операции с массивами
Исходный массив let lista = [1, 2, 3]. Четыре задания: чему равно lista[1] (2), чему равно lista.indexOf(3) (2), чему равно lista.length после lista.pop() (2) и написать код, добавляющий 7 в конец. Последнее проверяется запуском написанного. На первые три отвечают числом.
Задания для ученика
- Написать, чему равно lista[1] (2).
- Написать, чему равно lista.indexOf(3) (2, индекс, на котором стоит 3).
- Написать, чему равно lista.length после lista.pop() (2).
- Написать код, добавляющий 7 в конец lista (например, lista.push(7)).
Зал 32 · forEach, map, filter: работа с массивами
Столбчатая диаграмма со значениями массива. forEach рисует все столбцы синим, filter красным выделяет те, что выше порога, а map создаёт новый массив с удвоенной высотой каждого. Ползунок двигает порог filter (от 20 до 170), и видно, какие столбцы выделяются. Только наблюдение.
Задания для ученика
- Двигать порог и видеть, какие столбцы выбирает filter.
- Сравнить три вызова, forEach, map и filter, с тем, что они рисуют.
Зал 33 · Проверьте себя: forEach, map, filter
Два вопроса с выбором ответа (что возвращает map() — новый массив с преобразованными значениями; и для чего нужен filter() — вернуть элементы, удовлетворяющие условию) и задание расставить строки программы, объявляющей массив и применяющей к нему forEach, map и filter.
Задания для ученика
- Выбрать, что возвращает map() (новый массив).
- Выбрать, для чего нужен filter().
- Расставить строки программы с forEach, map и filter.
Зал 34 · Проект: система частиц
Полноценный скетч, объединяющий массивы, for...of, if, функции и переменные: массив частиц, которые падают под действием гравитации и отскакивают от пола и от боковых сторон. Четыре ползунка настраивают гравитацию, отскок, число частиц и цвет (оттенок), а каждый щелчок по холсту запускает ещё 8 частиц. Код обновляется при движении ползунков. Вопросов нет: нужно работать с более длинной программой и читать, как она устроена.
Задания для ученика
- Настроить гравитацию, отскок, число частиц и цвет.
- Щёлкать по холсту, запуская новые частицы.
- Найти в коде массив, цикл и условия.
Зал 35 · Проект: рекурсивное фрактальное дерево
Дерево, нарисованное функцией rama(len, n), которая вызывает сама себя: каждая ветвь делится на две более короткие, повёрнутые вправо и влево, пока уровень n не достигнет 0. push() и pop() сохраняют и восстанавливают положение. Четыре ползунка меняют угол, глубину, коэффициент уменьшения (в %) и длину ствола. Вопросов нет: нужно работать с более длинной программой и читать, как она устроена.
Задания для ученика
- Менять угол, глубину, коэффициент и длину и видеть, как меняется дерево.
- Найти в коде вызов rama самой себя и push()/pop().
Залы для показа
Самые наглядные для показа и обсуждения в классе.