Я не умею программировать и рисовать, но сделал гео-игру про славянских духов. Как ИИ построил Mifozov за неделю
Я не программист и не художник. С ИИ-помощником Claude Code за шесть дней сделал гео-игру в духе Pokémon GO, только со славянской мифологией: ходишь по настоящему городу, ловишь духов, крутишь идолов, торгуешь с Офеней. Ниже — как это было, на чём спотыкался и как выкручивался.
Откуда всё началось
Несколько лет я играл в Pokémon GO. Дело было не столько в покемонах, сколько в прогулках: выходишь вечером «на пять минут», а возвращаешься через два часа, пройдя десять километров. Во дворах собирались люди, ходили на рейды, знакомились, обсуждали, где что появилось.
Потом игра ушла из России, и всё это пропало. Местные чаты затихли, а привычка гулять осталась без повода. Я всё думал: как снова собрать людей и выходить вместе на улицу так, чтобы это было не «надо пройтись», а «пойдём, там Жар-птица».
Своя игра казалась фантастикой. Нужны программисты, художники, сервер, карта, деньги и годы работы. У меня из этого не было ничего, кроме желания.
Что изменилось с ИИ
Когда появились ИИ-агенты, которые не просто подсказывают строчку кода, а сами пишут, запускают, проверяют и исправляют, у меня в голове что-то щёлкнуло. Возможности стали почти безграничными. Человек без навыков программирования и дизайна может собрать своё приложение и воплотить свою мечту примерно за 5% тех сил и денег, которые ушли бы раньше.
Расклад ролей у нас простой. Я — автор идеи, геймдизайнер и «приёмщик»: говорю словами, что хочу, смотрю результат, хожу с телефоном по улице и ругаюсь, если неудобно. Claude Code пишет весь код, сам запускает тесты и браузер, рисует картинки через нейросети на моём компьютере и выкладывает игру на сервер.
Несколько правил, без которых ничего бы не вышло:
· Документы вместо памяти. У ИИ нет памяти между сессиями, поэтому всё записываем: план по фазам, дизайн игры (GDD) и журнал решений «что решили и почему». Сейчас в журнале почти 600 строк.
· Стек под ИИ, а не под человека. Сначала думали про Unity или Godot. Но там много работы мышкой в редакторе, а ИИ удобнее, когда всё — текстовые файлы, которые он может сам запустить и проверить. Поэтому TypeScript везде: Three.js в браузере, Fastify на сервере, общий пакет с правилами игры.
· Фазы и приёмка. Каждая фаза — своя ветка в git. В основную ветку попадает только то, что я принял.
· Одно слово — один ритуал. «Выкладывай» значит: запись в историю изменений → тесты → коммит → проверка, что в коммит не попали секреты → выкладка на сервер → проверка сайта.
· Выбор — за человеком. Когда нужно выбрать картинку, ИИ собирает HTML-страницу с вариантами и галочками. Я отмечаю, пишу правки и копирую ему текст. Сам он варианты не отбирает.
Для масштаба: от первого коммита до нынешней версии прошло шесть дней и больше 140 коммитов. В игре крупные города России, 90 видов духов, идолы, торговец, недельный пропуск, рейтинги, вход через Telegram и приложение для Android.
Так сейчас выглядит карта: настоящие улицы и дома, путник — Ведунья, рядом дух
Карта: «я не узнаю свой район»
Первую карту ИИ сделал «по учебнику»: плоские клетки по 8–10 метров, раскрашенные по данным OpenStreetMap. Технически всё работало, но я свой двор на ней не узнал. Я показал скриншот любимой гео-игры: наклонная камера, тонкие дороги, невысокие блоки домов.
Пришлось менять всё. Phaser (2D) уступил место Three.js с наклонной камерой. Вместо клеток — векторные тайлы: дороги стали линиями своей ширины, дома — своей формы. Затем появилась новая беда: трава «переливалась» и рябила при движении, а дома шли «лесенкой» из пикселей. Решили так: землю рисуем ровными заливками, а лёгкие пятна травы считает видеокарта прямо в шейдере. Пиксель-арт остался только у персонажей и духов.
Деревья растут по хешу координат: у всех игроков одно и то же дерево стоит в одном и том же месте, и в базе данных для этого ничего не хранится. Тысячи деревьев рисуются копиями одной модели, это десятки килобайт памяти.
Духи: от каши из пикселей к живым существам
Это была самая долгая и самая интересная часть. Сразу скажу: художника у меня нет. Всё нарисовано нейросетями на моём ноутбуке (RTX 4060, 8 ГБ) через ComfyUI, а ИИ-агент управляет ComfyUI напрямую, по его API.
Попытка 1: SDXL и скрипт «в пиксели»
Первые восемь духов нарисовала обычная SDXL, а скрипт уменьшал картинку до 40–60 пикселей, сводил цвета к палитре и обводил контуром. Для первой пробы получилось неплохо, но проблемы полезли сразу:
· на маленьком размере детали превращаются в кашу: глаза теряются, лапы сливаются;
· фон вырезался не всегда: у Ауки так и остался белый квадрат;
· нейросеть то рисовала лист с десятком фигурок вместо одной, то упорно превращала духа в «человечка»;
· иконки предметов на 32 пикселях были совсем беда: руны выходили узорными «мандалами», а «красная нить» превращалась в красные цветы. Иконки ИИ в итоге нарисовал кодом, пиксель в пиксель.
Попытка 2: духи, нарисованные кодом
Тогда я попробовал радикальный путь: пусть ИИ рисует духов программой. Из «заготовок» тела (зверь, птица, рыба, змей, жук, колобок, лягушка) и деталей (шерсть штрихами, перья «чешуйками», глаза с бликами) код собирал спрайт и сам его анимировал: Колобок скачет, Баюн водит хвостом, Жар-птица машет крылом. За один день в игре оказались все сто духов.
Потом ИИ перерисовал каждого духа кодом «точь-в-точь» по удачным эталонам на 48 пикселей, с эволюциями и Светлыми версиями. Стало чище, но характера всё равно не хватало: духи были похожи на клипарт.
Попытка 3: конвейер с человеком в середине
В итоге сложился конвейер, который мы записали в арт-гайд как правило:
· 6 вариантов каждого духа в ComfyUI: SDXL + LoRA Pixel Art XL, единый стиль и описание облика. В негативный промпт добавили human, humanoid, clothes, чтобы духи не превращались в людей;
· выбор на HTML-странице: я отмечаю вариант и пишу правки («глаза у Лисы как во втором варианте», «крыло сложить вдоль тела»);
· правки словами через Qwen-Image-Edit 2511: она меняет готовую картинку по тексту и сохраняет персонажа;
· подробная перерисовка через img2img без пиксельной LoRA, после неё BiRefNet вырезает духа: прозрачный фон, без тени и подставки;
· перевод в пиксели на 192 точки со своей палитрой. Для ручной доводки ИИ сделал мне простой пиксельный редактор в браузере. Мои правки хранятся отдельным списком пикселей, поэтому пересборка их не стирает;
· оживление: дух не режется на части, а целиком оживает на видеокарте. Он дышит, моргает, шевелит ушами и хвостом, летающие парят. Разметку (где глаза, где хвост) ИИ делает сам, а я проверяю на странице просмотра.
Одни и те же духи: первая попытка → нарисован кодом → нынешний вариант
Отдельно пришлось следить за мифологией. Человекоподобных персонажей мы не ловим: Сирин, Алконост и Гамаюн — это NPC, а не добыча. Коловрат и спорные неоязыческие символы не используем, на рунах только этнографические орнаменты вышивки и резьбы. Девять уже нарисованных духов я в итоге убрал из игры: они не вписались.
Путники
С героем вышла похожая история. Сначала SDXL нарисовала старца-странника. Потом ИИ нарисовал кодом шесть обликов (с лицом, поясом с кистями, лаптями). В итоге остались два героя, Друид и Ведунья, которых я принёс в виде гифок, а скрипт перевёл их в пиксели по 30 кадров.
Прямо сейчас учим путников поворачиваться во все восемь сторон. Qwen-Image-Edit с LoRA «multiple angles» поворачивает подробного Друида, а дальше из этих кадров соберём ходьбу. Пока нейросеть то и дело дорисовывает вокруг героя лес и каменные плиты, так что работа ещё идёт.
Бросок камня: шесть переделок за пять дней
В Pokémon GO ловят покемонов шаром. У нас духов удерживают обережным камнем: Куриный бог, Громовая стрела, Яхонт и Алатырь-камень. Духа можно задобрить требой: молоком, хлебом-солью, мёдом, лентой.
Сначала я хотел, чтобы обычных духов ловили черчением узоров. Но первая же прогулка показала: на ходу сосредоточиться на черчении трудно, и ловля простых духов начинает раздражать. Черчение оставили для легендарных духов и боссов, а обычных стали ловить броском. Дальше началась эпопея.
· «Рывок в конце». На телефоне палец при отпускании дёргается вбок, а сила считалась по последним ~90 мс. Случайный рывок уводил камень мимо. Теперь короткие отрезки «не вверх» в последний момент отбрасываются, а направление не может уйти от общего взмаха больше чем на 20°.
· Подкрут «как в Pokémon GO». Раскручиваешь палец вокруг камня, и бросок уходит дугой. Сделали дугу, потом настоящую боковую силу от вращения (эффект Магнуса), потом ограничение угла. На улице это не работало: игроки не понимали, куда полетит камень. Один коммит пришлось откатить целиком, а потом подкрут убрали совсем.
· «Управляемая баллистика». Я показал ChatGPT, что не нравится, и принёс в проект его разбор в PDF. Идея была такая: жест прямо задаёт бросок без «настоящей физики». Куда махнул, туда и летит, а сила зависит от длины и скорости взмаха. Стало лучше, но всё равно получался «Pokémon GO, только хуже».
· Рогатка. Это финальное решение. Камень лежит в развилке. Берёшь его, оттягиваешь вниз, к себе, и отпускаешь. Сила зависит от натяжения, направление обратно натяжению: тянешь вправо — камень летит влево. Такую механику понимает любой, кто в детстве держал рогатку, и она перестала быть копией чужой игры.
У рогатки тоже были свои грабли:
· Камень «проскакивал» духа. Попадание проверялось по кадрам, и быстрый камень пролетал между кадрами. Теперь попадание считается формулой: где камень коснётся земли и где пересечёт глубину духа.
· Непонятно, куда целиться. Сначала зоной попадания был прямоугольник вокруг спрайта. Теперь это белый круг-оберег вокруг духа. Мимо круга — «Молоко!».
· Промах «таял» в воздухе. Это выглядело дёшево. Теперь камень долетает по той же дуге до земли перед духом или за его спиной, катится и только потом исчезает.
· Слишком легко подумал я. Поэтому я внес уворот духа в момент поимки: время от времени перебегает к краю экрана и стоит там от 7 до 30 секунд. Камень летит не мгновенно, поэтому целиться нужно туда, где дух будет.
· Сила под экран. Натяжение подобрано так, что 45% силы приносит камень к ногам духа, а 75% — к макушке. Маленькие духи стоят ближе, большие дальше, и кольцо вокруг дальнего меньше.
Чтобы не гадать, ИИ сделал режим отладки (только у меня на компьютере): на экране видна будущая траектория и нужная сила, а каждый бросок пишется в журнал. По журналу видно, какие броски «по ощущениям попал» на самом деле были недолётами.
Отдельно про права. Механики авторским правом не защищены, но у Nintendo и The Pokémon Company есть патенты, связанные с поимкой (вспомним иск к Palworld в 2024 году). Я сознательно не копирую Pokémon GO один в один. Рогатка — хороший пример того, как ограничение подтолкнуло к своему решению.
Честная игра: сервер решает всё
Первые тестеры играли, пока сервер просто хранил сохранение целиком. Так быстрее начать, но «подкрутить» себе прогресс было несложно. Поэтому следующим шагом ИИ переделал всё по принципу «сервер главный»:
· клиент присылает только действие («бросил камень», «поклонился идолу») и своё место, а сервер проверяет и считает награду;
· вся случайность (где появится дух, его статы, исход броска) считается от ключей, подписанных секретом сервера (HMAC). Заранее её не вычислить, перезаходом не перебросить;
· духи, идолы и торговец Офеня не хранятся в базе: это детерминированные функции от координат и времени. Поэтому у всех игроков рядом один и тот же дух, а статы у каждого свои;
· правила и числа баланса лежат в общем пакете, его используют и клиент, и сервер. Расхождений нет.
GPS, Telegram и прочие сюрпризы реального мира
· Казань в Челябинске. Игрок из Челябинска получил «Вы перемещаетесь слишком быстро, подождите 255 минут». Телефон на минуту определил место по вышкам и выдал Казань в 780 км. Теперь вместе с местом уходит точность, и грубые точки (хуже 150 м) не считаются перемещением.
· Не бан, а «духи попрятались». Едешь быстрее ~32 км/ч — духи прячутся и возвращаются через 45 секунд после того, как пошёл пешком. Без наказаний: GPS иногда прыгает у всех.
· Свёрнутая игра. Поиграл дома, свернул, прошёл километр, открыл — «слишком быстро». Проснувшаяся игра отправляла старое место с новым временем. Теперь старые точки отбрасываются.
· Telegram из России. Вход сделан через Telegram, но сервер в РФ не может достучаться до APi телеграма. Помог посредник на Cloudflare Workers. Вебхуки до сервера тоже не доходили, поэтому сервер сам раз в ~25 секунд спрашивает бота о новых сообщениях.
· Приложение. APK — та же веб-игра в обёртке Capacitor, его собирает GitHub Actions. Сначала забыли про постоянную подпись: каждая сборка подписывалась новым временным ключом, и обновиться поверх было нельзя.
Что ИИ не сделает за вас
Звучит так, будто всё делается само. Это не так. ИИ пишет код быстрее, чем я мог бы мечтать, но:
· решать приходится вам. Сто раз в день: какой вариант духа, сколько опыта за поимку, бан или «попрятались»;
· вкус и ощущения не проверить тестами. Что бросок «бесит», я узнал только на улице, с телефоном в руке;
· нужна дисциплина. Документы, журнал решений, ветки, приёмка. Без них через три дня никто не помнит, почему сделано именно так;
· безопасность — ваша ответственность. Перед каждым коммитом скрипт проверяет, что туда не попали адреса, ключи и пароли. Об этом лучше подумать в первый день, а не после утечки.
А если у вас тоже есть мечта, которую вы откладывали, потому что «не умею программировать», — кажется, сейчас лучшее время её достать.













