Старшая школа 35 Залы Программирование

Дидактические цели

Короткий курс творческого программирования с 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().

Залы для показа

Самые наглядные для показа и обсуждения в классе.

★
Зал 1 · Несколько строк — и вот что происходит — Если показать её в начале на проекторе, можно спросить, сколько строк, по мнению учеников, нужно для такого рисунка, и сразу станет ясно, чему предстоит научиться.
★
Зал 19 · Проверьте себя: if — Вопрос про if (x = 5) показывает, что присваивание и сравнение — разные вещи и что JavaScript об этом не предупреждает; его стоит обсудить с классом.
★
Зал 35 · Проект: рекурсивное фрактальное дерево — Если двигать угол, глубину и коэффициент, видно, что делает рекурсия с функцией, вызывающей саму себя; это хорошее завершение, чтобы показать на проекторе.