|
Professor Seleznov
|
Всем привет! Меня зовутАмир Утеуов — я ML-инженер из Авито. В этой статье поделюсь своей историей создания мобильной игры DevRush, пет-проекта, который перерос в игру на стенде IT-конференции CodeFest 2025.
Однажды у меня под рукой оказался датасет из иконок различных фреймворков и языков программирования. Так я решил разработать приложение, где нужно как можно быстрее находить и выбирать иконки языков программирования среди случайных иконок. До этого я не занимался разработкой и публикацией мобильных игр и приложений, но решил пройти весь путь с нуля. Статью разделим на две части: в первой расскажу как создавал первую версию игры и с какими трудностями столкнулся, а во второй — как мы готовили игру к конференции. Если подробнее, вот, что будет в первой части статьи:
 Почему Flutter Начнем с самого главного — выбора на чём написать проект.
 Мне нравится идея кроссплатформенных приложений. Благодаря такому решению приложение, написанное на одном языке программирования, будет работать аналогично и на мобильном устройстве (iPhone, Android), и на компьютере, и в Web. Из множества вариантов реализации самым подходящим мне показался Flutter. Flutter — фреймворк для разработки кроссплатформенных приложений на языке программирования Dart. Dart — это С-подобный язык с некоторыми интересными фишками. Язык был создан Google для разработки кроссплатформенных приложений и значительно упрощает её за счет встроенных механизмов. Например, hot reload позволяет менять программный код, благодаря чему сразу меняются:
- отображение;
- логика работы экземпляра приложения в эмуляторе (или на реальном устройстве);
- вычисляемые переменные в runtime проекта.
Во Flutter удобный набор виджетов для основных компонентов в едином дизайне, которые можно гибко настраивать. Механизм event loop, позволяет в одном потоке осуществлять асинхронную работу, управляя очередью поступающих событий. Я прочитал туториалы по Flutter и нашел отличный бесплатный курс по Dart. Так без бэкграунда разработчика мобильных игр я принялся за разработку. Следующим шагом я нарисовал схему приложения для реализации:
 Приложение должно было состоять из экранов меню, игры, информации и победы или завершения игры. Нужен был также таймер обратного отсчета. Писал игровую логику я сам, не зная про игровой движок Flutter Flame, сейчас бы использовал его. Для начального таймера я поставил 16 секунд и этого было много (позже время было пересмотрено до 32 сек).

Тут еще больше контента Выбор языков программирования для иконок игры Я выбрал те языки программирования, которые мне казались распространенными. Чтобы игра была интересна и не слишком сложна, в нее были включены живые языки программирования (на которых еще разговаривают/программируют) и стабильные языки (релизы которых не находятся в тестировании). Именно поэтому я вручную отобрал только те, которые имеют сообщество, регулярно обновляются и поддерживаются. Например, в датасет попал Fortran, так как для него выходят обновления и новые стабильные релизы. Но не был добавлен язык Mojo Script, потому что он был в альфа-тестировании на момент разработки. Также я хотел добавить побольше бесплатных/открытых general-purpose языков программирования. Например, есть язык для SAP Abap или 1С, но они не является языками общего назначения (general purpose programming language). По тем же причинам в набор я не добавлял языки смарт-контрактов Solidity, Plutus и т.д. Различные языки запросов и разметки я тоже не добавлял в датасет. Языков программирования совсем немного, но вот фреймворков/пакетов/библиотек предостаточно. Например, 700 тыс. в pypi Python, 18 млн в maven репозитории Java, 3.6 млн в npm JavaScript и т.д. Поэтому из начального датасета я отобрал знакомые технологии: вышло около 250 иконок. Геймплей Напомню задумку: игроку необходимо как можно быстрее найти на экране иконку определенного языка программирования. Базово сложность устроена так: чем выше уровень — тем больше ЯП нужно найти среди большего количества иконок. Как я определил сложность по уровням:
- На уровне «Junior» у каждого логотипа есть текстовая подпись — название языка или фреймворка/технологии.
- На уровне «Middle» у половины иконок нет подписей — нужно искать по образу в памяти.
- На уровне «Senior» у всех иконок нет подписей, только сам лого.
Проект был максимально простой, и, посмотрев на датасет, я понял, что неявно знаю 90% иконок. Также я хотел, чтобы игра чему-то учила и давала новые знания тем, кто не знает часть технологий. Чтобы добавить определения технологий, написал скрипт на Python, который гуглит каждое название через DuckDuckGo API. Получилось вот так:
 Все термины и определения изначально были на английском. Чтобы выпустить игру поскорее, на русском языке дублировать не стал.

Таблица с информацией для игры Реализация проекта на Flutter После выбора стека разработки нужно было установить все необходимые зависимости в систему. Здесь уже можно столкнуться с проблемами, если у нас какая-то особенная конфигурация ОС. На Flutter обычно создается проект из шаблона, где есть все необходимые классы и файлы настроек. Далее этот проект уже собирается из консоли VS Code для Web, Desktop, Android и iOS. Также можно использовать FlutLab, чтобы разрабатывать приложение в облаке, на случай если локально вы не можете/не хотите устанавливать все зависимости.
Я создал проект и начал добавлять нужные мне экраны и классы. Интересная особенность Flutter заключается в том, что приложение обновляет элементы через event loop. Его нужно хорошо понять, чтобы добавленные изменения не затормозили приложение, а интерактивные компоненты остались изменяемыми. Начальный дизайн я сделал из дефолтных стилей, но отдельно добавил темную тему.
Необходимые файлы сохранил локально в проекте в assets — это папка, в которой мы храним ресурсы приложения. В ней я сохранил датасет, скачанные иконки из датасета и анимации. В проекте используются PNG-изображения: они поддерживают прозрачный фон/alpha-канал. Однако некоторые иконки были недостаточно разборчивы на белом или же темном фоне, поэтому я добавил дополнительный фикс, чтобы при необходимости обвести изображение по контуру. В первой версии проекта в названии картинки я закодировал нужную информацию. Файл назывался в формате: Name_Category_NeedBorder.png. Например, «Python_pr_nbrr.png» означало, что это картинка технологии «Python» из категории «Programming Language» и «nbrr» – не нужна граница. «Nbrr» – достаточно длинный тег, который вряд ли встретится при добавлении новых изображений, но это потенциальный баг. Основной экран состоял из класса игры, асинхронной загрузки поля игры и таймера в параллельном потоке. Экран завершения игры я сделал простым: в случае ошибки открывается название технологии. После игры можно посмотреть все открытые ячейки-карточки с технологиями и прочитать их короткое описание, а также перейти по ссылке в поисковик и почитать ещё подробнее. Всего я добавил 64 уровня с постепенным увеличением количества технологий/иконок для выбора. Начиная с двух до восьми иконок на фиксированном поле 4x4. Также я добавил режим контеста — при фиксированном random seed можно было запустить на разных устройствах одно случайное поле. Идея была в том, чтобы соревноваться с друзьями на скорость.


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

Жми сюда! Векторная анимация — главная сложность проекта Дольше всего я рисовал анимацию разлетающихся иконок в векторном формате lottie animation, которые далее портировал в JSON. Анимации генерировал скриптом на Python, а эффект взрыва настраивал через easings. Иконки фреймворков в векторе частично я нашел, а частично нарисовал сам на Python. В этом увлекательном процессе я вспомнил программирование в школе, где нужно было двигать частицу по формулам из физики. Чтобы иконки были будто случайными я сгенерировал 10 разных вариантов анимации, сохранил их в файлах проекта, чтобы при запуске случайно выбирался один из них. Такую логику можно было полностью сделать на Flutter, рисуя и управляя объектами на чистом Dart (причем действительно каждый раз случайно), но тогда мне это показалось сложнее, поэтому оставил в to-do. Анимация экрана победы
 Сборка проекта Flutter проект можно собрать в нескольких вариантах: Web, Desktop, Android, iOS, а также в Debug и Release. Самое простое — debug-версия, которая подписывается debug-ключом. Она может быть использована через установку из apk файла на любом Android устройстве, если пользователь установит файл из неопределенного источника. Правда код будет без всех release оптимизаций, так как используется JIT компиляция. Для публикации в Google Play сейчас необходим формат App Bundle (.aab). Это формат файла, который содержит в себе зависимости под разные устройства. Из него можно сконфигурировать и выгрузить только необходимые изменения под определенное устройство, а также загрузить только измененные части проекта, классы, ресурсы и т.д. Например, после обновления игры в маркете мне потребовалось скачать только обновление размером 14КБ вместо всего приложения весом 10 МБ. Для сборки под iOS потребуется Mac OS и установленная XCode свежей версии, так как App Store периодически поднимает версию iOS, которую должно поддерживать приложение. Сейчас существуют некоторые сложности публикации приложений в App Store, Google Play из России. Но, допустим, у вас уже есть аккаунты разработчиков в Google Play, App Store. Из-за санкций сейчас российским аккаунтам нельзя создавать платные приложения — только бесплатные и без внутренней системы монетизации. Сначала я опубликовал игру в Google Play: при первой публикации нужно подождать пару дней, чтобы ее проверили модераторы. Самыми сложными были процессы настройки правильной подписи сертификатом приложений и корректное размещение всех ключей во всех файлах настроек. Внутри Dart-проекта для каждой платформы создается папка со всей метаинформацией: Android, iOS, Web и так далее. В каждой папке отдельный проект, который может быть открыт соответствующей IDE, например, Android Studio и XCode. Правда, внутри, кроме настроек приложения и одного файла, который импортирует и вызывает Flutter приложение, особо ничего и нет. Основная работа и настройка идет в самом Flutter проекте. Как пройти модерацию При первой публикации в App Store игру отклонили по очень неожиданной причине. На одном из экранов игры при режиме игры OS была иконка операционной системы Android (среди Windows, MacOS, Linux, Debian и т.д.). Мне прислали скрин с выделенной иконкой Android и написали, что по правилам AppStore нельзя рекламировать продукты конкурентов.
 Это было забавно, ведь в контексте игры являлось уместным использованием логотипа. К сожалению, мне пришлось удалить эту иконку. Этот случай наводит на мысль, что в App Store используются автоматические средства проверки приложений с детектом и распознаванием изображений, так как маловероятно найти именно такой экран с иконкой Android среди всех режимов и уровней игры. Выводы
- Разрабатывать игры весело и интересно, в процессе я узнал много нового.
- Публикация игры в первый раз занимает приличное время.
- Я начал разработку, исходя из данных, и прошел путь от идеи до публикации, имея четкое представление схемы данных. Это помогло мне реализовать игру, не возвращаясь к изменениям различных частей.
- Flutter, в моём случае, показал себя с лучшей стороны. Функционала для моей простой игры было достаточно. Каких-то особых сложностей не возникло.
- Проблемы с производительностью Flutter обычно возникают, если делать какие-то тяжелые операции в шаге build event loop. Обычно помогает разделение логики вычислений.
- Программировать векторную lottie анимацию на Python достаточно ресурсозатратно, но увлекательно. В моем случае пришлось находить базовые элементы в SVG, потом писать логику анимации на Python в pylottie, экспортировать в .json и импортировать уже во Flutter приложение. Тема стоит отдельной статьи.
To be continued В данном виде игра существовала некоторое время, пока ко мне не подошли коллеги и не предложили использовать ее на стенде Авито на конференции Code Fest 2025. Как мы готовились, как был добавлен новый дизайн, веб-лидерборд и как прошла активность на конференция расскажу в следующей части! Что ещё посмотреть по теме

Кликни здесь и узнаешь-Источник
|