Рогатка: 3D-игра с настоящей физикой в браузере, где каждый уровень проверен на проходимость ещё до игрока
Натяни, прицелься, отпусти: сбей шесть целей в комнате, где всё падает по-настоящему. 3D-игра с физикой для браузера на компьютере и телефоне, которую мы сделали целиком, - 100 уровней, каждый из которых компьютер уже прошёл.
Натяни, прицелься, отпусти: сбей шесть целей в комнате, где всё падает по-настоящему.
Браузерная игра для компьютера и телефона на русском, английском и испанском, без установки и регистрации.
Как в это играют
- Оттяни шарик и отпусти. Натяжение задаёт силу и доводит прицел, а пунктир показывает, куда полетит шарик и от чего отскочит первым.
- Оглядись на все 360°: ты стоишь посреди гостиной, кухни, детской, кабинета или спальни, а за открытыми дверями - другие комнаты, и цели бывают и там.
- Сбей шесть вещей, над которыми висят жёлтые стрелки. Одни катаются по полу на роботах-пылесосах, а в большинстве уровней одна или две стоят за стеклянной ширмой, сквозь которую прямой выстрел не пройдёт: бей в стену, чтобы шарик отскочил к цели, а то и от двух стен.
- Отзывается и всё остальное: чашки и вазы бьются, стёкла в окнах вылетают, экран телевизора трескается, люстра от сильного удара срывается с цепи, двери захлопываются, холодильник открывается, из крана течёт вода, из тостера выпрыгивают тосты, а выключатель действительно гасит свет.
- Все шесть целей за шесть выстрелов - три звезды. За монеты в магазине покупаются новые шарики и следы, а ежедневный подарок растёт с каждым днём подряд.
“Рогатка” - наш собственный продукт: та инженерия, которую мы продаём, в виде того, что понятно за секунду.
Настоящая физика в настоящей комнате
Такая игра держится на одном: падает ли всё так, как ждёт глаз. Поэтому здесь ничего не подделано: каждая книга, чашка, игрушка и стул - тело в настоящем физическом движке (Rapier, собранный в WebAssembly), который считает мир 60 раз в секунду. Для шарика включено непрерывное определение столкновений, так что даже на полной силе он не пролетит сквозь тонкую полку. Керамика и стекло разлетаются на настоящие осколки, у каждого своя физика, а чашка, сбитая со стола, разбивается об пол, но переживает падение на ковёр.
Как предмет выглядит и как он сталкивается, в коде разделено. Благодаря этому мы целиком сменили облик игры - с карандашного наброска на яркие глянцевые игрушечные комнаты с мягкими тенями и ночным режимом - и не тронули ни одного уровня: после редизайна доказательные выстрелы всех 100 уровней (о них ниже) совпали байт в байт.
Уровни от генератора, мебель - руками
Уровень - это данные, а не нарисованная сцена: размер комнаты, окна и двери, мебель и где она стоит, шесть целей. Генератор строит комнату по зерну и теме, с тем, что нужно комнате такого типа (диван или телевизор, кухонный гарнитур, кровать, письменный стол), и оставляет пол вокруг игрока свободным, чтобы ничто не загораживало вид.
Сгенерированные комнаты были только отправной точкой. Потом мы прошли по уровням и обставили их так, как обставил бы человек: мебель у стен, где ей место, полки и картины на пустых стенах, батарея под каждым окном и больше нигде. Картины на стенах - детские рисунки. То, что пропустит глаз, ловит проверка расстановки: мебель за краем стены, поверх окна, на пути двери или наполовину на ковре. Уровень можно закрепить, и тогда генератор его больше никогда не перепишет.
Каждый уровень доказан симулированным выстрелом
Хуже всего, когда головоломка требует невозможного. Поэтому ни один уровень не выходит на веру. Тот же код, что строит комнату в браузере, работает и в Node, вне браузера, с той же физикой, и проверяет каждый уровень:
- комната 2,5 секунды симуляции стоит неподвижно, а всё, что само сползает или опрокидывается, убирается;
- каждую цель видно с места игрока;
- каждую цель действительно сбивает симулированный выстрел в копии мира;
- цель за стеклом недоступна ни одному прямому броску и сбивается отскоком: проверка отражает цель в ближайших стенах и боках мебели, перебирает прицел по градусу, а потом выпускает лучшие броски по-настоящему.
Ручные правки проходят ту же проверку, так что передвинутый стеллаж не сделает цель тихо недостижимой. Нативное приложение играет те же уровни на другом физическом движке, и там, где оно не смогло сбить цель, мы заменили эту цель и в веб-уровнях - пока обе версии не прошли все 100.
Чтобы хватало браузера на телефоне
У браузерной игры есть несколько секунд на запуск, прежде чем игрок уйдёт. WebAssembly физического движка раньше был вшит в скрипт текстом; теперь он грузится отдельным файлом и компилируется прямо во время загрузки, так что скрипт, который браузер разбирает до старта, похудел примерно с 1,4 МБ до 277 КБ в сжатом виде. Первой комнате нужны только модели, которые в ней видны, - всего около 1,15 МБ, остальное догружается следом.
Неподвижная мебель комнаты рисуется несколькими объединёнными мешами, и в комнате 50-го уровня вызовов отрисовки стало 619 вместо 1120. На компьютере, изображающем телефон с процессором в шесть раз медленнее, 100-й уровень вырос примерно с 49 кадров в секунду до ровных 60. Кроме того, игра подстраивается сама: меряет собственное время кадра и на устройстве, которое не успевает, ступенями снижает разрешение и тени. На настоящих телефонах веб-версию мы пока не измеряли.
Законченная игра, готовая к порталам и магазинам
Вокруг ядра есть всё, чтобы в игру играли, а не просто смотрели: рука-подсказка, которая без слов учит натягивать и оглядываться, звёзды, список уровней, монеты, магазин из 12 шариков и 6 следов, ежедневный подарок, музыка и звуки, дневная и ночная темы. Один переключатель сборки добавляет SDK игрового портала Poki: рекламные паузы в естественных перерывах и необязательный ролик за удвоение монет, по правилам портала.
Нативная версия для Android на Unity собрана и играет те же 100 уровней из тех же файлов. На Samsung Galaxy S23 измеренные уровни держат 60 кадров в секунду, самый тяжёлый - 54–55, а страница в магазине, графика и анкеты о данных подготовлены.
Что это значит для вашего проекта
- Мы делаем интерактивное 3D для браузера: конфигураторы товаров, планировщики комнат и шоурумы, где вещи ведут себя как настоящие. Всё это быстро загружается и работает на обычных устройствах, и мы это проверяем.
- Когда система порождает много контента - планировки, расчёты, расписания или уровни, - мы строим автоматическую проверку, которая доказывает, что каждая единица работает, до того как её увидит клиент. Так контенту можно доверять и в больших масштабах.
- Один продукт может быть и сайтом, и приложением: браузер и телефон делят данные и правила, так что изменение, сделанное один раз, попадает в обе версии и проверяется в обеих.
Статус
“Рогатка” готова и играбельна, но пока не публична: веб-версия не выложена ни на сайте, ни на портале, а приложение для Android подготовлено к магазину, но не опубликовано.
Технологии
- Клиент: TypeScript + Vite, Three.js (WebGL), мягкие тени, дневное и ночное освещение
- Физика: Rapier (Rust, собранный в WebAssembly), фиксированный шаг 60 Гц, бьющиеся предметы
- Уровни: генератор по зерну и теме комнаты, затем ручная расстановка; файл данных на уровень
- Проверка уровней: тот же код комнаты и физики в Node, симулированные выстрелы и рикошеты
- Производительность: объединённые неподвижные меши, адаптивное качество по замерам кадров
- Мета-игра: монеты, магазин, ежедневный подарок, прогресс в локальном хранилище
- Сборка для портала: SDK Poki за переключателем сборки
- Нативное приложение: Unity 6, C#, PhysX, те же файлы уровней
- Языки: русский, английский, испанскийРезультат
3D-игра с физикой, которая открывается в браузере, где полка с книгами рушится ровно так, как ждёшь, и где каждый из 100 уровней уже пройден компьютером до того, как его увидит игрок.




