Архитектура спрайтовой системы в Space Station 14

SS14_#3 // Основы RSI, анимации, оптимизация текстур // Время чтения: 45 мин

Обзор

Спрайтовая система в Space Station 14 - это комплексная архитектура для управления визуальными элементами игры. Построенная на движке RobustToolBox, она обеспечивает эффективное, гибкое и поддерживаемое управление спрайтами для всех игровых сущностей и элементов интерфейса.

Обработка спрайтов на уровне движка (RobustToolBox)

RSI (Runtime Sprite Image) система

Расположение: `RobustToolbox/Robust.Client/Graphics/RSI/`

Система RSI является основным компонентом движка для работы с файлами спрайтов. Она поддерживает:

  • Многнаправленные спрайты (1, 4 или 8 направлений)
  • Анимации с кадрами и настраиваемыми задержками
  • Определения спрайтов на основе метаданных
  • Оптимизацию через текстуровые атласы

Основные файлы RSI

  • RSI.cs - Основной класс RSI, хранит определения спрайтов и состояний
  • RSI.State.cs - Индивидуальное состояние спрайта с поддержкой анимации

Структура RSI

Каждый RSI представляет собой директорию с следующей структурой:

text
your_sprite.rsi/
├── meta.json         # Метаданные
├── state1.png        # Состояние 1 (один кадр)
├── state2-1.png      # Состояние 2 (кадр 1)
├── state2-2.png      # Состояние 2 (кадр 2)
└── state2-3.png      # Состояние 2 (кадр 3)

Пример meta.json

json
{
  "version": 1,
  "license": "CC-BY-SA-3.0",
  "copyright": "Taken from vgstation at https://github.com/vgstation-coders/vgstation13/commit/1cdfb0230cc96d0ba751fa002d04f8aa2f25ad7d",
  "size": {
    "x": 32,
    "y": 32
  },
  "states": [
    {
      "name": "stunbaton_off"
    },
    {
      "name": "stunbaton_on",
      "delays": [
        [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
      ]
    },
    {
      "name": "on-inhand-left",
      "directions": 4,
      "delays": [
        [0.1, 0.1, 0.1, 0.1],
        [0.1, 0.1, 0.1, 0.1],
        [0.1, 0.1, 0.1, 0.1],
        [0.1, 0.1, 0.1, 0.1]
      ]
    }
  ]
}

SpriteComponent

Расположение: `RobustToolbox/Robust.Client/GameObjects/Components/Renderable/SpriteComponent.cs`

SpriteComponent - это основной компонент для рендеринга спрайтов на сущностях. Ключевые функции:

  • Поддержка многослойности: Каждый спрайт может иметь несколько слоев для сложных визуальных эффектов
  • Направленные спрайты: Автоматически выбирает спрайт на основе направления сущности
  • Обработка анимаций: Поддерживает анимации с кадрами и пользовательскими задержками
  • Трансформации: Управление масштабом, поворотом и прозрачностью
  • Слоевая маппинг: Именованные слои для удобного управления состояниями

SpriteSystem

Расположение: `RobustToolbox/Robust.Client/GameObjects/EntitySystems/SpriteSystem.cs`

SpriteSystem управляет всеми операциями с спрайтами в движке:

  • Обновление кадров: Обрабатывает прогрессию анимаций
  • Манипуляция слоями: Добавление, удаление и изменение слоев спрайтов
  • Загрузка ресурсов: Загрузка и кэширование ресурсов RSI и текстур
  • Управление анимациями: Воспроизведение, пауза и синхронизация анимаций
  • Оптимизация рендеринга: Обнаружение неактивных спрайтов и пространственное разбиение

Реализация спрайтов на уровне контента

Компоненты Content.Shared

Расположение: `Content.Shared/Sprite/`

  1. RandomSpriteComponent - Обрабатывает случайные вариации спрайтов с поддержкой групп
    • Позволяет указывать доступные группы спрайтов с состояниями слоев и цветами
    • Поддерживает выбор либо всех групп, либо случайной одиночной группы
    • Сетевая компонент для синхронизации сервер-клиент
  2. ScaleVisualsComponent - Управляет масштабом спрайта с сервера
    • Сетевая компонент для серверного контроля масштаба спрайта
    • Поддерживает отслеживание исходного масштаба для восстановления
  3. SpriteFadeComponent - Отмечает сущность для затемнения спрайта
    • Сетевая компонент, заставляющая клиент затемнять сущность, когда игрок за ней

Пример RandomSpriteComponent

csharp
[RegisterComponent, NetworkedComponent]
public sealed partial class RandomSpriteComponent : Component
{
    [DataField("getAllGroups")]
    public bool GetAllGroups;

    [DataField("available")]
    public List>> Available = new();

    [DataField("selected")]
    public Dictionary Selected = new();
}

Системы Content.Client

Расположение: `Content.Client/Sprite/`

  1. ContentSpriteSystem - Инструмент для администраторов для экспорта спрайтов
    • Экспортирует спрайт во всех 4 направлениях (Юг, Восток, Север, Запад)
    • Использует целевой рендеринг для захвата спрайта сущности
    • Доступно через административный глагол "Export Sprite"
  2. RandomSpriteSystem - Клиентская обработка случайных спрайтов
    • Обрабатывает обновления состояния компонента с сервера
    • Обновляет как SpriteComponent, так и визуал ClothingComponent
    • Поддерживает слоевую маппинг через перечисления или строковые ключи
  3. SpriteFadeSystem - Реализация анимации затемнения
    • Затемняет сущности, когда игрок за ними
    • Отслеживает позицию игрока и курсор мыши для логики затемнения
    • Управляет FadingSpriteComponent для отслеживания активного затемнения
    • Восстанавливает исходную прозрачность при выключении компонента
  4. ScaleVisualsSystem - Управление масштабом с сервера
    • Обрабатывает AppearanceChangeEvent для обновления масштаба спрайта
    • Отслеживает исходный масштаб для восстановления при удалении компонента
    • Работает с ScaleVisualsComponent и SharedScaleVisualsSystem

Структура ресурсов спрайтов

Организация директорий

Спрайты организованы в директории `Resources/Textures/`:

text
Resources/Textures/
├── Objects/              # Игровые объекты
│   ├── Weapons/          # Оружие (ближний бой, огнестрельное, Throwable)
│   ├── Misc/             # Разное
│   ├── Consumable/       # Еда и напитки
│   ├── Devices/          # Электронные устройства
│   └── Storage/          # Контейнеры и хранилища
├── Mobs/                 # Живые сущности
├── Effects/              # Визуальные эффекты
├── Decals/               # Наполнители пола
├── Interface/            # Спрайты интерфейса
├── Tiles/                # Пол и стены
└── Structures/           # Здания и структуры

Пример структуры RSI - Бензопила

text
Resources/Textures/Objects/Weapons/Melee/chainsaw.rsi/
├── meta.json            # Метаданные
├── icon.png             # Состояние покоя (анимированное)
├── inhand-left.png      # Левая рука (4 направления, анимированно)
├── inhand-right.png     # Правая рука (4 направления, анимированно)
├── wielded-inhand-left.png  # Рука в несении (лево, 4 направления, анимированно)
└── wielded-inhand-right.png # Рука в несении (право, 4 направления, анимированно)

Определение спрайтов в прототипах

Базовый Sprite Component

yaml
- type: entity
  name: chainsaw
  parent: BaseItem
  id: Chainsaw
  components:
  - type: Sprite
    sprite: Objects/Weapons/Melee/chainsaw.rsi
    state: icon
  - type: Item
    sprite: Objects/Weapons/Melee/chainsaw.rsi
  - type: MeleeWeapon
    autoAttack: true
    damage:
      types:
        Slash: 2
        Blunt: 2
        Structural: 4

Сложный спрайт с слоями и визуализаторами

yaml
- type: entity
  name: stun prod
  parent: [BaseItem, BaseMinorContraband]
  id: Stunprod
  components:
  - type: Sprite
    sprite: Objects/Weapons/Melee/stunprod.rsi
    layers:
    - state: stunprod_off
      map: [ "enum.ToggleableVisuals.Layer" ]
  - type: ItemToggle
    soundActivate:
      collection: sparks
    soundDeactivate:
      collection: sparks
  - type: Stunbaton
    energyPerUse: 120
  - type: GenericVisualizer
    visuals:
      enum.ToggleableVisuals.Enabled:
        enum.ToggleableVisuals.Layer:
          True: {state: stunprod_on}
          False: {state: stunprod_off}

Инструменты и обработка спрайтов

Iconsmooth Tool

Расположение: `Tools/iconsmooth.py` и `iconsmooth_lib.py`

Конвертирует спрайтовые листы в иконные состояния с антиалиасингом.

Использование

bash
python3 iconsmooth.py input.png METRICS MODE OUTPREFIX

Параметры

  • input.png: Исходный спрайтовый лист
  • METRICS: Конфигурация тайлов (например, 32x32)
  • MODE: Режим конвертации (например, walls, floors)
  • OUTPREFIX: Префикс для выходных файлов

Плагины Aseprite

Расположение: `Tools/SS14 Aseprite Plugins/`

Плагины для редактора спрайтов Aseprite:

  • Displacement Map Visualizer.lua: Предварительный просмотр карты смещений
  • Displacement Map Flip.lua: Отражение карт смещений по горизонтали/вертикали
  • Displacement Map Shift.lua: Сдвиг карт смещений
  • Aseprite Templates: Шаблоны для создания спрайтов

Загрузка и кэширование спрайтов

RSIResource

Расположение: `RobustToolbox/Robust.Client/ResourceManagement/ResourceTypes/RSIResource.cs`

RSIResource отвечает за загрузку и кэширование файлов RSI:

  • Асинхронная загрузка: Неблокирующая загрузка ресурсов
  • Восстановление после ошибок: Вариант fallback на error.rsi, если RSI не найден
  • Генерация атласов: Оптимизация загрузки и рендеринга текстур
  • Управление кэшем: Кэширует загруженные RSI для будущих обращений

Пайплайн загрузки ресурсов

  1. Ресурсы загружаются из ContentPack
  2. Метаданные RSI парсятся из meta.json
  3. PNG-файлы загружаются и обрабатываются
  4. Текстуры упаковываются в атласы для оптимизации GPU
  5. Ресурсы кэшируются для будущих использований

Система анимаций спрайтов

Архитектура анимаций

Каждое состояние спрайта может иметь анимации с:

  • Задержками между кадрами: Указывает время между каждым кадром
  • Направленными анимациями: Отдельные анимации для каждого направления
  • Управлением циклами: Циклические или одноразовые анимации

Определение анимации

json
{
  "name": "stunbaton_on",
  "delays": [
    [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
  ]
}

Система анимаций

SpriteSystem.FrameUpdate() управляет прогрессией анимаций:

  • Очередь обновления кадров: Сущности с анимированными спрайтами помещены в очередь для обновлений
  • Синхронизация времени: Анимации синхронизируются с игровым временем
  • Поддержка паузы: Пауза анимаций, когда сущность приостановлена
  • Неактивные спрайты: Пропускает обновления для неанимированных спрайтов

Расширенные функции спрайтов

Направленные спрайты

  • 4-направленная система: Юг, Восток, Север, Запад
  • Автоматический выбор: На основе направления сущности
  • Поддержка состояний: Состояния могут иметь 1, 4 или 8 направлений

Система слоев

  • Несколько слоев на спрайт: Сложные визуальные эффекты путем объединения слоев
  • Независимые свойства: Каждый слой имеет свой RSI, состояние и свойства
  • Слоевая маппинг: Именованные слои для удобного управления состояниями

Визуализаторы

  • GenericVisualizer: Связывает поля данных с визуальными изменениями
  • Серверный контроль: Позволяет серверу обновлять внешний вид спрайта
  • Переходы между состояниями: Обрабатывает плавные переходы между визуальными состояниями

Оптимизация производительности

Неактивные спрайты

  • Автоматическое обнаружение: Спрайты без анимаций помечаются как неактивные
  • Оптимизация обновлений: Пропускает обновления кадров для лучшей производительности

Текстуровые атласы

  • Упаковка спрайтов: Спрайты упаковываются в атласы для уменьшения числа вызовов отрисовки
  • Оптимизация GPU: Уменьшает переключение текстур и улучшает эффективность кэша

Кэширование

  • Кэш RSI: Загруженные RSI кэшируются
  • Кэш компонентов спрайтов: Компоненты повторно используются при возможности
  • Предварительная загрузка: Ресурсы загружаются заранее для быстрого доступа

Инструменты для отладки и разработки

Инструмент для экспорта спрайтов

  • Административный глагол: Экспорт спрайтов сущности как PNG
  • Поддержка направлений: Экспортирует все 4 направления
  • Место вывода: Директория `/Exports`

Наложение границ спрайтов

  • Визуализация для отладки: Показывает границы спрайтов для детекции столкновений
  • Кодирование цветом: Разные цвета для разных типов границ

Система дерева спрайтов

  • Пространственное разбиение: Оптимизирует порядок рендеринга и проверки видимости
  • Быстрый поиск: Улучшает производительность при большом количестве сущностей

Заключение

Архитектура спрайтовой системы в Space Station 14 - это мощный и гибкий инструмент для создания визуально привлекательного и производительного игрового контента. Понимание основ RSI, SpriteSystem и спрайтовых компонентов является важным для разработки качественных модов и контента.

Полезные ссылки