Егор Урванов

Архитектура игры «Сибирь»: C4 и критические пути

Схемы C4 до уровня компонентов и четыре критических пути через sequence: кадр, ночная угроза, шаг сюжета и сохранение.

«Сибирь» — игра на выживание в тайге, вид сверху, прямо в браузере: без движка, без сборки, около пятидесяти скриптов на холсте 2D. Здесь описано, как она устроена: схемы C4 до уровня компонентов и четыре пути, на которых всё держится.

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

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

Игрокмышь, клавиатура, тач«Сибирь»игра в браузереGoogle Fontsшрифты интерфейсаБраузерlocalStorageиграетгрузит шрифтысохранения
Своего сервера у игры нет: подойдёт любой статический хостинг. Без шрифтов игра работает, меняется только гарнитура.

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

index.htmlхолст, HUD, стилиЯдро и данныеcore, data, content/*Системымодули js/*.jsКартинкаgfx, art-*, particlesЗвукaudio.js, Web AudioИнтерфейс и циклui, input, mapХранилищеlocalStorageгрузит скриптычисла, сюжетupdate(dt)renderSound.frameсейв
Цикл живёт в интерфейсе и по очереди зовёт системы, рендер и звук. Все скрипты грузятся по порядку тегами в index.html.

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

Показаны пять контекстов, где решается игра. Сохранение разобрано ниже как критический путь.

Мир

ГенерацияWorld.gen(seed)Зоны8 зон, свои правилаГлубина снегаdepth.jsЛёдпровал у перекатаВетерwind.jsСнег на вещахsnow.jsЖивые вещилопасть, дверь, проводаОткликиinteract.jsкарта зонповерхностьрекасдув, наддувкачаетшапкисобытия
Мир строится из числа seed: лес, зоны и сугробы пересчитываются, а не хранятся.
  • Зоны (наледь, гарь, курумник, голец и другие) меняют правила: холод, шаг, опасности.
  • Отклики вещей описаны таблицей «событие + свойства вещи → реакция», а не парами «кто с чем».

Герой, выживание и угрозы

Время и погодаtime.jsГеройдвижение, навыкиДействияE, F, крафт, сонВыживаниетепло, голод, здоровьеОгонь и печьfire.jsДиректор угрознапряжение, бюджетВолкиразведчик, стаяШатунbear.jsЖивностьзайцы, олениморозодеждажестыдроватеплосостояние героявызываетночь
Тепло падает от мороза и ветра, растёт у огня и печи; директор следит за состоянием героя и решает, когда прийти волкам.
  • Директор угроз устроен как в Left 4 Dead: напряжение → бюджет → предвестник (вой, следы) → разведчик или стая.
  • Пурга прогоняет стаю, а при низком здоровье директор берёт паузу.

Посёлок и люди

Данныеcontent/npcs, people, questsПерсонажиnpc.jsЗаданияquests.jsРазговорtalk.jsПосёлоклюди, стройка, эпохиРеплики мираbarks.jsВводприказы ПКМСводка Ctxcontext.jsзаписизаписиговоритузлы диалогаприказчто вокруг
Новый персонаж или задание добавляются записью в данные, исполнители не меняются.
  • Люди посёлка работают по циклу «добыть → склад → снова», стройка даёт убывающую отдачу строителей.
  • Четыре эпохи, восемь видов построек, торговля за рубли с плавающим курсом.

Сюжет

Событияcontent/events.jsГлавыchapterTickОперацииOPS, Story.runВертолётheliTickДиалоги, карточкиUI.dialogЧекпоинтSaveGameФиналfinale.jsКомпасgoalTargetкаждый шагwhen → doкаждый шагпоказатьновая главаспасеныцель
Сюжет лежит данными, а Story только исполняет: «когда выполнится условие — сделать операции».
  • Семь глав, пять концовок: ветка выбирается тем, придёт ли вертолёт и готов ли посёлок.
  • Вход в главу сам делает автосохранение.

Картинка, звук и интерфейс

Вводinput.jsКартаmap.jsИнтерфейс и циклui.jsКачествоавто-упрощениеРендерgfx.jsЗвукaudio.jsСпрайтыart-*.jsЧастицы, погодаparticles.jsнамерениеоткрытьrenderfpsSound.frameрисуетслои
Весь ввод проходит через один автомат, а картинка собирается слоями с одним светом и одним солнцем.
  • Звук целиком синтезируется в Web Audio, файлов нет; музыка следует за опасностью.
  • Если кадры дольше 28 мс или реже 30 в секунду два окна подряд, графика упрощается.

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

1. Один кадр

БраузерЦиклupdateРендерЗвукКачествоrequestAnimationFramedt ≤ 0.05 сupdate(dt)время, герой, огонь, выживание, угрозы, люди, посёлокмир обновлёнGFX.renderSound.framesample(fps)панель или диалог: только visual
Во сне update идёт четыре раза за кадр, при открытой панели мир стоит и только «дышит».

2. Ночная угроза

ВыживаниеДиректорЗвук, тостыВолкиОгоньтепло, голод, здоровьенапряжение → бюджетвой и следы (предвестник)spawnPack / spawnScoutзащита огнявыпад: здоровьепурга, рассвет или бегство: стая уходит
Сначала предупреждение, потом нападение: игрок успевает дойти до огня.

3. Шаг сюжета

Story.tickСобытияОперацииИнтерфейсГлавыSaveGamewhen(G, c)условие верноrun(do)флаги, предметыдиалог, тостchapterTickвсе цели закрыты?карточка главыcheckpoint()
Событие срабатывает один раз по сохранённому флагу; глава меняется, когда закрыты все её цели.

4. Сохранение и загрузка

ИгрокИгра, UISaveGameSavesМирсон в избе, новая главаcheckpoint()snapshot: seed + измененияwrite("auto")localStorage«Продолжить»load(json)gen(seed)изменения применены
В сохранение попадает только то, что изменилось: лес, зоны и сугробы пересчитываются из seed.

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

  • Одно состояние G. Системы читают и пишут в него, сохранение это G плюс seed.
  • Мир считается из seed. Лес, зоны и сугробы не хранятся.
  • Сюжет это данные. Главы, события, задания и люди лежат в content/, исполнители про них ничего не знают.
  • Один порядок шага. update зовёт системы в фиксированном порядке.
  • Одна сводка Ctx. Реплики, звук и свет берут «что вокруг героя» оттуда.

Слабые места

Где Что не так
Порядок скриптов Около 55 тегов в index.html, порядок важен и нигде не проверяется.
Глобальные модули Модули зовут друг друга по именам, границ между контекстами в коде нет.
Большой G Одно изменяемое состояние на всё: любая система может сломать чужое поле.
ui.js В одном файле на тысячу строк HUD, диалоги, карта, цикл кадра и сохранения.
Старые сейвы Сейвы до версии 4 не читаются: мир другой.

Об игре

Страница игрыСибирьЧетыре ночи в эвенкийской тайге, 1993 год — выживание и постройка поселения
© 2026 Егор Урванов