птицы

3 сентября 2026 г. devlogpixelart

началось всё с тупиков

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

А потом подумал: ну, одна птица выглядит немного одиноко.

а потом это уже было не остановить

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

У каждого вида свой размер, своя скорость и своя частота появления. Орлана я специально сделал довольно редким, показалось правильным для такой крупной птицы.

Полоса в подвале: сидящие тупики и кулик-сорока вдоль берега

потолок, потому что стало уже слишком

В какой-то момент птицы появлялись почти без ограничений, и после перезагрузки страницы можно было увидеть штук пятнадцать птиц, дерущихся за воздушное пространство над крошечной шапкой сайта. Больше похоже на фильм Хичкока, чем на блог про побережье. Поставил ограничение прямо в логике отрисовки:

const guaranteed = CANDIDATES.find((c) => c.guaranteed)!;
const rest = CANDIDATES.filter((c) => !c.guaranteed);
const shuffled = [...rest].sort(() => rand() - 0.5);
const extraCount = 2 + Math.floor(rand() * 3); // 2-4
const chosen = [guaranteed, ...shuffled.slice(0, extraCount)];

рыбы, и путаница на моей совести

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

// first pass: one shared list, whatever top value felt right per sprite
const sprites = [...birds, ...fish].map((s) => ({ ...s, top: s.top }));

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

// row 3's top edge, 60% down the strip's own height, is literally
// "the waterline" in this layer's own geometry. Humans stand in the
// land band (top 0-60%); fish swim in the sea band (top 60-100%).
//
// Caps: fish <= 3 (here: 3), humans <= 2 (here: 2 -- one standing, one
// running).

Теперь всё исправлено: птицы летают, рыбы плавают, каждый в своей полосе.

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

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

0 комментариев

Войдите , чтобы оставить комментарий.

Войти

Забыли пароль?

Нет аккаунта?