基于组件的游戏引擎中的模板和运行时组件加载

时间:2011-04-16 18:42:30

标签: c++ templates components runtime game-engine

假设我有一个基于组件的游戏引擎,并且在那个引擎中我有一个 以stl映射的形式存储属性存储库的对象 通过对象access()方法访问,这是一个模板化的调用 您可以访问存储库并将任何类型的数据存储到存储库中,例如:

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;
        }
}

然后开始我的问题和怀疑的海洋:这个代码是否会编译为 共享库?如果是的话,当我在运行时加载并插入时会发生什么 a已经创建并填充了其他组件对象?假设其他 已经进行访问&lt; double&gt;(...)调用的组件将是地图 一样吗?

假设组件也有一个类型,比如struct position {int x,y; } 之前没有定义,所以这个代码还没有在主引擎中编译, 在这个最近插入的组件中access<position>(...)会发生什么?

对于这个大问题感到抱歉,但这也是我头脑中的一个大问题。 我对C ++非常熟悉,但仍然了解模板的工作原理......

有没有人有这方面的经验可以启发我?

另外我觉得函数调用中的静态std :: map不是最好的 方法,但我想不出另一个让我创造跨度的方法 基于呼叫的不同属性存储库...

谢谢!

2 个答案:

答案 0 :(得分:0)

这样做很好。实际上,由于链接顺序问题和构造顺序问题,您希望将模板化容器作为函数中的静态容器。规则声明必须在调用第一个函数之前创建所有静态对象。我使用一个名为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>();
}

答案 1 :(得分:0)

除了代码中access的错误签名之外,这一切都归结为您的平台如何处理来自共享库的实例化全局对象。在我看来,你将最终得到每个库加载到进程中std::map<std::string, Whatever>的不同实例......