Форматы изображений и спрайтов
FOnline запекает авторские и устаревшие изображения в компактный клиентский
контейнер спрайта. Baker импортирует статические RGBA-источники, устаревшие
индексированные форматы, анимации, наборы направлений и текстовые композиции
.fofrm. Он также может заменить обычный полноразмерный quad проверенным
индексированным силуэтом и обрезать сериализованный RGBA-холст по этой геометрии.
В runtime штатный клиент читает версионированный контейнер, размещает конкретные
кадры в атласе текстур и создаёт AtlasSprite либо SpriteSheet.
Используйте это руководство для решений по авторингу и рабочему поведению. Точный контракт текущей ревизии находится в сгенерированном справочнике image-format, его страницах исходных форматов, FOFRM, параметров имени файла, запекания, runtime и проверки, а также в канонической JSON-модели.
Область действия и источник истины
Поведение принадлежит следующим исходникам:
Source/Tools/ImageBaker.cppиImageBaker.h: обнаружение источников, декодирование форматов, композиция FOFRM, имена выходов,SpriteInfoкаждого пакета, интеграция mesh и сериализация;Source/Tools/SpriteMeshing.cppиSpriteMeshing.h: построение маски, генерация и оценка кандидатов, триангуляция и проверка покрытия;Source/Common/SpriteResource.cppиSpriteResource.h: общий версионированный декодер, записи кадров/mesh и формат индексаSpriteInfo;Source/Client/DefaultSprites.cppиDefaultSprites.h: загрузка запечённого контейнера,AtlasSprite,SpriteSheet, смещения кадров и загрузка в атлас;Source/Client/SpriteManager.cpp: диспетчеризация по расширению и кэши спрайтов;Source/Client/TextureAtlas.cpp: выделение места в атласе;Source/Tests/Test_ImageBaker.cppиTest_TextureAtlas.cpp: исполняемые примеры импорта, отказов и выделения памяти.
BuildTools/ImageFormatInterface.json является структурированным контрактом,
подтверждённым исходниками. BuildTools/docs_image_format.py проверяет каждый
объявленный source anchor, выводит актуальные списки расширений baker и runtime,
подтверждает, что устаревшее поле FOFRM Effect по-прежнему отсутствует в
сериализованном результате, и строит сгенерированный справочник. Изменение
импортера, descriptor, контейнера, factory, atlas или cache должно обновлять эту
модель в той же правке.
Эта страница описывает переиспользуемый Engine. Встраиваемый проект владеет своим каталогом ресурсов, лицензиями, приоритетом resource pack, политикой исходных файлов, визуальным стилем, подстановками анимаций, ожиданиями hit-test, настройкой движения и эталонами визуальной приёмки.
Выбор исходного формата
| Задача | Предпочтительный источник | Примечания |
|---|---|---|
| Обычное статическое изображение или прозрачный спрайт | PNG | Рекомендуемый lossless-вход для авторских ресурсов проекта. Палитра, grayscale малой разрядности, tRNS и 16-битные каналы нормализуются в RGBA8. |
| Существующий выход TrueColor-конвейера | TGA | Используйте поддерживаемое подмножество: type 2/type 10, 24/32 bpp, без image ID, начало координат снизу слева. |
| Многокадровый или направленный спрайт проекта | FOFRM со ссылками на PNG/TGA | Композиция, смещения, дельты кадров и timing остаются явными и удобными для ревью. |
| Существующий ресурс Fallout FRM/FR0 | FRM или FR0 | Сохраняйте только когда проект может распространять источник и имеет маршрут визуальной регрессии. |
| Существующий ресурс Tactics ART/SPR | FOFRM со ссылками на ART/SPR | Параметры имени выбирают палитры, кадры, отражения, цвета и последовательности. SPR обычно следует оборачивать из-за границы штатного runtime. |
| Существующий ресурс Infinity Engine | ZAR/TIL/MOS/BAM, обычно через FOFRM, если нужен выбор | Считайте это путём импорта, а не рекомендуемым форматом для новой графики. |
Встроенный image baker не поддерживает JPEG, BMP, GIF, DDS, WebP, AVIF и SVG.
Перед запеканием преобразуйте такие входы в PNG или поддерживаемое подмножество
TGA. Не делайте вывод о поддержке по renderer или сторонней библиотеке, которая
случайно умеет читать формат: контракт определяют ImageBaker и выбранная
runtime-реализация SpriteFactory.
Обзор конвейера
Обычный путь выглядит так:
- Resource pack публикуют исходные файлы через
FileCollection. ImageBakerсканирует зарегистрированные расширения или получает один целевой путь.- Выбранный loader возвращает
FrameCollectionс единым числом кадров/timing и одной последовательностью либо полным набором направлений. BakeCollectionпри необходимости строит и оценивает silhouette mesh для каждого уникального кадра, добавляет поля или обрезает RGBA-холст и определяет его логический корень.- Он записывает частный контейнер RGBA/mesh-кадров по исходному пути либо под
заданным loader
NewNameи поддерживаетSpriteInfo/<PackName>.foinfo. - В клиентском runtime
SpriteManagerвыбирает factory по приведённому к нижнему регистру расширению, аDefaultSpriteFactoryчитает запечённые байты. - Конкретные кадры попадают в запрошенный texture atlas; при необходимости
metadata анимации/направлений становится
SpriteSheet.
Исходные декодеры не исполняются в штатном клиенте. Файл Sprite.png в
запечённом resource pack содержит контейнер спрайта Engine, а не исходные байты
PNG. Сохранённое расширение является идентификатором диспетчеризации, а не
обещанием формата запечённой нагрузки.
Грамматика FOFRM
FOFRM использует parser Engine ConfigFile. Корневой/default-раздел описывает
однонаправленную последовательность. Направленные sheets используют разделы
[dir_N] или [Dir_N].
Минимальное статическое изображение
count = 1
fps = 10
frm = Icon.png
Ненумерованный alias frm/Frm допускается только для ссылки с номером ноль.
Нумерованные ключи яснее и масштабируются на анимации:
fps = 8
count = 3
frm_0 = Idle_00.png
frm_1 = Idle_01.png
frm_2 = Idle_02.png
Ссылки разрешаются относительно каталога .fofrm. Храните связанные исходные
кадры рядом с descriptor или в стабильном относительном поддереве; не полагайтесь
на текущий каталог машины разработчика.
Размещение последовательности и дельты кадров
Корень или каждое направление может задавать знаковые смещения размещения в одном из двух стилей имён:
offs_x = -24
offs_y = -63
или:
OffsetX = -24
OffsetY = -63
Если смещения направления пропущены, они наследуют значения, действовавшие при разборе предыдущего направления. Это бывает полезно для legacy-данных, но легко читается неверно. Production descriptor направлений должен явно записывать оба смещения в каждом разделе направления.
Дельты каждой ссылки используют next_x_N / next_y_N либо NextX_N /
NextY_N:
next_x_0 = 2
next_y_0 = -1
Дельта descriptor прибавляется к собственным NextX и NextY каждого
импортированного дочернего кадра. Это не обычные смещения размещения изображения.
Многокадровые runtime sheets сохраняют их как смещение каждого кадра,
используемое специализированным presentation-кодом. Подробная проекция ходьбы/
бега и граница authoritative movement описаны в
Sprite Root Motion.
Наборы направлений
Направленный descriptor должен содержать либо одну последовательность, либо все
направления от нуля до GameSettings::MAP_DIR_COUNT - 1:
fps = 10
count = 2
[dir_0]
offs_x = -24
offs_y = -63
frm_0 = Walk_NE_00.png
frm_1 = Walk_NE_01.png
[dir_1]
offs_x = -24
offs_y = -63
frm_0 = Walk_E_00.png
frm_1 = Walk_E_01.png
# Continue every configured map direction.
Каждое направление должно после flattening давать одинаковое итоговое число кадров. Неполный набор направлений, отсутствующий последующий раздел или иное число расплющенных кадров приводят к ошибке запекания.
Вложенные ссылки и flattening
Каждый frm_N может ссылаться на любое зарегистрированное расширение image
loader и содержать параметры имени после $. Если дочерний ресурс имеет
несколько кадров, FOFRM добавляет его последовательность Main в родителя. Он
не компонует наборы направлений ребёнка и его OffsX/OffsY уровня
последовательности. Вложенный дочерний кадр, уже являющийся shared record,
отклоняется, потому что его индекс не перенумеровывается при flattening.
Различие между числом ссылок descriptor и расплющенным числом кадров существенно:
fps = 10
count = 2
frm_0 = FirstCycle.bam
frm_1 = SecondCycle.bam
FOFRM вычисляет полную длительность как 1000 * count / fps, а runtime делит
эту длительность на расплющенное число кадров. Если каждая ссылка BAM добавляет
несколько кадров, воспроизведение будет быстрее ожидаемого. Для предсказуемого
темпа ссылайтесь на один статический кадр в каждом слоте descriptor либо
рассчитывайте timing по фактическому итоговому числу и проверяйте его в видимом
клиенте.
fps = 0 создаёт нулевое полное число ticks и намеренно отключает обычное
воспроизведение. Для проигрываемого многокадрового sheet целочисленное
AnimTicks / frame_count должно быть не меньше одной миллисекунды: runtime loop
делит на это значение.
Устаревший ключ Effect
Parser принимает effect и Effect в FrameCollection::EffectName, но baker
не сериализует и не применяет его, а штатный runtime не выбирает по нему shader.
Считайте ключ игнорируемым compatibility-входом. Выбирайте эффекты проекта через
принадлежащую renderer, prototype, GUI или script поверхность, описанную в
Effect Format.
Устаревшие параметры имени файла
Параметры располагаются после $ и перед расширением. LoadAny удаляет их из
физического пути поиска и передаёт выбранному loader.
ART
Actor$1THF5-7.art
0-3выбирают палитру; действует последний selector, а недоступная палитра заменяется нулевой.Tвыводит alpha из максимального компонента RGB; индекс палитры ноль остаётся полностью прозрачным.HиVотражают изображение по горизонтали и вертикали.F5выбирает кадр 5;F5-7иF7-5выбирают включительные возрастающий и убывающий диапазоны. Границы ограничиваются доступной таблицей кадров.- Регистр букв параметров не важен. Неизвестные символы игнорируются.
Флаг static в ART принудительно оставляет одну rotation. Вход с восемью rotation переназначается под текущую геометрию карты и становится полным набором направлений Engine.
SPR
Actor$[1,12,0,0][2,0,-8,4]Walk.spr
Parts: 0 — other, 1 — skin, 2 — hair, 3 — armor. Смещения RGB
прибавляются и ограничиваются диапазоном 0..255. Значение part вне диапазона
применяет RGB ко всем частям. Текст после последней скобки выбирает
последовательность без учёта регистра; пустое имя выбирает первую.
SPR импортирует слоёные пиксели, удаляет недопустимые индексы кадров
последовательности и создаёт shared records для повторяющихся индексов. Темп
фиксирован на 10 fps. Штатная DefaultSpriteFactory не регистрирует .spr,
хотя ImageBaker умеет его запекать. Обычно ссылайтесь на SPR из .fofrm, чтобы
скомпонованный запечённый выход имел зарегистрированное расширение .fofrm.
Прямые runtime-пути .spr требуют явной пользовательской sprite factory.
BAM
Spell$1.bam
Spell$1-3.bam
Первое целое выбирает cycle. Необязательное целое после - выбирает один кадр.
Значения cycle или frame вне диапазона заменяются нулём. Без selector кадра
импортируется весь cycle. Отрицательные значения выбранного кадра трактуются
как форма всего cycle.
Подробности исходных форматов
PNG
PNG рекомендуется по умолчанию для авторских изображений проекта. Loader:
- сокращает 16-битные каналы до 8 бит;
- расширяет grayscale малой разрядности и palette pixels;
- раскрывает прозрачность
tRNS; - заполняет отсутствующий alpha значением 255;
- создаёт один кадр RGBA8.
Повреждённый вход завершается через callback ошибок libpng. Явно определяйте в проекте политику color space и premultiplication: ImageBaker не предоставляет проектный workflow управления цветом.
TGA
Поддерживаемое production-подмножество намеренно узкое:
- TrueColor type 2 (raw) или type 10 (RLE);
- 24-битные BGR или 32-битные BGRA pixels;
- без image ID;
- origin снизу слева, поскольку реализация всегда переворачивает строки.
Indexed, grayscale и другая разрядность завершаются ошибкой. Loader не учитывает бит origin descriptor и не пропускает image ID, поэтому top-origin или ID-bearing файлы могут дать неверный либо отклонённый результат. Предпочитайте PNG, если существующий toolchain не имеет проверенного TGA preset.
Fallout FRM и FR0
FRM читает big-endian frame rate/count, смещения последовательности, дельты
кадров и одну либо полную таблицу направлений. Файл .pal с тем же базовым
именем переопределяет встроенную палитру Fallout. При стандартной палитре
анимированные индексы палитры могут развернуть один источник в сгенерированный
цветовой cycle; проверяйте итоговое число кадров и темп.
FR0 является точкой входа для разделённых соседних fr0, fr1 и последующих
направлений. После начала нескольких направлений отсутствие следующего файла
является ошибкой. Пути critter нормализуются в lowercase .fofrm, другие
разделённые наборы — в .frm.
RIX, ZAR, TIL, MOS и BAM
- RIX создаёт один непрозрачный кадр со встроенной палитрой.
- ZAR создаёт один raw/RLE кадр с палитрой и alpha.
- TIL импортирует вложенные кадры ZAR как последовательность 10 fps.
- MOS/MOSC импортирует одно tiled-изображение, предварительно распаковывая MOSC;
зелёный
0x00FF00в палитре прозрачен. - BAM/BAMC импортирует выбранный cycle/frame, распаковывает BAMC, поддерживает RLE, выводит дельты кадров и считает синий 255 в палитре прозрачным.
Это compatibility-импортеры. Не выбирайте их для новой графики проекта, если PNG и FOFRM выражают тот же авторский замысел яснее.
Граница запечённого контейнера
Запечённый поток байтов — частное соглашение между ImageBaker и
DefaultSpriteFactory, а не публичный формат сериализации проекта.
Концептуально он содержит:
SPRITE_RESOURCE_MAGIC(43) иSPRITE_RESOURCE_VERSION(2);- little-endian
uint16числа кадров и полных animation ticks; uint8числа направлений (1либоGameSettings::MAP_DIR_COUNT);- shared flag каждого кадра каждого направления;
- для конкретного кадра — знаковый
int16draw offset,uint16обрезанных width/height, знаковыеint16NextX/NextYи ровноwidth * height * 4байта RGBA; SpriteMeshKind; mesh record дополнительно хранит числа vertices/indices, логический размер источника и origin обрезки, локальные вершины фиксированной ширины и индексы треугольников;- для shared frame —
uint16индекса более раннего кадра; - завершающий
SPRITE_RESOURCE_MAGIC.
Не разбирайте и не создавайте этот поток в скриптах проекта или внешних content tools. Передавайте поддерживаемые исходники закреплённому baker Engine. Изменение layout контейнера может координироваться внутри одной ревизии Engine без сохранения межревизионной совместимости байтов.
Runtime-загрузка, atlas и caches
SpriteManager приводит расширение пути к нижнему регистру и выбирает
зарегистрированную SpriteFactory. Стандартная factory передаёт полный диапазон
байтов в ReadSpriteResource, который проверяет magic, version, records, mesh
geometry, footer и trailing data. Затем factory проверяет инвариант одного или
полного набора направлений.
Ресурс с одним кадром и одним направлением становится AtlasSprite. Его
OffsX/OffsY последовательности становится смещением размещения спрайта;
сериализованные NextX/NextY читаются, но игнорируются. Многокадровый или
направленный ресурс становится SpriteSheet. Каждое направление владеет
параллельным sheet, а каждый concrete/shared кадр сохраняет отдельное смещение в
_sprOffset.
SpriteSheet умеет выбирать направление, рандомизировать начальный кадр через
Prewarm, задавать нормализованное время и проигрывать с loop или reverse.
Play ничего не делает при одном кадре или нулевых полных ticks. Смена
направления сама по себе не переписывает общие animation clock.
Конкретные RGBA-кадры размещаются в запрошенном AtlasType. Factory требует
положительные размеры, загружает изображение, дублирует однопиксельные края для
linear filtering и создаёт hit mask из alpha через Settings.SpriteHitValue.
Тип атласа также входит в ключ cache копируемых спрайтов, поэтому один путь
может иметь отдельные экземпляры interface/map/one-image.
При SpriteMesh.Enabled ImageBaker считает alpha > AlphaThreshold видимой
маской, ищет кандидаты до MaxTriangles и через AreaSavingsWeight оценивает
сэкономленную площадь исходного кадра относительно отправляемых треугольников.
Каждый выбранный mesh должен покрывать все видимые pixel cells. Недопустимые или
невыгодные кандидаты сохраняют обычный quad; пустая маска записывает явную пустую
геометрию. Mesh frames могут использовать обрезанный или немного дополненный
texture canvas, но их сериализованные offset, логический размер источника и
source origin сохраняют размещение, scaling, интерполяцию map light и координаты
hit-test.
Baker проверяет всю группу SpriteMesh.*, даже когда генерация mesh отключена.
Поэтому standalone-конфиги проекта должны объявлять положительный
MaxTriangles, AlphaThreshold в 0..254 и конечный неотрицательный
AreaSavingsWeight; конфиг минимального проекта
показывает явные стандартные значения для отключённого режима.
Обычные полноразмерные draw спрайта отправляют запечённый индексированный список треугольников. Region crops, tiled patterns, padded custom-effect/outline draws, fonts, blits, runtime model sprites и particles продолжают использовать прямоугольные пути. Точное поведение draw и dump атласа описано в Frontend и рендеринг, а политика кандидатов и поля baking report — в Baking Pipeline.
SpriteInfo/<PackName>.foinfo версии 1 — компактный индекс каждого pack с
duration, directions, границами кадров, offsets и shared references. Общий
EngineMetadata загружает его на server и client без декодирования RGBA payload.
Появление или потеря этого агрегированного индекса требует полной перезапечки.
Copyable cache entries хранят prototype и возвращают MakeCopy(), чтобы
вызывающие стороны не разделяли animation state. Отсутствующие файлы/расширения,
неизвестные factories и ошибки загрузки отдельно мемоизируются по пути в
_nonFoundSprites. CleanupSpriteCache() не очищает этот набор. После
добавления ресурса, который запущенный клиент уже не смог загрузить, пересоздайте
sprite manager или перезапустите клиент перед проверкой того же пути.
Практики авторинга
Для нового игрового контента:
- Предпочитайте PNG для пикселей и FOFRM для композиции анимаций/направлений.
- Используйте lowercase-расширения и стабильные пути с правильным регистром, хотя само расширение при диспетчеризации приводится к нижнему регистру.
- Храните одну семантическую анимацию в одном descriptor. Избегайте глубоко вложенных анимированных ссылок: count, flattening и timing сложнее ревьюить.
- Явно записывайте
fps,count, каждыйfrm_Nи оба offset. В направленном файле записывайте offsets в каждом направлении. - Делайте все разделы направлений полными, а числа кадров — симметричными.
- Считайте
NextX/NextYpresentation-данными. Проверяйте root motion визуально и не используйте его как authoritative movement/collision state. - Оборачивайте SPR-импорт в FOFRM, если проект намеренно не владеет custom factory.
- Преобразуйте неподдерживаемый или неоднозначный TGA export в PNG.
- Храните оригинальные legacy assets и custom palettes только когда лицензия разрешает распространение; документируйте provenance во встраиваемом проекте.
- В видимом клиенте проверяйте размеры, прозрачные поля, atlas filtering, click/hit masks, отображение направлений, темп и stop/start behavior.
- После изменения
SpriteMesh.*, кода контейнера или mesh policy запускайтеForceBakeResources: timestamps источников не доказывают, что существующие выходы использовали те же settings. Перед приёмкой изменений triangle cost, padding, crop или fallback изучайтеBakingReport.jsonиGame.DumpAtlases().
AI-автору следует предпочитать явные ключи FOFRM и ссылки на однокадровые PNG. Перед изменением существующей строки legacy-параметров изучите сгенерированный справочник options и focused native fixtures, а не угадывайте поведение по имени файла.
Диагностика
| Симптом | Вероятная граница | Первые проверки |
|---|---|---|
| Targeted bake ничего не записывает и не сообщает ошибку | Неподдерживаемая/отсутствующая цель или пропуск BakeChecker |
Проверьте расширение, source pack, регистр пути, timestamp/cache policy и видит ли файл полный scan. |
Image file not found |
Относительная ссылка FOFRM | Разрешите путь от каталога descriptor и удалите $... перед проверкой физического пути. |
FOFRM file invalid data |
Отсутствующий slot, неравные направления, пустой child или неполный набор направлений | Сравните count, каждый frm_N, все разделы направлений и итоговые числа дочерних кадров. |
FOFRM file invalid data (shared index) |
Вложенный child уже использует shared records | Выполните flattening из конкретных источников либо уберите слой вложенной анимации. |
Прямой путь .spr сообщает неизвестное расширение |
Граница штатной runtime factory | Загружайте запечённую .fofrm-обёртку либо регистрируйте принадлежащую проекту custom factory. |
| Спрайт остаётся отсутствующим после добавления файла | Мемоизация _nonFoundSprites |
Перезапустите/пересоздайте sprite manager клиента и подтвердите наличие запечённого выхода. |
| Анимация не проигрывается | Один кадр, нулевые ticks или недопустимый эффективный темп | Проверьте итоговое число кадров и AnimTicks; вычислите целые ticks на кадр. |
| При смене направления неверное framing | Унаследованные/пропущенные offsets или remap исходных направлений | Сделайте offsets явными в каждом разделе и визуально проверьте все направления. |
| TGA перевёрнут или смещён | Неподдерживаемые допущения origin/image ID | Экспортируйте с поддерживаемым preset либо преобразуйте в PNG. |
| Alpha fringe или неверная hit area | Source alpha, граница атласа или SpriteHitValue |
Проверьте raw alpha и итоговый atlas-backed sprite в нужном client profile. |
Во время scan независимые ошибки изображений журналируются как
Image baking error, а после завершения всей выбранной работы baker выбрасывает
одно агрегированное исключение Errors during images baking. Исправьте каждый
исходный файл: агрегированное число не является первопричиной.
Порядок проверки
Для изменений документации/модели:
python BuildTools\docs_image_format.py --write
python BuildTools\docs_image_format.py --check
python -m unittest BuildTools.tests.test_docs_image_format
python BuildTools\docs_contract_diff.py --help
python BuildTools\docs_validate.py
Для изменений importer, container, atlas или playback запустите focused native
image-baker и texture-atlas coverage через настроенную цель RunUnitTests.
Test_ImageBaker.cpp покрывает targeted/scan baking, поведение BakeChecker,
PNG/TGA, каждый legacy importer, options, flattening/directions FOFRM, shared
records, переименование выхода и повреждённые входы. Test_TextureAtlas.cpp
покрывает split/search/free allocator.
Затем проверьте затронутый встраиваемый проект:
- Перегенерируйте image-format model/reference и просмотрите агрегированный
diff контракта
image-format. - Перезапеките затронутые ресурсы закреплённой ревизией Engine проекта.
- Запустите узкие project resource/prototype checks, разрешающие эти пути.
- Запустите видимую клиентскую сцену, использующую каждое изменённое изображение, анимацию, направление, отражение, alpha edge, hit area и поддерживаемый renderer/profile.
- Для locomotion offsets также следуйте Sprite Root Motion и проверьте прямое движение, повороты, смену направления и переходы stop/start.
Native tests доказывают инварианты декодирования и контейнера. Они не доказывают framing графики проекта, приоритет resource pack, визуальный темп, filtering, clickability или воспринимаемое скольжение ног.
Checklist изменения
При изменении image surface:
- обновите
BuildTools/ImageFormatInterface.jsonи это руководство в одной правке Engine; - перегенерируйте
Docs/generated/image-format.jsonи все generated image-страницы; - запустите
BuildTools/tests/test_docs_image_format.py, полный documentation suite иdocs_contract_diff.pyотносительно требуемой базы; - запустите focused native tests затронутой границы loader/runtime/atlas;
- обновляйте Baking Pipeline, Client Runtime или Sprite Root Motion, только когда меняется принадлежащее им поведение;
- обновляйте документацию встраиваемого проекта только для конкретных assets, policy, integration и изменений видимой проверки;
- закрепляйте public examples на точной ревизии Engine и не обещайте поддержку формата или option, которую не исполняет их validation route.