Первый скетч: setup() и draw()

Сегодня ты напишешь свой самый первый скетч на p5.js и поймёшь, как из двух функций — setup() и draw() — рождается живая картинка на холсте.
Скетч — одна программа на p5.js, отдельный набросок, который рисует и анимирует картинку.

Представь, что ты открыл пустой лист в скетчбуке. Ничего не нарисовано — только белая бумага и желание что-то на ней оставить. В прошлом уроке мы говорили о том, что такое креативное кодирование и зачем вообще рисовать кодом. Теперь хватит разговоров — берём карандаш. Точнее, открываем редактор и пишем первые строчки, после которых на экране появится холст, а на нём — крошечная точка. Эта точка не просто так: с неё начнётся наш сквозной герой, цыплёнок CodeChick, который будет расти вместе с тобой весь курс.

Зачем тебе вообще эти две функции

Любая игра, которую ты запускал на телефоне, внутри устроена примерно так: один раз игра загружается (подтягивает картинки, расставляет уровень, заводит счёт на ноль), а потом много-много раз в секунду перерисовывает экран — двигает персонажа, считает очки, проверяет, не врезался ли ты в стену. Глаз видит плавное движение, а на самом деле это сотни отдельных картинок, мелькающих одна за другой.

В p5.js этот же принцип уложен ровно в две функции. Одна отвечает за «загрузку» — она называется setup. Вторая отвечает за «много раз в секунду перерисовать» — она называется draw. Если ты поймёшь, чем они отличаются, ты поймёшь вообще всё устройство p5: остальное будет наращиваться поверх этих двух кирпичей.

setup() — функция p5.js, которая выполняется один раз в начале и настраивает скетч (например, создаёт холст).
draw() — функция p5.js, которая повторяется много раз в секунду и отрисовывает каждый новый кадр.

К концу урока у тебя будет работающий скетч, в котором есть холст нужного размера, фон и первая деталь будущего цыплёнка. А ещё ты на пальцах поймёшь разницу между «сделать один раз» и «делать постоянно» — это пригодится не только в p5, но и почти в любой программе с экраном.

Главная идея: декорации и актёр

Чтобы не запутаться, держи в голове простую сцену в театре. Перед спектаклем рабочие один раз расставляют декорации: вешают задник, ставят стол, кладут реквизит. Это долго и делается заранее — но только один раз. А когда спектакль начался, актёр выходит и снова и снова играет своё действие: шаг, реплика, жест, шаг, реплика, жест.

Так вот, setup — это рабочие сцены. Здесь ты один раз настраиваешь всё, что не должно меняться каждую секунду: создаёшь холст, задаёшь его размер. А draw — это актёр: всё, что внутри неё, p5 проигрывает снова и снова, кадр за кадром, пока скетч запущен.

Вот самый маленький скетч, который вообще можно написать. Разберём его построчно.

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
}

Результат: на странице появляется квадратный холст 400 на 400 пикселей, залитый ровным светло-серым цветом. Картинка статичная — она не двигается, но на самом деле p5 перерисовывает этот серый фон десятки раз в секунду.

Разберём, что здесь происходит:

  • function setup() { ... } — мы объявляем функцию настройки. p5 сам найдёт её по имени и вызовет один раз при старте.
  • createCanvas(400, 400) — создаём холст шириной 400 и высотой 400 пикселей. Два числа в скобках — это ширина и высота.
  • function draw() { ... } — функция кадра. p5 будет вызывать её снова и снова, примерно 60 раз в секунду.
  • background(220) — заливаем весь холст серым цветом. Число 220 — это яркость от 0 (чёрный) до 255 (белый); 220 — светло-серый.
Холст (canvas) — прямоугольная область на странице, внутри которой p5.js рисует всё изображение.
createCanvas() создаёт этот холст. Без него рисовать просто негде — это как пытаться рисовать в воздухе без листа бумаги.

Почему createCanvas стоит именно в setup

Логика простая: холст тебе нужен один и тот же на весь скетч. Незачем создавать новый лист бумаги 60 раз в секунду — это всё равно что на каждом кадре спектакля заново строить декорации. Поэтому всё «разовое» — размер холста, его создание — живёт в setup. А всё «повторяющееся» — рисование фигур, движение — живёт в draw.

Разбираем на примерах

Пример 1. Холст и фон — самый минимум

Мы его уже видели выше, но давай задержимся и поэкспериментируем. Поменяй число в background и представь результат.

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(135, 206, 235);
}

Результат: холст 400 на 400 заливается голубым цветом неба. Три числа в background — это уже не яркость, а доли красного, зелёного и синего (модель RGB), и вместе они дают небесно-голубой. Подробно про цвет будет отдельный модуль, а пока просто запомни: одно число — это серый, три числа — это полноцветный оттенок.

Вот тебе первое поле для эксперимента: попробуй мысленно поставить background(0) (получишь чёрный холст) или background(255) (белый). Поменял число — поменялась сцена. Это и есть кайф креативного кодирования: ты крутишь параметры и сразу видишь отклик.

Пример 2. Первая деталь цыплёнка

Серый прямоугольник — это, конечно, скучно. Давай нарисуем на нём первую деталь нашего героя — кружок-тело будущего цыплёнка CodeChick.

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(135, 206, 235);
  circle(200, 200, 120);
}

Результат: на голубом небе в самом центре холста появляется белый кружок диаметром 120 пикселей — пока без цвета и клюва, просто тельце. Это первая клеточка нашего цыплёнка: дальше по курсу он обзаведётся жёлтой заливкой, клювом и научится прыгать.

Разберём circle(200, 200, 120):

  • Первое число — координата x центра кружка, то есть отступ слева. 200 — это ровно половина от 400, значит центр по горизонтали.
  • Второе число — координата y центра, отступ сверху. Тоже 200 — центр по вертикали.
  • Третье число — диаметр кружка в пикселях.

Тут важная деталь, на которой спотыкаются все новички: на холсте точка (0, 0) находится в левом верхнем углу, а не внизу, как на уроках математики. Ось x растёт вправо, а ось y — вниз. Представь клетки в тетради, только нумерация строк идёт сверху вниз. Поэтому центр холста 400 на 400 — это точка (200, 200).

Система координат — способ задавать точку на холсте парой чисел (x, y), где начало (0, 0) находится в левом верхнем углу.

Пример 3. Проверяем, что setup действительно срабатывает один раз

Давай докажем себе, что setup выполняется ровно один раз, а draw — постоянно. Используем функцию print, которая пишет сообщение в консоль (это служебное окошко, куда программа выводит текст для разработчика).

function setup() {
  createCanvas(400, 400);
  print("setup сработал");
}

function draw() {
  background(220);
  print("draw сработал");
}

Результат: в консоли строчка «setup сработал» появляется ровно один раз, а строчка «draw сработал» печатается снова и снова без остановки, десятки раз в секунду, пока скетч работает. Это наглядно показывает разницу: одна функция — про старт, другая — про бесконечный поток кадров.

Кадр (frame) — одно изображение анимации; draw() рисует кадры подряд, создавая иллюзию движения.

Каждый вызов draw рисует новый кадр поверх предыдущего. Пока картинка не двигается, ты этого не замечаешь, но именно эта повторяемость в следующих модулях оживит нашего цыплёнка.

Пример 4. Что будет без background в draw

А теперь хитрый момент, который многих сбивает. Зачем вообще каждый кадр перерисовывать фон? Давай посмотрим, что выйдет, если фон оставить в setup, а в draw рисовать кружок в случайном месте.

function setup() {
  createCanvas(400, 400);
  background(135, 206, 235);
}

function draw() {
  circle(random(400), random(400), 30);
}

Результат: голубое небо заливается один раз, а потом по нему начинают рассыпаться белые кружочки — каждый кадр добавляет новый, и старые никуда не деваются. За пару секунд весь холст покрывается белыми пятнами, как будто кто-то щедро сыпет конфетти. Так происходит, потому что фон не стирается: каждый новый кружок ложится поверх всего нарисованного раньше.

Запомни это поведение — оно не баг, а инструмент. Иногда тебе нужно, чтобы рисунок накапливался (так делают красивые узоры), а иногда — чтобы каждый кадр был чистым (так делают анимацию). Управляешь этим ты, ставя или убирая background внутри draw.

Частые ошибки и подводные камни

Вот грабли, на которые наступают почти все в первый день. Пробежись по ним заранее — сэкономишь себе кучу нервов.

1. Забыть createCanvas

Если не вызвать createCanvas в setup, p5 создаст крошечный холст по умолчанию (100 на 100), и ты будешь недоумевать, почему твой кружок с координатой 200 вообще не виден — он просто за краем малюсенького холста. Правило: первым делом в setup создавай холст нужного размера.

2. Путать порядок: фигура раньше фона

Команды рисования выполняются сверху вниз, и каждая следующая ложится поверх предыдущей, как слои краски. Если ты сначала нарисуешь кружок, а потом зальёшь background, фон закрасит твой кружок целиком, и ты увидишь пустой холст. Правило: background почти всегда идёт первой строкой в draw.

3. Думать, что (0, 0) внизу

На математике начало координат внизу слева, а ось y растёт вверх. На холсте всё наоборот: (0, 0) сверху слева, а y растёт вниз. Поэтому circle(200, 350, 40) нарисует кружок не вверху, а почти у нижнего края. Держи это в голове, иначе фигуры будут улетать не туда, куда ты ждёшь.

4. Лишние или пропущенные скобки и точки с запятой

Тело функции обязано быть в фигурных скобках { }, а аргументы — в круглых ( ). Если потеряешь закрывающую скобку, скетч просто не запустится и выдаст ошибку. Пиши скобки парами сразу, а потом заполняй внутри — так сложнее забыть закрывающую.

5. Писать createCanvas внутри draw

Если по ошибке поставить createCanvas в draw, p5 будет создавать новый холст 60 раз в секунду. В лучшем случае скетч начнёт тормозить, в худшем — насоздаёт кучу холстов друг под другом. Холст — это разовая настройка, ему место строго в setup.

Мини-проект: посади цыплёнка в гнездо

Пора рисовать самому. Возьми скетч из примера 2 и доведи его до маленькой сценки. Задание собирается из шагов, каждый следующий чуть сложнее.

  1. Создай холст 500 на 400 и залей его светло-голубым фоном неба (подбери три числа в background на свой вкус).
  2. Нарисуй тельце цыплёнка — кружок диаметром около 120 примерно в центре холста. Посчитай координаты центра сам: для холста 500 на 400 это (250, 200).
  3. Добавь второй кружок поменьше, диаметром около 60, чуть выше и правее тельца — это будет голова. Прикинь координаты так, чтобы голова касалась тела.
  4. Под цыплёнком нарисуй ещё один широкий и низкий кружок (или используй ellipse с разной шириной и высотой) тёмного цвета — это гнездо, на котором он сидит.
  5. Когда всё встанет на места, поэкспериментируй: подвигай числа координат и понаблюдай, как деталь переезжает по холсту. Попробуй сдвинуть голову на пару десятков пикселей и почувствуй систему координат руками.

Подсказка по последнему шагу: чтобы голова была выше тела, её координата y должна быть меньше, чем у тела (помни — вверх это меньшие значения y). Если запутался, вернись к примеру 2 и разделу про координаты.

Не гонись за идеальной картинкой. Цель этого мини-проекта — почувствовать, как из простых кружков и пары чисел складывается узнаваемая сценка, и закрепить, что вся отрисовка живёт в draw, а размер холста задаётся один раз в setup.

Итоги

Соберём всё, что ты сегодня узнал, в одну картину:

  • Скетч в p5.js держится на двух функциях: setup и draw.
  • setup() выполняется один раз при старте — здесь ты создаёшь холст через createCanvas(ширина, высота) и задаёшь всё разовое.
  • draw() выполняется снова и снова, десятки раз в секунду, рисуя каждый новый кадр; здесь живёт вся отрисовка и будущая анимация.
  • Холст — это твой лист бумаги; без createCanvas рисовать негде.
  • В системе координат точка (0, 0) находится в левом верхнем углу, x растёт вправо, y — вниз.
  • background в draw стирает прошлый кадр; убери его — и рисунок начнёт накапливаться.
  • Первая деталь нашего цыплёнка CodeChick — простой кружок-тельце — уже на холсте.

В следующем уроке мы разберём систему координат глубже и научимся точно ставить фигуры в нужные точки — это нужно, чтобы цыплёнок не разъезжался по холсту, а собирался аккуратно из деталей. А дальше его ждут цвет, движение и характер. Ты только что сделал самый важный шаг — написал первый работающий скетч. Дальше будет только интереснее.

Проверьте себя
1. Чем функция setup() отличается от функции draw()?
Asetup() выполняется один раз при старте, а draw() повторяется много раз в секунду
Bsetup() повторяется постоянно, а draw() выполняется один раз
CОбе выполняются ровно один раз
DОбе повторяются по очереди ровно по два раза
2. Где правильнее всего вызывать createCanvas()?
AВнутри draw(), чтобы холст обновлялся каждый кадр
BВнутри setup(), потому что холст создаётся один раз
CВообще вне обеих функций
DЭто неважно, можно где угодно
3. Где на холсте p5.js находится точка с координатами (0, 0)?
AВ центре холста
BВ левом нижнем углу, как на уроках математики
CВ левом верхнем углу
DВ правом верхнем углу
4. Что произойдёт, если в draw() убрать вызов background()?
AСкетч перестанет запускаться и выдаст ошибку
BПрошлые кадры перестанут стираться, и фигуры начнут накапливаться поверх друг друга
CХолст станет полностью чёрным
DНичего не изменится
5. Что задают три числа в circle(200, 200, 120)?
AКрасный, зелёный и синий цвета кружка
BКоординату x центра, координату y центра и диаметр
CШирину, высоту и поворот
DТри точки, через которые проходит окружность
6. Почему скетч с circle(200, 200, 120) показывает кружок ровно в центре холста 400 на 400?
AПотому что p5.js всегда центрирует фигуры автоматически
BПотому что 200 — это половина от 400, значит центр и по горизонтали, и по вертикали
CПотому что 120 — это специальное центрирующее число
DПотому что circle() игнорирует координаты