Холст, пиксели и система координат

Холст — это сетка из пикселей, а каждая точка на нём — пара чисел (x, y); освоишь эту сетку — и сможешь поставить любую часть цыплёнка ровно туда, куда задумал.

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

Зачем вообще знать, где у холста ноль

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

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

Вот к чему мы придём в конце урока — к аккуратно собранной мордочке цыплёнка, где каждая деталь стоит на своём месте не случайно, а потому что ты сам назначил ей координаты:

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

function draw() {
  background(135, 206, 235); // небо
  // тело
  circle(200, 220, 160);
  // голова
  circle(200, 130, 110);
  // глаза
  circle(175, 115, 14);
  circle(225, 115, 14);
  // клюв
  triangle(200, 130, 230, 145, 200, 160);
}

Результат: на голубом небе — цыплёнок из двух кругов (тело внизу, голова сверху), с двумя маленькими глазками и треугольным клювом по центру. Всё симметрично и собрано, потому что мы заранее посчитали координаты.

Холст — это сетка из пикселей

Открой телефон и поднеси его к глазам очень близко. Если экран хороший, ты ничего не разглядишь, а если присмотреться к старому монитору или увеличить картинку в редакторе — увидишь, что изображение состоит из крошечных квадратиков. Каждый такой квадратик — это пиксель (от английского picture element, «элемент картинки»). Любая фотография, мем или кадр из игры — это просто сетка пикселей, каждый из которых светится своим цветом.

Холст (canvas) — это прямоугольная область на странице, внутри которой p5.js рисует всё изображение. По сути это лист в клетку, только клетки — это пиксели.

Когда ты пишешь createCanvas(400, 400), ты говоришь p5.js: «Дай мне лист шириной 400 пикселей и высотой 400 пикселей». Получается сетка 400 на 400 — это 160 000 маленьких квадратиков, каждым из которых ты можешь управлять. Звучит как много, но не пугайся: чаще всего ты рисуешь не по одному пикселю, а целыми фигурами — кругами, линиями, прямоугольниками — и p5.js сам закрашивает нужные пиксели за тебя.

Чем холст похож на тетрадь в клетку

Вспомни обычную тетрадь в клетку. Когда на уроке геометрии ты строил точку, ты отсчитывал клетки: столько-то вправо, столько-то вниз. Холст в p5.js работает точно так же, с одним важным отличием от того, что вы рисовали на математике.

Единственное, что стоит держать в голове: на холсте нет «полуклеток». Координата — это число пикселей (p5.js терпит и дробные, просто отрисовывает их с округлением). Поэтому, когда ты пишешь 200, это буквально «двухсотый пиксель по горизонтали», а не абстрактная точка где-то посередине. Очень удобно: ты всегда можешь точно сказать, где стоит каждая деталь, и измерить расстояние между ними обычным вычитанием — прямо как считал клетки между двумя точками в тетради.

Где находится начало координат

На уроках математики ты привык, что начало координат — где-то в центре, ось x идёт вправо, ось y — вверх. В p5.js (и почти во всей компьютерной графике) всё иначе, и это первое, что сбивает новичков с толку.

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

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

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

Точка (x, y)Где окажется на холсте 400×400
(0, 0)Самый левый верхний угол
(400, 0)Правый верхний угол
(0, 400)Левый нижний угол
(400, 400)Правый нижний угол
(200, 200)Ровно центр холста

Маленькая хитрость: центр холста — это всегда половина ширины и половина высоты. Для холста 400×400 центр в точке (200, 200). Это пригодится постоянно, когда захочешь поставить цыплёнка ровно посередине.

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

Пример 1. Одна точка на холсте

Начнём с самого маленького — поставим одну-единственную точку. Это будущий «зародыш» нашего цыплёнка, та самая точка из первого модуля.

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

function draw() {
  background(245);     // светло-серый фон
  strokeWeight(10);    // толщина точки — 10 пикселей
  point(200, 200);     // точка в центре
}

Результат: на светло-сером фоне ровно по центру холста — одна жирная чёрная точка. Если поменять point(200, 200) на point(50, 50), точка переедет ближе к левому верхнему углу.

Разберём по шагам:

  • createCanvas(400, 400) — создаём холст-сетку 400 на 400 пикселей.
  • background(245) — заливаем весь холст светло-серым, чтобы точку было видно.
  • strokeWeight(10) — говорим, что линии и точки будут толщиной 10 пикселей (иначе точка была бы крохотной, в один пиксель).
  • point(200, 200) — рисуем точку в координатах x = 200, y = 200, то есть в центре.

Поиграй: подставь разные числа и попробуй мысленно предсказать, куда уедет точка, прежде чем посмотришь результат. Это лучший способ «почувствовать» сетку.

Пример 2. Голова и тело из двух кругов

Теперь соберём из точек что-то осмысленное. Функция circle(x, y, диаметр) рисует круг с центром в точке (x, y). Третий аргумент — это диаметр, то есть ширина круга в пикселях.

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

function draw() {
  background(245);
  circle(200, 230, 160); // тело: центр чуть ниже середины
  circle(200, 130, 110); // голова: центр выше тела
}

Результат: на сером фоне — два круга, поставленные друг на друга столбиком: большой внизу (тело) и поменьше сверху (голова). Похоже на снеговика или на заготовку цыплёнка.

Обрати внимание на главное: у обоих кругов x одинаковый — 200. Поэтому они стоят строго друг под другом, по одной вертикали. А вот y разный: у тела 230 (ниже), у головы 130 (выше). Помнишь правило? Меньше y — выше на экране. Голова с y = 130 оказывается над телом с y = 230. Если бы ты случайно поставил голове y = 330, она бы уехала под тело — и цыплёнок встал бы на голову.

Пример 3. Добавляем глаза и клюв

Цыплёнку нужно лицо. Глаза — два маленьких круга, клюв — треугольник. Функция triangle(x1, y1, x2, y2, x3, y3) соединяет три точки и закрашивает фигуру между ними — то есть тебе нужно задать координаты всех трёх углов.

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

function draw() {
  background(245);
  circle(200, 230, 160); // тело
  circle(200, 130, 110); // голова
  circle(180, 120, 16);  // левый глаз
  circle(220, 120, 16);  // правый глаз
  triangle(200, 132, 235, 150, 200, 168); // клюв
}

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

Смотри, как работает симметрия. Центр головы — x = 200. Левый глаз стоит на x = 180 (на 20 пикселей левее центра), правый — на x = 220 (на те же 20 пикселей правее). Одинаковое смещение в обе стороны — и глаза смотрятся ровно. Это приём, который ты будешь использовать постоянно: чтобы что-то выглядело симметрично, отсчитывай равные расстояния влево и вправо от центральной линии.

Пример 4. Зерно на земле

Дадим цыплёнку, что поклевать. Положим зёрнышко внизу холста — а заодно убедимся, что мы поняли правило про большой y.

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

function draw() {
  background(245);
  // земля внизу
  fill(120, 200, 120);
  rect(0, 360, 400, 40);
  // зёрнышко на земле
  fill(210, 160, 60);
  ellipse(120, 350, 18, 12);
}

Результат: снизу холста — зелёная полоса земли во всю ширину, а на ней — маленький овальный жёлто-коричневый зёрнышко слева. Земля прижата к нижнему краю, потому что её y = 360 — почти максимум для холста высотой 400.

Здесь два новых момента. Во-первых, rect(x, y, ширина, высота) рисует прямоугольник, но его точка (x, y) — это левый верхний угол, а не центр (в отличие от круга). Поэтому rect(0, 360, 400, 40) начинается у левого края (x = 0), от высоты 360 и тянется на 400 в ширину и 40 в высоту — ровно до нижнего края. Во-вторых, ellipse(x, y, ширина, высота) — это растянутый круг, у которого ширину и высоту задаёшь отдельно; центр у него, как у круга, в точке (x, y).

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

На этих граблях спотыкаются почти все новички. Прочитай заранее — сэкономишь себе час нервов.

  1. Путать x и y местами. Координаты всегда идут в порядке «сначала по горизонтали, потом по вертикали»: circle(x, y, d). Если написать circle(50, 300, 40) вместо circle(300, 50, 40), круг окажется совсем не там, где ты думал. Запомни как адрес: сначала «улица» (x — вправо), потом «этаж» (y — вниз).
  2. Думать, что y растёт вверх. Самая частая ловушка после математики. Ты хочешь поднять фигуру выше — и увеличиваешь y, а она едет вниз. Повторяй мантру: больше y — ниже на экране.
  3. Рисовать за пределами холста. Если у тебя холст 400×400, а ты ставишь circle(700, 700, 50), круг просто не появится — он целиком за краем. p5.js не ругается и не выдаёт ошибку, фигура молча исчезает. Если что-то «не рисуется», первым делом проверь, не уехали ли координаты за размер холста.
  4. Забывать, что у прямоугольника точка — это угол, а у круга — центр. rect(0, 0, 100, 100) прижмётся к левому верхнему углу, а circle(0, 0, 100) покажет только свою правую нижнюю четвертинку, потому что его центр в самом углу, а остальное ушло за край. Это разное поведение, и о нём легко забыть.
  5. Считать, что третий аргумент круга — это радиус. В circle(x, y, d) третье число — это диаметр (вся ширина), а не радиус (половина). Если хотел круг шириной 80, пиши 80, а не 40.

Мини-проект: расставь цыплёнка сам

Пора применить всё на практике. Возьми за основу пример с головой и телом и доработай его сам — без подсказок, как настоящий автор скетча. Вот техзадание:

  • Создай холст 500×500 (не 400 — придётся пересчитать центр самому: чему теперь равна середина?).
  • Залей фон голубым небом через background(135, 206, 235).
  • Поставь тело и голову цыплёнка точно по центру холста по горизонтали.
  • Добавь два симметричных глаза и треугольный клюв.
  • Положи внизу холста зелёную полосу земли и хотя бы два зёрнышка в разных местах.
  • Бонус: подними цыплёнка чуть выше центра, чтобы он «стоял» на земле, а не висел в воздухе.

Подсказка по центру: для холста 500×500 середина по горизонтали — это 250. Значит, у тела, головы и клюва x должен крутиться вокруг 250, а глаза — симметрично слева и справа от него (например, 230 и 270). Не бойся подбирать числа методом «поменял — посмотрел»: именно так работают и настоящие художники-кодеры.

Если хочешь усложнить — добавь цыплёнку второе зёрнышко повыше, как будто оно ещё падает, и подумай, какой y сделает его «выше» в воздухе. Это и есть тот самый эксперимент, ради которого мы тут собрались.

Итоги

Сегодня ты разобрался с фундаментом, на котором держится вообще всё рисование в p5.js:

  • Холст — это сетка из пикселей; createCanvas(ширина, высота) задаёт её размер.
  • Начало координат (0, 0) — в левом верхнем углу; x растёт вправо, y растёт вниз.
  • Любая точка задаётся парой чисел (x, y), и от этой пары зависит, куда попадёт фигура.
  • У круга и эллипса точка (x, y) — это центр, а у прямоугольника — левый верхний угол.
  • Симметрию делают через равные смещения влево и вправо от центральной линии.

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

Проверьте себя
1. Где на холсте p5.js находится начало координат — точка (0, 0)?
AВ центре холста
BВ левом нижнем углу
CВ левом верхнем углу
DВ правом верхнем углу
2. Что произойдёт, если у круга увеличить координату y?
AКруг сместится вверх
BКруг сместится вниз
CКруг станет больше
DКруг сместится вправо
3. Что задаёт третий аргумент в функции circle(x, y, d)?
AРадиус круга
BДиаметр круга
CЦвет круга
DТолщину обводки
4. Чем отличается точка (x, y) у rect() от точки (x, y) у circle()?
AУ rect() это центр, у circle() — угол
BУ rect() это левый верхний угол, у circle() — центр
CУ обоих это центр
DУ обоих это левый верхний угол
5. Где окажется центр холста размером 400×400?
A(0, 0)
B(400, 400)
C(100, 100)
D(200, 200)
6. Почему фигура с координатами circle(700, 700, 50) не появится на холсте 400×400?
AПотому что p5.js выдаст ошибку
BПотому что её центр находится за пределами холста
CПотому что диаметр слишком большой
DПотому что нужно сначала вызвать background()