Загрузка шаблонов и компонентов в игровом движке на основе компонентов - PullRequest
0 голосов
/ 16 апреля 2011

Предположим, у меня есть игровой движок на основе компонентов, и в этом движке у меня есть объект, который хранит хранилище свойств в виде карты STL и может быть доступным через метод доступа к объекту, который является шаблонным вызовом, так Вы можете получить доступ и хранить данные любого типа в хранилище, например:

class component {
    private:
        object * parent;

    public:
        component() : parent(0) { }
        void setparent(object * p) { parent = p; }
        virtual void tick() = 0;
}

class object {
    private:
        std::list compipeline;

    public:
        template<typename prop_t>
            access(std::string propname) {
                static std::map<std::string, prop_t> repository;
                return repository;
            }

        void attach(component * c) {
            compipelane.push_back(c);
            c->setparent(this);
        }
};

В этой схеме компоненты будут вызывать что-то вроде

parent.access<double>("health) = 0;

Пока все отлично, но я хочу поддержать динамическую загрузку компонентов. Я знаю, что шаблоны разрешаются во время компиляции, тогда весь код для доступа () вызовы, подобные приведенным выше, будут генерироваться при компиляции кода моего движка. Но затем я разрабатываю компонент и собираю его как загружаемую разделяемую библиотеку, которая делает parent.access ("урон"), например:

class health : public component {
    public:
        health(object & parent) : component(parent) { }
        virtual void tick() {
            double damage = parent.access<double>("damage");
            parent.access<double>("health") -= damage;
            parent.access<double>("damage") = 0;
        }
}

Ну, тогда начинается мое море вопросов и сомнений: этот код скомпилируется как общая библиотека? Если да, что произойдет, когда я загружу его во время выполнения и подключу уже созданный и заполненный другими компонентами объект? Предположим, другие компоненты, которые уже сделали вызов (...), будут ли карты то же самое?

Предположим, у компонента также был создан тип, например struct position {int x, y; } это не было определено ранее, поэтому этот код не был скомпилирован в главном движке, что будет в access<position>(...) в этом недавно подключенном компоненте?

Извините за большой вопрос, но это большой вопрос и в моей голове. Я довольно знаком с C ++, но все еще понимаю, как работают шаблоны ...

Кто-нибудь имеет опыт с этим, который мог бы просветить меня?

Также я чувствую, что статический std :: map внутри вызова функции не самый лучший подход, но я не могу думать о другом, который позволит мне создать пролеты различные хранилища свойств, основанные на вызове ...

Спасибо!

Ответы [ 2 ]

0 голосов
/ 24 апреля 2011

Помимо неверной подписи access в вашем коде, все сводится к тому, как ваша платформа справляется с созданием глобальных объектов из общих библиотек.Насколько я понимаю, вы получите разные экземпляры std::map<std::string, Whatever> для библиотеки, загруженной в процесс ...

0 голосов
/ 24 апреля 2011

Это хорошо.Фактически, из-за проблем порядка ссылок и проблем порядка построения вы хотите, чтобы ваш шаблонный контейнер был статическим в функции.Правила гласят, что все статические объекты должны быть созданы до вызова первой функции.Я использую функцию GetRegistry, которая хранит только реестр, так как несколько функций не могут получить доступ к статическим функциям других функций.Таким образом, вы можете получить что-то вроде этого:

class GameWorld
{
    template <typename T>
    T& GetRegistry
    {
        static T registry;
        return registry;
    }

public:
    template <typename T>
    void Add(const T& gameThing)
    {
        GetRegistry<T>().push_back(gameThing);
    }

    template <typename T>
    void Update()
    {
        for_each(GetRegistry<T>().begin(), GetRegitry<T>.end(), Render);
    }
};

void main()
{
    GameWorld world;

    Animal cow;
    Soldier sniper;
    Soldier cook;

    world.Add(cow);
    world.Add(sniper);
    world.Add(cook);

    world.Update<Animal>();
    world.Update<Soldier>();
}
...