Проект

Hop & Fill — головоломка для Яндекс.Игр

25 уровней в пяти главах, оптимальный маршрут считается формулой, а реклама и облачные сохранения встроены по правилам платформы

  • Pixi.js
  • React
  • Яндекс.Игры SDK
  • TypeScript

Попробуйте сами

Закрасьте всё поле, не наступая на одну плитку дважды. Управляйте с клавиатуры или свайпами.

Открыть в новой вкладке
Hop & Fill В новой вкладке

Что требовалось от проекта

Головоломка, а не аркада

Закрасить всё поле за ограниченное число ходов. Уровень обязан быть решаемым — и при этом не прощать лишних шагов.

Сложность без подбора на глаз

Минимум ходов нужно считать для каждого уровня, иначе пороги звёзд разъезжаются с реальной сложностью и кампания ломается посередине.

Правила площадки — часть игры

Реклама, сохранения, язык интерфейса, сигнал готовности и портретная ориентация приходят от SDK, а не выбираются нами.

Архив, который пройдёт модерацию

Требования к структуре загружаемого архива жёсткие, и проверять их нужно до загрузки, а не по отказу модератора.

Один маршрут, восемь направлений и плитки, которые ломаются

Плитка закрашивается, когда на неё наступают. Цель — закрасить все и не потратить лишнего хода.

Шаг в восьми направлениях

Ход идёт по горизонтали, вертикали или диагонали. Комбинация клавиш сводится в одно направление, а на тач-экране ход задаётся свайпом с порогом по длине — случайное касание не тратит ход.

Хрупкие плитки и телепорты

Хрупкая плитка ограничивает маршрут, пара телепортов его сокращает. Оба элемента ставятся не для красоты: генератор проверяет, нужен ли телепорт для оптимального прохода и повышают ли хрупкие плитки минимум ходов.

Звёзды и гонка на время

Три звезды даются по порогам числа ходов. Отдельная награда — за скорость: у каждого из 25 уровней свой лимит, от пяти до восьмидесяти секунд.

Пять глав — пять миров

Плюшевая долина, Желейное болото, Неоновая матрица, Столярная мастерская и Бумажный замок, по пять уровней на тему. Тема меняет не правила, а материал плиток и палитру.

Как устроены расчёт сложности и связь с платформой

Две трети инженерной работы в этом проекте лежат не в геймплее, а в том, что вокруг него: сложность уровней и правила площадки.

Расчёт сложности

  • Минимум ходов уровня считается формулой по графу плиток, а не выставляется вручную
  • В формулу входит число плиток, число тупиков и расстояние от старта до ближайшего тупика: каждый тупик, кроме финального, требует возврата
  • Уровень решается поиском маршрута — так проверяется, что он вообще проходим за расчётное число ходов
  • Отдельная команда прогоняет анализ всех уровней и не должна выдавать предупреждений

Интеграция с платформой

  • Игра монтируется только после инициализации SDK; вне платформы работает подменный слой, поэтому локальная разработка не требует площадки
  • Сигнал готовности уходит не по загрузке страницы, а после первой отрисованной сцены — то есть когда играть действительно можно
  • Реклама за вознаграждение после проигрыша даёт десять дополнительных ходов
  • Межуровневая реклама запрашивается только на терминальных переходах и с кулдауном 70 секунд
  • Пауза геймплея и звук согласованы с рекламой и уходом со вкладки, но пользовательское отключение звука не перебивается
  • Прогресс авторизованных игроков идёт в облако платформы, гостевой — на клиент, после входа локальный прогресс переносится в профиль

Сборка и проверки

  • Упаковка идёт одной командой: проверка типов, сборка, валидация каталога, архив, валидация архива
  • Валидатор ловит именно то, на чём падает модерация: абсолютные пути к ассетам, пробелы и кириллицу в именах, попавшие в сборку серверные файлы и переменные окружения
  • Автотесты закрывают расчёт уровней, прогресс, рекламу и жизненный цикл интеграции с платформой

Четыре задачи, которые решали отдельно

  1. 01

    Минимум ходов считает формула

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

  2. 02

    Готовность игры вместо готовности страницы

    Если сообщить платформе о готовности слишком рано, игрок увидит незагруженную сцену и уйдёт. Сигнал уходит после загрузки текстур и первой отрисованной сцены.

  3. 03

    Реклама не должна стоить прогресса

    Показ рекламы приостанавливает игровое время и звук, а возврат восстанавливает их в том же состоянии. То же поведение — при уходе со вкладки. Отключённый игроком звук после рекламы не включается сам.

  4. 04

    Архив проверяется до загрузки

    Отказ модерации стоит суток ожидания. Поэтому структура архива, пути к ассетам и отсутствие лишних файлов проверяются локально, до отправки.

Результат

Игра собрана под требования площадки, а не подогнана под них после отказа.

25 уровней в релизной версии
5 визуальных глав, по пять уровней в каждой
69 автотестов на логике уровней и интеграции
2 языка: русский и английский, язык берётся от платформы

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

Стек технологий

Клиент
React, TypeScript, Vite
Рендеринг
Pixi.js — изометрическое поле, плитки, анимации
Платформа
SDK Яндекс.Игр — реклама, облачные сохранения, локаль, готовность
Стили
Tailwind CSS, Radix UI
Тесты
Vitest и Testing Library — логика уровней, прогресс, реклама
Контент
Собственный анализатор уровней: минимум ходов, тупики, телепорты

Нужен такой же проект?

Собираем браузерные игры под площадки: геймплей, интеграция SDK, упаковка и прохождение модерации.