Город побед перерождён — полный разбор

Раньше была странность: 1 выигранная партия — целый небоскрёб. Сыграл 5 партий — у тебя район из пяти высоток, это не имело смысла для игры про столбики из 11 блоков.

Переделали всё в корне и добавили кучу виральных фич. Никакой миграции базы не было — все старые победы пересчитались автоматически. Если раньше было 30 высоток на 30 побед, теперь будет 5-7 высоток + одна строящаяся.

НОВАЯ КОНЦЕПЦИЯ КИРПИЧЕЙ

1 победа теперь даёт от 1 до 5 кирпичей:
— база +1
— живой соперник +1
— Hard AI +1, Extreme +2, Impossible +3
— золотая победа +1

Кирпичи укладываются хронологически в стойки по 11. 11-й кирпич закрывает высотку. Если этот последний кирпич был особый (золотая виктория или Impossible AI) — сверху висит золотая корона-шпиль, выше звезда и дым.

Цвет этажа = скин игрока на момент той победы. Высотки получаются разноцветные — это история твоих скинов.

ИНТЕРАКЦИЯ

Наведи на этаж — tooltip покажет конкретную победу: соперник, сложность AI, дата. Наведи на высотку целиком — статус (закрыта/строится), период от первой до последней победы, сколько побед её составили. Сама высотка подсвечивается и лёгко увеличивается. Кликни на высотку — модалка с полным списком побед и количеством кирпичей от каждой (сгруппировано по победе).

Фильтры высоток: все / с короной / содержит Impossible AI / за последнюю неделю. Остальные полупрозрачные.

Индикатор «Следующая высотка: 7/11 кирпичей» — видно сколько осталось до закрытия.

СЪЁМКА, ВИДЕО И РАКУРСЫ

4 пресета камеры: Изо (обзорный), Сверху, Кино (низкий кинематографичный угол), FPV-облёт + автоповорот. Плавный переход между ними. 6 слотов сохранённых ракурсов — нашёл красивый угол, сохранил с именем, возвращаешься в один клик.

4 пресета времени суток: Ночь, Утро, День, Закат — меняются цвет неба, фог, солнце и экспозиция. Ночью окна в высотках зажигаются, выходят звёзды. Сезонная погода: снег зимой, дождь весной, листья осенью (летом выключена).

Time-lapse «История» — проигрывает постройку города хронологически с датами в углу. Видно как рос твой город.

Снимок города с фильтрами (Vivid, Ч/Б, Сепия) и водяным знаком «Highrise Heist · Имя · N побед».

Запись 8-секундного облёта города в видео (.webm/.mp4, кодеки vp9→vp8→h264). Где поддерживается Web Share — сразу в системный share sheet (один клик в TikTok/Instagram), иначе скачивается файлом. Рекордер показывает REC-индикатор с прогресс-баром и обратным отсчётом.

Режим полного экрана. Минимап в углу (золото/фиолет/синий, клик — полёт к высотке).

ШАРИНГ И СОРЕВНОВАНИЕ

Кнопка «Поделиться городом». Модалка содержит три ссылки с кнопками копирования:
— embed-виджет highriseheist.com/embed/city/123 — отдельная страница с интерактивным 3D-городом
— личный профиль
— iframe-снипет для вставки в блог/сайт (поддерживает параметры ?theme=day|night и ?nocontrols=1 для чистых скриншотов)

При вставке embed-ссылки в Telegram, Discord, Reddit, BGG или любой блог появляется большая красивая карточка-превью: имя, 4 стата (победы/кирпичи/высотки/короны), силуэт высоток. Картинка генерируется на сервере на лету и обновляется после каждой новой победы.

Кнопка «Сравнить с…» с тремя вкладками:
— Друзья (если есть)
— Топ из leaderboard
— Поиск по точному нику

Открывается страница с двумя городами бок-о-бок, счётом и лидером с короной. Очки = высоток × 100 + корон × 50 + кирпичей (такая же формула используется в холле оф фейм). На самой странице compare есть кнопка «Поделиться сравнением» — копирует ссылку, которая в мессенджерах даёт своё красивое превью с именами обоих и счётом.

В публичном профиле другого игрока теперь есть кнопка быстрого сравнения — в один клик.

ТОП И ЛЕНТА

Холл оф фейм (кнопка «Топ» в панели) — топ-20 игроков по 4 метрикам: размер города (score), кирпичи, высотки, короны. Сверху — глобальные счётчики (всего игроков, кирпичей, высоток). Медали 🥇🥈🥉 за топ-3, твоя строка подсвечена «(вы)». Клик по строке — переход на профиль игрока. У каждой строки — мини-превью в виде SVG-силуэта города (лёгкое, без WebGL).

Если у тебя пустой город — появилась кнопка «Посмотреть топ городов» сразу в экране приветствия — видно куда стремиться.

Новый endpoint /api/buildings/feed/recent — лента последних 20 побед всех игроков + глобальные счётчики за 24ч и всё время. Скоро появится на лендинге и в глобальной ленте.

МЕЛОЧИ

Интро-анимация камеры при первой загрузке и рост башен из земли. ESC закрывает любые модалки. Уважается prefers-reduced-motion — пульсации, дым и погода выключаются.

ПОД КАПОТОМ

2D-fallback для устройств без WebGL переписан под новую модель — SVG-изометрия, зум колёсиком, drag-pan, выбор высотки тапом. На слабых телефонах включается mobile-режим: меньше окон, упрощённые тени, меньше частиц погоды. Рендер приостанавливается когда город вне экрана или вкладка в фоне.

OG-картинки для превью рендерятся через @resvg/resvg-js (Rust binding) — лёгкий, без headless chrome, порядка 50 миллисекунд на картинку. LRU-кэш 500 картинок / 1 час в памяти. Сбрасывается автоматически после новой победы и для личной картинки, и для compare-картинок где этот игрок участвует. POST /api/buildings возвращает обновлённый город сразу — клиент обновляет UI без второго запроса.

Боты мессенджеров не запускают JS, поэтому для корректных preview сделаны SSR-страницы /embed/city/:id и /embed/compare/:id1/:id2 — они отдают og:image и редиректят пользователя на полноценный SPA.

ПОЛИРОВКА 3D

После выкатки релиза прошёлся по 3D-движку с фонариком и закрыл несколько мелких, но обидных проблем.

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

Окна больше не висят в воздухе пока башни вырастают из земли. И при первом появлении города (intro-анимация), и в режиме «История» (time-lapse) — окна теперь появляются только после того как все башни доросли до финальной высоты. Раньше они оставались на финальных позициях пока башни были маленькими — выглядело как парящие в воздухе огоньки.

Запись 8-секундного облёта больше не «съедает» включённый авто-поворот. Если до записи у тебя был активен автоповорот камеры, после видео он восстановится сам. Раньше молча выключался.

Дороги (~10 штук) теперь шарят одну геометрию, материал и текстуру вместо клонирования каждой. Это убрало утечку 10 GPU-текстур и 10 геометрий на каждое открытие профиля.

И глобальная уборка ресурсов — Город побед теперь корректно высвобождает все WebGL-ресурсы при закрытии профиля. Если открывал-закрывал профиль много раз подряд (или у тебя профиль в боковой панели и ты переключаешь вкладки), память на видеокарте больше не растёт. Заодно убраны утечка прогресс-таймера записи (если закрыть профиль во время записи), потерянные обработчики мыши и race condition между размонтированием компонента и анимационным циклом, который изредка давал ошибку в консоли.

Каждая правка по отдельности почти не заметна, вместе — заметно стабильнее работает на длинных сессиях и слабых машинах.