Егор Урванов

Архитектура игры «Березовка»: C4 и критические пути

Окружение, схемы C4 до компонентов и четыре критических пути: запуск, кадр, шаг сюжета и подстройка под слабую машину.

Берёзовка — заснеженная деревня в браузере: открытый мир около километра, сюжет, «Жигули», рыбалка. Без сервера и без сборки: одна страница и пять модулей. Ниже: окружение, схемы C4 до компонентов и четыре пути, на которых всё держится.

C4: контекст и контейнеры

Уровень 1. Система и её окружение

Игрокклавиатура, мышь, касание«Берёзовка»игра в браузереCDN jsDelivrthree.jsGoogle Fontsшрифтыиграетгрузит библиотекугрузит шрифты
Своего сервера у игры нет: всё работает из статических файлов, прогресс лежит в браузере.

Уровень 2. Контейнеры

Страницаindex.htmlцикл, сюжет, мирМодулиsrc/*.jsсвет, движение, лесПакеты и текстурыassets/модели, небо, звукиСохранениеlocalStorageCDNthree.jsвызываетзагрузкапрогрессimportimport
Страница владеет циклом и состоянием; модули получают всё нужное через переданный объект ctx и своих глобальных данных не заводят.

C4 уровня 3: компоненты

Показаны контейнеры, где есть что разбирать: страница и четыре модуля плюс загрузка ассетов. Звук (sound.js) устроен просто: makeSound(env) получает снимок состояния игры и сам решает, что играть.

Страница

Циклloop(now)Игрок и машинаввод, шагСтолкновениясетка коробок и круговСюжет13 этапов, диалогиМир и жителиNPC, звери, погодаИнтерфейсHUD, карта, компасСохранениеberezovka_v1РендерпостобработкаupdateпозицияupdateHUDпредметы, речьэтапrender
Сюжет задаёт номер этапа; от него зависит, какие предметы видны и куда указывает стрелка задания.
  • Цикл ограничивает шаг по времени 0,05 с, чтобы после паузы ничего не «прыгнуло».
  • Сохранение пишется при смене этапа и каждые 15 секунд.

Свет и вид

НебоbuildSkyтри панорамыСмена сутокupdateсолнце, туман, сияниеСнег на моделяхsnowifyЗатенение угловaddAO / setAOМатериалыдорога, горы, облакаПроверка видаgateединый источник
Небо, окружающий свет и туман берутся из одних и тех же панорам, поэтому все модели стоят в одном свете.
  • Днём и в пасмурь это панорамы Poly Haven, ночью своя картинка.
  • Затенение углов само выключается, если средний кадр дольше 33 мс.

Движение

ЧеловекhumanStepМашинаcarStep, suspStepПоходкаcalibrate, gaitPlayУдарcarImpactЧетвероногиеmakeQuad, updateQuadПроверкиsimHuman, simCarскоростьтемп шага
Чистая логика не зависит от three.js: человека и машину можно прогнать в тесте без экрана.
  • Скорость растёт с конечным ускорением, поворот идёт дугой.
  • Темп шага считается как скорость, делённая на длину шага клипа: ноги не скользят.
  • Машина: четыре пружины, крен, лёд, ручник; разгон 0–100 за около 18 с.

Расстановка и масштаб

Планplanповороты домов, зоныДеревня и посёлокbuildVillage, buildTownЛесforestField, placeForestРеальные размерыREAL, fitRealПосадка на землюgroundFitПлитки и отсечениеtiled, cullTilesдворызонымодельдальний лес
Все расстановки считаются от одного зерна случайных чисел: мир каждый раз получается одинаковым.
  • Дом разворачивается к ближайшей дороге, двор получает забор и колею.
  • Размер модели сверяется с реальным: если выходит из допустимой полосы, ставится целевой.
  • Дальний лес режется на плитки и скрывается целиком, пока игрок далеко.

Загрузка ассетов

ЗагрузчикloadModels, loadPackПакеты моделейGLB в base64Текстурынебо, снег, скалаЗвукиassets/sfxПлитки загрузкичто готовоmodel()клон из кэшаскрипт, разборотдельно
Модели лежат в .js-файлах как текст: так игра грузится с любого статического хостинга.
  • Загрузчик показывает группы ресурсов и помечает ту, где что-то не загрузилось.
  • Звуки подгружаются отдельно, пока файла нет, играет синтез.

Четыре критических пути

1. Запуск игры

ИгрокСтраницаCDNЗагрузчикМодулиоткрываетthree.jsбиблиотекапакеты, текстурыготовоbuildWorld, motionSetupмир собранрендер-цепочкаменю«Новая игра»
Меню появляется, только когда загружено и собрано всё; кнопка «Продолжить» видна, если есть сохранение.

2. Один кадр

ЦиклСветДвижениеСтолкн.МирРендерupdateEnvшаг человека или машиныновая позициявытолкнутожители, погода, лескамера, HUD, звукrender
Если игра в меню, цикл только крутит камеру вокруг деревни; в загрузке ничего не делает.

3. Шаг сюжета

ИгрокСтраницаСюжетДиалогСохранениеE у герояtalk(id)реплики по этапупечатает, ждёт выборответконец репликsetStage(n)save()новая цель
Игра ведёт игрока по цепочке из 13 этапов; финал запускается колоколом на 12-м.

4. Слабая машина

СтраницаСветРендерЗатенениесенсорный экран?без постобработкикадркопит время кадров 4 ссреднее больше 33 мс: выкл.кадр без затенения
Игра снижает качество сама: на сенсорных экранах без постобработки, на медленных видеокартах без затенения углов.

Правила, на которых всё держится

  • Один источник света. Небо, окружение и туман берутся из одних панорам.
  • Модуль не заводит глобальных данных. Всё приходит через ctx из страницы.
  • Чистая логика отдельно от экрана. Движение проверяется без three.js.
  • Каждое измеримое свойство имеет проверку. Игра печатает в консоль строки GATE … OK или FAIL: размеры зданий, скорость шага, скольжение ног, разгон машины, яркость кадра.
  • Мир детерминирован. Расстановка идёт от фиксированного зерна.

Слабые места

Где Что не так
Страница-монолит Цикл, сюжет, столкновения, интерфейс и сборка мира лежат в одном файле на полторы тысячи строк.
Сюжет в коде Реплики и этапы зашиты в функции talk; новую главу не добавить без правки страницы.
Вес загрузки Около 33 МБ при первом запуске: модели в base64 и библиотека с внешнего CDN.
Нет сервера Сохранение живёт только в одном браузере и пропадает при очистке данных сайта.
Телефоны Есть джойстик, но игра рассчитана на компьютер; на сенсорных экранах нет постобработки.

Об игре

Страница игрыБерезовкаЗаснеженная русская деревня, в которую можно зайти — 3D-игра с открытым миром в браузере
© 2026 Егор Урванов