Skip to content

Valeryn4/StaticECS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StaticECS

This Template ECS (Entity Component System)

облегченная реализация ECS, через агегирующие шаблоны и явную композицию через кортежи. Тут все отдано на откуп программисту. Создание Entity, наполнение его компонентами и получение компонентов - все просчитывается в Компайл тайме. Данная библиотека не содержит в себе готовых компонентов или систем. Только базовый функционал!!!

EntityComp<Components...>
  • Сущность-композитор. Все данные хранятся в кортеже, внутри сущности. Доступ к ним вызывает std::get.
Component<DATA></b> 
  • Шаблонный компонент. Каждый тип компонента уникальный и не имеет базового общего класса. DATA - это любая структура с данными и методами для работы с данными. В компоненьте ни в коме случае, не должна выполняться логика!!!! Только базовый фунционал для работы с данными.
System<Component>
  • Шаблонная система связанная с компонентом. Это абстрактная система с методами Update и Draw. Как система будет работать и взаимоействовать с компонентами - остается на откуп программисту. Т.к. сущности и компоненты не знают ничего об системах, систему можно реализовать независимо от фреймворка, не наследуя ни от какого либо класса
Component<DATA>::Pool
  • Пулл компонентов. Имеет статический инстанс. В основном, это необходимо системе.
EventComponent
SystemEvent
  • Простейшая система событий, где событие - есть функция передающайся в std::function<void()>

пример:

    Render::Texture _texture;

    using Sprite = Component<SpriteData>;
    using Transform = Component<TransformData>;
    using MoveTo = Component<MoveToData>;

    using Entity = EntityComp<Sprite, Transform, MoveTo>;

    SpriteSystem _spriteSystem;
    MoveSystem _moveSystem;

    Entity _entity;

    void Init()
    {
        _entity.GetComponent<Sprite>().SetTexture(_texture);
        _entity.GetComponent<Transform>().SetPosition(math::Vector3(500,500,500));
        _entity.GetComponent<MoveTo>().SetParam(math::Vector3(900, 900, 900), 10.f);
    }

    void Draw()
    {
        //отрисовка компонентов спрайт
        _spriteSystem.Draw();
    }

    void Update(float dt)
    {
        //обновлени движения сущностей.
        _moveSystem.Update(dt); 
    }

пример с событиями:

//Данные для компонента-слушателя
struct ListenerTargetData
{
    std::string name =  "Target_0";
    int i = 0; 

    void Set(int v)
    {
        i = v;
        printf("Listener %s i set to %i\n", name.c_str(), i);
    }
};

//данные для компонента слушателя бродкастов
struct ListenerBrodcastData
{
    std::string name = "Brodcast";
    int i = 0;

    void Set(int v)
    {
        i = v;
        printf("ListenerBrodcast %s i set to %i\n", name.c_str(), i);
    }
};

//Компонент слушателя одиночки
using ListenerTargetComp = StaticECS::Component<ListenerTargetData>;
//компонент слушателя бродкастов
using ListenerBrodcastComp = StaticECS::Component< ListenerBrodcastData>;
//компонент event
using EventComponent = StaticECS::EventComponent;

//сущность генерирующая события и слушатель одиночка
using Entity = StaticECS::EntityComp< EventComponent, ListenerTargetComp>;
//сущность слушатель бродкастов и слушатель одиночка (ВНИМАНИЕ! МЫ СПЕЦИАЛЬНО ДОБАВИЛИ СЮДА СЛУШАТЕЛЯ-ОДИНОЧКУ! ДЛЯ ДЕМОНСТРАЦИИ)
using Entity2 = StaticECS::EntityComp<ListenerBrodcastComp, ListenerTargetComp>;




int main()
{
    //создаем сущность, которая будет генерировать события
    Entity entity;
    //создаем систему
    StaticECS::SystemEvent system_;

    //получаем указатели на компоненты бродкастера
    auto listener = entity.GetComponentPtr<ListenerTargetComp>();
    auto event = entity.GetComponentPtr<EventComponent>(); //компонент event, в который мы будем посылать кобытия


    //создаем 10 сущностей, которые будут ловить бродкасты, посылаемые в ListenerBrodcastComp
    for (int i = 0; i < 10; ++i)
    {
        auto e = new Entity2();
        e->GetComponent<ListenerBrodcastComp>().name = "Brodcast_" + std::to_string(i);
    }

    
    //Пусть это будет у наж GameLoop
    std::thread thread([listener, event, &system_]() 
    {


        for (int i = 0; i < 10; ++i)
        {

            auto parent = event->GetParent();

            //отправляем три события в целевой компонент самому себе. Ключ является parent!
            for (int z = 0; z < 3; ++z)
            {
                
                event->PushEvent([parent]()
                {
                    //так мы получаем компонент-слушатель, который принадлежит той же сущности, что и создает ивент
                    //если такого компонента нет - получим nullptr
                    auto comp = ListenerTargetComp::Pool::Instance().GetComponent(parent); 
                    if (comp)
                    {
                        comp->Set(comp->i + 1);
                    }
                });

                
            }

            //отправляем событие-бродкаст, которео отправиться всем компонентам ListenerBrodcastComp
            event->PushEvent([]() 
            {
                auto& pool = ListenerBrodcastComp::Pool::Instance().GetPool();

                //обратиет внимание! Что порядок перебора зависит от реализации std::unorder_map
                for (auto &&v : pool)
                {
                    v.second->Set(v.second->i + 1);
                }
                
            });

            printf("\nUpdate all events!\n");
            system_.Update(1);

            using namespace std::chrono_literals;
            std::this_thread::sleep_for(1s);
        }

    });


    thread.join();

    system("pause");
}

About

This Template ECS (Entity Component System)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages