Привет, читатель! В этой статье не будет практики, а только спецификация формата и примеры для его объяснения. Код парсера будет в следующей части статьи!
Что такое 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)
}
В следующей части я напишу парсинговый механизм для этого формата. Удачи!