惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 聂微东
大猫的无限游戏
大猫的无限游戏
IT之家
IT之家
月光博客
月光博客
博客园_首页
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
AWS News Blog
AWS News Blog
S
Securelist
T
Tailwind CSS Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
罗磊的独立博客
D
Docker
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
Scott Helme
Scott Helme
H
Help Net Security
Project Zero
Project Zero
P
Proofpoint News Feed
D
DataBreaches.Net
Recorded Future
Recorded Future
Simon Willison's Weblog
Simon Willison's Weblog
V2EX - 技术
V2EX - 技术
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog
I
Intezer
Engineering at Meta
Engineering at Meta
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
I
InfoQ
酷 壳 – CoolShell
酷 壳 – CoolShell
雷峰网
雷峰网
S
Secure Thoughts
GbyAI
GbyAI
U
Unit 42
Blog — PlanetScale
Blog — PlanetScale
T
Threat Research - Cisco Blogs
The Last Watchdog
The Last Watchdog
Y
Y Combinator Blog
F
Fortinet All Blogs
博客园 - Franky
T
The Blog of Author Tim Ferriss
Hacker News: Ask HN
Hacker News: Ask HN
Microsoft Security Blog
Microsoft Security Blog
Stack Overflow Blog
Stack Overflow Blog
S
Security @ Cisco Blogs
Cyberwarzone
Cyberwarzone

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Как я сделал на Flutter игру для разработчиков
submaps (Avi · 2026-05-12 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение8 мин

Охват и читатели852

Кейс

Всем привет! Меня зовут Амир Утеуов — я ML-инженер из Авито.

В этой статье поделюсь своей историей создания мобильной игры DevRush, пет-проекта, который перерос в игру на стенде IT-конференции CodeFest 2025.

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

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

Если подробнее, вот, что будет в первой части статьи: 

  1. Почему Flutter 

  2. Выбор языков программирования для иконок

  3. Геймплей

  4. Реализация проекта на Flutter

  5. Векторная анимация — главная сложность проекта

  6. Анимация экрана победы

  7. Сборка проекта

  8. Как пройти модерацию

  9. Выводы

  10. Что ещё посмотреть по теме

Почему 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 иконок.

Геймплей

Напомню задумку: игроку необходимо как можно быстрее найти на экране иконку определенного языка программирования. 

Базово сложность устроена так: чем выше уровень — тем больше ЯП нужно найти среди большего количества иконок. Как я определил сложность по уровням: 

  1. На уровне «Junior» у каждого логотипа есть текстовая подпись — название языка или фреймворка/технологии.

  2. На уровне «Middle» у половины иконок нет подписей — нужно искать по образу в памяти.

  3. На уровне «Senior» у всех иконок нет подписей, только сам лого.

Проект был максимально простой, и, посмотрев на датасет, я понял, что неявно знаю 90% иконок.

Также я хотел, чтобы игра чему-то учила и давала новые знания тем, кто не знает часть технологий. Чтобы добавить определения технологий, написал скрипт на Python, который гуглит каждое название через DuckDuckGo API.

Получилось вот так:

ae04c06884a59f83e4c2eb07884e46f6.png

Все термины и определения изначально были на английском. Чтобы выпустить игру поскорее, на русском языке дублировать не стал.

8e1a1dff1106ba8a2bbc67351983da46.png

Таблица с информацией для игры

Реализация проекта на 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 можно было запустить на разных устройствах одно случайное поле. Идея была в том, чтобы соревноваться с друзьями на скорость.

fe6a16cb6d42d07bf1c18b4e8df5abb3.png
19f783260878185819849410e4e1dcee.png

Экраны моей игры

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

Жми сюда!

Жми сюда!

Векторная анимация — главная сложность проекта

Дольше всего я рисовал анимацию разлетающихся иконок в векторном формате 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 нельзя рекламировать продукты конкурентов.

95172a751de8c5def6a0f9b585f6cd2d.png

Это было забавно, ведь в контексте игры являлось уместным использованием логотипа.

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

Выводы

  1. Разрабатывать игры весело и интересно, в процессе я узнал много нового.

  2. Публикация игры в первый раз занимает приличное время.

  3. Я начал разработку, исходя из данных, и прошел путь от идеи до публикации, имея четкое представление схемы данных. Это помогло мне реализовать игру, не возвращаясь к изменениям различных частей.

  4. Flutter, в моём случае, показал себя с лучшей стороны. Функционала для моей простой игры было достаточно. Каких-то особых сложностей не возникло.

  5. Проблемы с производительностью Flutter обычно возникают, если делать какие-то тяжелые операции в шаге build event loop. Обычно помогает разделение логики вычислений.

  6. Программировать векторную lottie анимацию на Python достаточно ресурсозатратно, но увлекательно. В моем случае пришлось находить базовые элементы в SVG, потом писать логику анимации на Python в pylottie, экспортировать в .json и импортировать уже во Flutter приложение. Тема стоит отдельной статьи.

To be continued 

В данном виде игра существовала некоторое время, пока ко мне не подошли коллеги и не предложили использовать ее на стенде Авито на конференции Code Fest 2025. Как мы готовились, как был добавлен новый дизайн, веб-лидерборд и как прошла активность на конференция расскажу в следующей части!

Что ещё посмотреть по теме 

Кликни здесь и узнаешь

Кликни здесь и узнаешь