Привет, читатель! В этой статье не будет практики, а только спецификация формата и примеры для его объяснения. Код парсера будет в следующей части статьи!
Что такое ECS
ECS - Entity Component System (Сущности Компоненты Системы), это распространённый паттер программирования игр, используемый для упрощения разработки. В этом паттерне есть 3 определения:
Entity (Сущность) - контейнеры, хранящие в себе Компоненты (Данные). Сами не хранят свойства.
Component (Компонент) - классы/структуры, хранящие в себе всевозможные данные, нужные для игровой логики (Систем).
System (Системы) - Логические ядра игры. Они манипулируют сущностями и данными внутри них. Чаще всего реализуются классами
Если же вы хотите разобраться в теме подробнее, предлагаю вам вот эту статью.
Хочу отметить, что в Формате будет возможно описывать только ПЕРВЫЕ два определения, так как для описания игровой логики нужен язык программирования, а это задача сложная.
Зачем?
"Зачем?" - задаст вопрос читатель. И я отвечу - упрощение. Вот пример объявления компонента во ECS-фреймворке BrokenBricksECS:
namespace ECSExample { [Serializable] public struct FloatComponent : IComponent { public float value; public FloatComponent(float value) { this.value = value; } } public class FloatDataComponent : ComponentDataWrapper<FloatComponent> { } }
Сначала мы здесь должны создать структуру, внутри которой будет значения и конструктор. Потом мы создаем FloatDataComponent. Это обёрнутый в ComponentDataWrapper FloatComponent. Разве это нужно?
Решение
Для этого я предлагаю создать формат описания компонентов и прототипов сущностей (префабов). И все что мне пришло на ум, так только это.
@component Component1 { value: int, } @component Comp2(Component1) { value2: str = "default_value" # Будет иметь value: int и value2: str } # Родитель - Component1
Используя ключевое слово @component, мы создаем новый компонент. Внутри фигурных скобок типы объявляются так: <name>: <type>, также можно указать дефолтное значение <name>: <type> = <value>
Комментарии начинаются с символа решётки # Комментарий
Наследование компонентов?
Компоненты могут наследоваться друг от друга. Это делается так:
@component <name>(<parent>) { data_from_parent, ..., new_and_overriden_data } # Пример @component Component1 { value: int, } @component Comp2(Component1) { value2: str = "default_value" # Будет иметь value: int и value2: str } # Родитель - Component1
Множественного наследования формат не поддерживает, так как есть проблема ромба.
Хочу заметить, ради оптимизации компоненты при наследовании просто сливаются.
Прототипы сущностей (Префабы)
А тут, во время написания, мне приходит мысль? А почему бы и не добавить в формат описание сущностей! И я добавил их:
@entity Name { Component1(value=10) } @entity Name2(Name) { Comp2(10, 'default_value') } @entity Name3 { # Равен Name Component1(10), Comp2(value=10) }
Используя ключевое слово @entity <name>, мы создаем новый прототип сущности. Внутри фигурных скобок компоненты добавляются так: <name>(<value>, <field_name>=<value>)
Наследование же работает также, как у компонентов.
Итог
Итого, у нас есть вот такой example-файл:
@component Component1 { value: int, } @component Comp2(Component1) { value2: str = "default_value" # Будет иметь value: int и value2: str } # Родитель - Component1 @entity Name { Component1(value=10) } @entity Name2(Name) { Comp2(10, 'default_value') } @entity Name3 { # Равен Name Component1(10), Comp2(value=10) }
В следующей части я напишу парсинговый механизм для этого формата. Удачи!
