Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

ИИ-картограф: как карты сшиваются в бесшовный мир — тулсеты (toolsets) для MMORPG игр на PHP, ч. 21

Дата публикации: 12-08-2026 11:14:07

Я сшил разрозненные карты MMO в один бесшовный мир: игрок выходит из города в пустыню и не замечает, что под ним уже работает другой сервер. А всю рутину картографа — импорт, разметку препятствий, разрезание карт и проверку связей — отдаю ИИ. Заодно проверил, что происходит, если доверить ему игровую графику Читать далее

Основное содержимое страницы с новостью.

Карта тайлового мира — это файл: несколько слоёв тайлов, слой непроходимых клеток и объекты-двери, у каждой в свойствах записаны карта назначения и клетка прибытия. Законченная единица, нарисованная отдельно от соседей. Края карт заходят друг на друга на десяток клеток, тропа с одной упирается в обрыв на соседней, а переход между ними всегда телепорт с экраном загрузки.

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

Что происходит с картой по дороге в мир: слева дверь-телепорт с экраном загрузки, справа бесшовный стык

Что происходит с картой по дороге в мир: слева дверь-телепорт с экраном загрузки, справа бесшовный стык

Коротко о проекте

С 2022 года я в одиночку веду дневник разработки: делаю авторитарный сервер для 2D MMO RPG — игры с открытым бесшовным миром, где сотни игроков и существ живут в реальном времени. Сервер на PHP и Symfony, клиент на Unity, правду о мире считает только сервер. С семнадцатой части в проекте работает ИИ: механику я описываю словами, а собирает её он — и на сервере, и в клиенте, через свой протокол доступа к данным и коду игры. В прошлой части был контур проверки, который не даёт этой сборке молча разъехаться с задумкой: спеки, агенты-ревьюеры, прогон по живому серверу.

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

Карты я беру из The Mana World, открытой MMO с историей длиннее моей. Её мир рисовали люди и достраивали годами, а лицензия позволяет брать его в работу. Мне он нужен как настоящий полигон: синтетическая карта из трёх домиков не покажет ни одной живой проблемы.

f9cdb24f30dbaac95f4b57af7924d1ad.png

Миры игры: открытый мир из трёх состыкованных карт, отдельные подземелья, пещеры и городские интерьеры — каждый мир ставится и снимается целиком

Карта — это процесс, а не картинка

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

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

c458940c2598c4b65b79bf05ddfb63d5.png

Слева раскладка открытого мира, справа приближение к стыку: городская стена с воротами стоит ровно на границе карт

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

Граница, которой не видно

Сам переход устроен так. Игрок доходит до кромки, его карта отдаёт клиенту адрес соседнего процесса и одноразовый пропуск. Клиент переподключается к новому адресу и продолжает идти. Ни экрана загрузки, ни возврата в меню, ни паузы на вход в локацию.

a3f82963f11d9b10e0db0cb6d8fccf2d.png

Сверху персонаж в тех же воротах, номер карты — 54. Снизу он же шагом южнее: ворота видны вверху кадра, номер уже 55

Самое интересное здесь не сам переход, а то, из чего рождается граница.

Поставить две карты рядом на раскладке мало. Соседство даёт только соприкосновение краёв, а пройти игрок сможет там, где непроходимые клетки убраны с обеих сторон. Границу открывают дыры в преградах, и ничего кроме них.

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

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

Что из этого делает ИИ

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

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

Заливка одной карты — цепочка шагов, и каждый шаг машина делает сама.

Импорт. Карта приезжает вместе со своими наборами графики одним архивом. Сам разбор формата Tiled у меня появился давно, ещё в седьмой части, и с тех пор не менялся. Изменилось то, что происходит с картой дальше.

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

Срез мёртвых краёв. Карты источника лежат с перекрытием: по краям идут ряды-заглушки, закрывающие игроку выход наружу. Их срезают, а величину среза читают по самой карте — сколько рядов с краю занято сплошной стеной. Дальше начинается рельеф, и резать его нельзя.

Разрезание. Один файл источника часто содержит десяток не связанных между собой комнат: трактир, банк, тюрьму, кузницу. У меня каждая становится отдельной картой со своим процессом. Из городских интерьеров Тулимшара так вышло семь карт, из пустынных — одиннадцать. Заодно приходится перенацелить все двери, которые вели в общий файл.

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

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

Приборная панель вместо веры на слово

Отдать машине руки мало. С кодом эту роль играют контракты и прогон по живому серверу, с картами нужен экран, где сразу видно, что она натворила.

У меня это схема переходов: граф всех карт игры и всех связей между ними. Бесшовные стыки идут пунктиром, двери — линиями, и у каждой связи разобрана цель: какая карта, в какую клетку прибывает игрок.

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

9abb601d28d5cb57ba80e1f0746dc52d.png

Схема переходов: пунктир — бесшовные стыки, линии — двери, справа разбор поломок

Разница между «сломано» и «ещё не сделано» звучит мелочью, пока карт десяток. На сотне без неё работать невозможно.

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

Чего ИИ не умеет

Данные машина ведёт отлично. С картинками всё иначе, и граница проходит резко.

Claude, которым я работаю, прекрасно кроит атлас механически: обрезать, расширить холст, вклеить недостающие тайлы, переписать их свойства. Рисовать он не умеет и вида не делает.

Поэтому графику я отдал генеративной модели. Задача была понятная: сделать ремастер набора — осовременить рисунок, сохранив размер тайла, пропорции и сетку. Тайл ведь не картинка, а ячейка: он обязан лечь ровно в свои тридцать два пикселя, иначе поедут все карты, где он стоит.

Этот заход сразу показал главное: рисунок действительно осовременивается. Камень стал объёмным, у арки появилась фактура, песок перестал быть плоской заливкой. Стиль игры при этом узнаётся — инородного модель не притащила.

4230dc7b0a5ac489447a176f92138c51.png

Слева исходный набор, справа он же после ремастера

А дальше начинаются детали, из-за которых набор пока не поехал в игру. Прозрачности для модели не существует: пустые места между объектами она закрашивает камнем — на кадре выше этот фон уже вырезан, но об этом чуть ниже. Кое-где вместо исходного предмета нарисовано своё. И главное — содержимое клеток съехало на пару пикселей. Тайл обязан укладываться ровно в свои тридцать два: сдвиг на два даёт шов на каждой стене, где этот тайл повторяется.

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

Есть и развилка, из которой я пока не вышел. Когда модель видит весь набор целиком, ей достаётся горстка пикселей на тайл и правки выходят косметическими. Когда режешь набор на куски и увеличиваешь каждый, деталь появляется — но соседние куски начинают жить разной жизнью, и посреди одной стены меняется манера рисунка. Либо однородно и скромно, либо детально и вразнобой.

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

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

Что дальше

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

Вопрос к вам. Кто делал открытый мир: как у вас решён момент, когда игрок стоит на границе двух серверов и ровно в этот момент в него летит удар? Интересны ваши грабли, а не теория.

История
  1. Платформа для 2D MMO вместо очередного игрового сервера

  2. Почему одного процесса не хватит: асинхронность и масштаб

  3. Почему игровому серверу нужен WebSocket, а не HTTP

  4. Redis как память игрового мира: сколько игроков и NPC он держит

  5. Lua или JavaScript в песочнице: чей код быстрее на сервере

  6. Выбор технологий и ECS: почему архитектура быстрее языка

  7. Тайловые карты: импорт локаций из Tiled одной строкой

  8. Клиент на Unity для авторитарного сервера: что он обязан уметь

  9. Игровые механики без обновления клиента: события на сервере

  10. Бесшовный мир в 2D MMO: локации на разных машинах

  11. Почему персонаж телепортируется: пинг, интерполяция и экстраполяция

  12. Очереди без RabbitMQ: обмен между процессами в памяти

  13. Event-driven и JSON-RPC: почему игровой сервер не собран из сервисов

  14. Не размер пакета: где на самом деле узкое место сетевого сервера

  15. Почему сервер собран на процессах, а не на потоках

  16. MVP авторитарного сервера для 2D MMO: три года и что получилось

  17. Внедряю ИИ: механики из одного описания

  18. Конвейер контента для MMO: импорт анимации, экипировка и обновление игры без патчей

  19. Каталог ассетов и git для MMO: как командой вести игру в облаке

  20. Тесты для кода, который пишет ИИ: контракты вместо ассертов

  21. ИИ-картограф: как карты сшиваются в бесшовный мир

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1Как ИИ не дал загнуться ещё одной ноунейм игре. Даже текстовой08.8824-07-2026
27 месяцев вайбкодинга: как в одиночку делать то, что раньше требовало команду0901-08-2026
37 месяцев вайбкодинга: как в одиночку делать то, что раньше требовало команду0901-08-2026
4DS MCP: как дать AI-агенту знание о вашей дизайн-системе7808-07-2026
5ИИ-Автопилот: замкнутый цикл разработки на C++ — от тикета до проверки в живом GUI08.2229-07-2026
6ИИ-Автопилот: поток принятых задач вырос в тринадцать раз18.8231-07-2026
7Ааа, всё пропало! AI создаёт дырявый код! Что же делать?011.4316-06-2026
8Невыносимая слопность бытия010.7325-07-2026
9Книга: «Эффективный разговорный ИИ. Создаем чат-ботов, которые действительно работают»012.4929-04-2026
10Для русскоязычной версии игры Throne and Liberty вышло первое крупное обновление05.4912-08-2026

Классификация: Пресс-релизы. Схожих патентов: 0. Схожих новостей: 10. Тональность: 0. Информативность: 10.08. Источник: habr.com.