В прошлых статьях:
1 Итоги 2025 года: Часть 1/4 (Игры)
2 Итоги 2025 года: Часть 2/4 (Сервисы и утилиты)
3 Итоги 2025 года: Часть 3/4 (Визуализации)
Эксперименты
Я долго работал над этой статьей, потому что материал получился объемным. Поэтому я решил разбить финальную часть итогов года на несколько статей и дать больше инженерной информации о том, какие решения применял ИИ. Думаю это интереснее, чем просто писать о том, как с помощью диалога с ИИ написать приложение. Мне кажется мы достаточно осветили эту часть работы с ИИ.
Тут я оставлю список проектов, который будет освещен в цикле статей Эксперименты 2025 года:
1. Автономный лабиринт
2. ZX-загрузчик
3. Космический аквариум
4. Аудиопроигрыватель
5. Бои гладиаторов
6. Симулятор турниров
7. Симулятор алхимии
8. Биологический инженер
9. Неизвестный коллайдер
10. Уютная погода
11. Криптоархеология
12. Наса
13. Сеть
14. Демонстрация возможностей
Автономный лабиринт
Идея была простой:
1. Сделать генератор лабиринтов
2. Сделать интеллект, который бы проходил этот лабиринт
Помимо этих простых идей я подумал, а почему бы не сделать несколько персонажей, которые бы искали друг друга в лабиринте.
Для каждого сделать разный уровень интеллекта.
Когда персонажи находят друг друга - они связываются в буквальном смысле - устанавливают видимую связь и ходят дальше по лабиринту в связке.
Можно и дальше развивать эту идею. Например определить - кто в связке принимает решения. Делится ли группа знаниями о лабиринте, чтобы повысить эффективность.
И я наверное этим займусь на досуге.
Как таковой практической значимости у эксперимента, наверное нет. Разве что отработать некоторые механики и возможности персонажей, которые можно потом переиспользовать в других проектах.
Некоторые из особенностей моей реализации:
Персонажи не могут развернуться на 180°, кроме случаев тупика.
Один персонаж запоминает пройденные пути и избегает тупиков.
Лабиринт без тупиков? Нет, с идеальными тупиками
ИИ не стал использовать случайную расстановку стен — это привело бы к несвязным областям. Вместо этого он применил алгоритм поиска в глубину (DFS) с рекурсивным бэктрекингом для генерации лабиринта. Суть: алгоритм «проходит» по ещё не тронутым клеткам, прорубает проходы, а когда заходит в тупик — возвращается назад и ищет новый путь. В результате получается идеальный лабиринт: между любыми двумя точками существует ровно один путь. Никаких циклических коридоров, что заставляет персонажей действительно блуждать, а не ходить по кругу.
Кстати, размер лабиринта динамически подстраивается под окно браузера — ИИ рассчитал, что ширина и высота должны быть нечётными, чтобы алгоритм DFS работал корректно (стены и проходы чередуются).
Никаких «топтаний на месте»
Одно из моих требований: персонажи не должны резко разворачиваться на 180°, если только не попали в тупик. ИИ реализовал это простым, но гениальным правилом: каждое направление хранит ссылку на «противоположное». Когда персонаж выбирает следующий шаг, из списка возможных направлений удаляется то, которое ведёт назад (если только других вариантов нет).
Это трёхстрочное условие — и персонажи перестали «дёргаться» вперёд-назад.
Стратегия «иди туда, где был реже всех»
Первый персонаж в игре — «лидер». Он не просто запоминает пройденные клетки (Map с координатами), но и при выборе направления сравнивает число посещений каждой соседней клетки. Выбирает ту, где был минимальное количество раз. Это простейшая форма исследования неизвестной местности — он автоматически избегает уже исхоженных коридоров и стремится в новые.
Более того, если такой персонаж попадает в цепочку, его память никуда не девается — он продолжает передавать своим ведомым «знание» о том, куда ходить не стоит. В текущей версии цепочка не обменивается картами (это я планирую добавить), но ИИ уже заложил фундамент для коллективного интеллекта.
Луч зрения, отрисованный математикой
Чтобы искатели могли целенаправленно двигаться друг к другу, ИИ реализовал проверку прямой видимости. Функция isPathClearHorizontal просто идёт по строке лабиринта от одного персонажа к другому и проверяет, нет ли на пути стен (единиц). То же самое по вертикали.
Если путь свободен, оба персонажа получают targetPlayer и флаг isMovingToTarget. Для движения к цели выбирается приоритетное направление: сначала горизонтальное, потом вертикальное (или наоборот — в зависимости от разницы координат). Это заставляет персонажей идти по прямой к друг другу, однако из-за лабиринта им приходится огибать стены — и тут в дело вступает стандартный интеллект (выбор направления с минимальными посещениями или случайный).
Такая гибридная система (глобальная цель + локальный поиск пути) очень похожа на поведение животных в стае — и ИИ реализовал её буквально за один промпт.
Как они ходят вместе?
Когда два персонажа встречаются на одной клетке, они образуют цепочку. ИИ не стал делать сложную физику — он поступил хитро. У каждого персонажа в цепочке есть ссылка на предыдущего. При движении лидера (первого в цепочке) все остальные просто перемещаются на предыдущую позицию предыдущего игрока. Для этого специально сохраняется prevX/prevY перед каждым шагом.
Это даёт эффект «идеального следования» без проскальзываний. Визуально на экране цепочка рисуется белыми линиями между участниками — выглядит как настоящая связка.
Что важно: объединение цепочек работает независимо от порядка. Если встречаются две группы, ИИ просто сливает одну в конец другой, обновляя идентификаторы. Вся структура данных — массив chains, где каждая цепочка хранит массив индексов игроков — позволяет легко управлять слиянием и отрисовкой.
Чего вы не видите, но ИИ это предусмотрел
- Защита от бесконечного цикла: если у персонажа нет ни одного возможного хода (заблокирован со всех сторон), он просто остаётся на месте — программа не падает.
- Автомасштабирование холста: размер лабиринта пересчитывается при изменении окна браузера, но только если игра не запущена — чтобы не ломать текущий сеанс.
- Эффект «цепной реакции»: когда все персонажи собираются в одну цепочку, игра останавливается и показывает сообщение с числом шагов. ИИ добавил это условие в gameLoop — простая проверка, но без неё процесс ушёл бы в бесконечность.
ZX-загрузчик
Тот, у кого в начале 90х был ZX-spectrum думаю разделят мою ностальгию по этой машине, способной загружать программы (в том числе и игры) с обычных для того времени аудиокассет. О, этот волшебный звук!
Идея эксперимента проста, воссоздать с помощью ИИ тот самый звук, тот самый процесс загрузки. И пришлось изрядно побороться с ИИ, чтобы он:
1. Нашел всю информацию о ZX-spectrum
2. Нашел доступные библиотеки звука
3. Воссоздал визуальную часть
4. Создал алгоритм загрузки изображения
В качестве бонуса, после загрузки в моем случае появляется игра - Змейка. Ну, вы все ее прекрасно знаете.
Предлагаю потом скачать исходник и также заценить тот самый УЖАСНЫй звук загрузки.
Звук загрузки: цифровая реинкарнация визга
Главная узнаваемая черта ZX-загрузки - это звук. ИИ использовал Web Audio API и создал полноценный синтезатор импульсов. Он генерирует звук в реальном времени на основе параметров реального Spectrum:
- Пилот-тон: частота ~1300 Гц, длительность импульса 16 мс, интервал 18 мс — это даёт характерный «вибрирующий» гул перед данными.
- Тоны данных: бит 0 - 1350 Гц, бит 1 - 675 Гц (как в оригинальном формате). ИИ даже добавил псевдослучайную последовательность битов, чтобы звук не был монотонным.
- Активная загрузка: хаотичная смесь частот от 800 до 1500 Гц с микро-длительностями (3–8 мс), имитирующая настоящий «треск» данных.
Все звуки имеют огибающую без щелчков (linear ramp) и отдельный gain-узел для громкости.
Визуальный бордюр: полосы, которые «плывут» как на старом телевизоре
У ZX Spectrum во время загрузки экранный бордюр (border) заполнялся цветными полосами - это был индикатор чтения данных. ИИ реализовал этот эффект с бесшовной анимацией:
- Полосы рисуются динамически с помощью requestAnimationFrame.
- Каждая полоса имеет случайный «джиттер» позиции и высоты - имитация аналоговых помех.
- Цвета полос меняются в зависимости от фазы загрузки: жёлтый/синий, пурпурный/голубой и т.д.
Эта техника гарантирует, что полосы никогда не обрываются на границе экрана - они «заворачиваются» сверху, создавая непрерывный движущийся узор. Именно так выглядела реальная загрузка на старых телевизорах.
Прогрессивная загрузка PNG: строки сверху и снизу одновременно
Главная обложка на ZX-Spectrum имела несколько вариантов загрузки. Мне всегда нравился тот вариант, когда рисунок словно пазл заполняется построчно сверху и снизу пропуская каждый раз 1 строку. А затем в центре заполняющиеся строчки пересекались и заполняли уже пробелы друг друга.
ИИ довольно легко понял о чем речь и реализовал алгоритм, где одна итерация рисует строку сверху и строку снизу одновременно.
Космический аквариум
Все началось довольно просто. Мне как-то попался архив с 3д объектами из игры Elite 1984 года, которая к слову сказать была на ZX-Spectrum. Мне было лень искать программу для просмотра этих объектов, я пошел проторенной дорожкой. Так ИИ написал мне простенький 3д viewer для 3д файлов. Конечно, с первого раза редко бывает все идеально. Потом путем диалога я попросил поправить масштаб, реализовать органы управления для вращения моделью.
На скрине выше видно, что объект отрисован только за счет его ребер. Сами плоскости не закрашены ! и тут важно отметить, что при этом мы не видим ребер, которые находятся ЗА невидимыми плоскостями. Это позволяет нам воспринимать объект привычным глазу образом.
Но так не было изначально. Эту фичу мы с ИИ реализовали отдельным диалогом.
Секрет «Скрытых линий»
Посмотрите, какое элегантное техническое решение применил ИИ:
- Дублирование геометрии: Создаются две копии модели.
- Depth Pass (Глубина): Первая копия рисуется невидимыми чернилами (ColorWrite: false). Она не видна глазу, но видеокарта запоминает, какие пиксели ближе к камере.
- Wireframe сверху: Сверху рисуются белые линии. Но там, где пиксель закрыт ближней геометрией (из шага 2), линия не прорисовывается.
Так мы получаем эффект инженерного чертежа, где передние линии яркие, а задние — исчезают.
Далее пример заливки всей геометрии.
Для меня этого было достаточно. Однако мысль о том, что у меня в руках есть объекты космических кораблей и ИИ инструмент, который может не просто поместить их на экран, но и возможно заставить двигаться - меня не отпускала.
Тогда то я и решил с ИИ разработать для кораблей программу автопилотирования в пространстве.
И знаете, так и получился аквариум из космических кораблей.
Алгоритм автопилота
Пожалуй это стало самой интересной частью разработки. Ведь при первом полете корабли летали боком, просто по кругу.
Я попросил условия реального космоса:
- Корабль всегда должен лететь носом вперед.
- У корабля не должно быть резких торможений и изменений курса - должна быть инерция.
- Траектории должны меняться случайным образом (без скучных орбит).
- Корабли должны уворачиваться друг от друга, а не проходить сквозь.
Вот как ИИ реализовал физику поведения:
1. Инерционная система (Smooth Velocity)
Вместо жесткой привязки к координатам, ИИ добавил velocity (вектор скорости). Корабль не телепортируется в следующую точку маршрута, а разгоняется к ней и тормозит за счет трения (multiplyScalar(0.99)). Движение стало плавным, как настоящий массивный корабль.
2. Смена маршрута "на лету" (CatmullRomCurve3)
Когда кораблю пора лететь по новой траектории, ИИ не дергает его резко. Алгоритм строит специальную сглаженную кривую (TransitionCurve), которая соединяет текущий вектор скорости с новой точкой маршрута.
3. Избегание столкновений (Evasion Offset)
Самое забавное — это анти-коллизия. Когда два корабля подлетают слишком близко, ИИ не пересчитывает всю траекторию (это дорого). В коде реализовано противоположное уклонение. То есть один корабль уходит вверх, другой — вниз относительно глобальной оси Y. При этом величина смещения случайна, но знаки строго противоположны. Это гарантирует расхождение по вертикальной оси.
Результат: Мы получили не просто анимацию, а симуляцию роя в браузере, работающую на чистой математике без тяжелых физических движков, которые ИИ мог применить, но их использование целесообразно было бы, если бы мне нужно было реализовать сталкивание кораблей друг с другом или более реальную физику.
Результатом я доволен. Накидал 3-4 корабля, включил мягкий эмбиент, а на фоне есть даже звездное поле, которое вращается и можно серьезно так залипнуть наблюдая их странный космический танец.
Идеи для развития:
Можно реализовать посадочную платформу и имитировать взлет и "выстрел" в гиперпространство с яркой вспышкой. И возвращение из гиперпрыжка с посадкой на платформу.
Заключение
Важно понять одно. Даже неудачный опыт дает опыт, и потом, при второй или тридцатой попытке ты находишь нужный ключик и получаешь желаемый результат. Поэтому важно делать попытки, включая неудачные, анализировать опыт и двигаться вперед. Иногда можно сделать паузу, переключиться на что-то другое. Понимаете, человек не стоит на месте, он развивается, меняется. Это значит, в следующий раз, когда ты попробуешь сделать то, что в прошлый раз не получилось, ты будешь делать это иначе, вероятность успеха однозначно будет выше. Главное продолжать делать. Некоторые из моих идей лежали в заметках десятилетиями и только сейчас с приходом ИИ в наш мир получают практическое воплощение. И это круто!
Я надеюсь мой опыт вас вдохновляет к собственным исследованиям возможностей ИИ, к реализации собственных идей, к открытиям и просто получению удовольствия от нового опыта.
Все приложения будут ждать вас MAX канале по ссылке: https://max.ru/join/8nUK6QBPHTrawGYW_elL1qGOxj_qeTDF4a4QCr-z5gM