copyright longer 2013
请不要转载。
(一)
我个人认为,好的程序结构不要用单例。
所以虽然有从loki里拿出来的SingletonHolder,但最后还是去掉不用了。
在初始化第一个对象时将全局的对象初始化,然后将其作为其他对象初始化条件传进对象,是不错的选择。
见附件Manager模块
(二)实体组件体系。
EntityX是个快速易于使用的Entity-component系统。
EntityX https://github.com/alecthomas/entityx
但是它只支持c++11标准。msvc2012都不能通过编译。原因是改库使用了c++11标准的可变模板参数新机制。
但这完全不是我们使用它的障碍。通过使用boost::mpl替换,还是十分简单的。
见附件的:
Entity Event System Manager模块。
(三)数据驱动
有了实体组件系统,数据驱动就水到渠成了,首先是提取组件的方式。
可做如下定义:
entitieManager是实体组件的实体池。
struct Position : public Component<Position>{...}
struct Orientation : public Component<Orientation>{...}
typedef boost::mpl::vector<Orientation,Position> TypeList;
typedef boost::shared_ptr<Position> EPositionPtr;
typedef boost::shared_ptr<Orientation> EOrientationPtr;
const View& v=entitieManager->entities_with_components<TypeList>();
for (View::Iterator it=v.begin();it!=v.end();++it)
{
o=(*it).component<Orientation>();
p=(*it).component<Position>();
...
}
然后分离系统。
一般较常分离的是逻辑和显示,甚或将之分为双线程。以此为例。
组件所含数据可以不必锁定。因为这并不影响,也不会运行时出错。
线程附件里用的是std::thread当然boost也是可以的。
数据驱动有一种需要update。就是action的update(Real dt)。
这需要另开线程(或者也可以不用)跑update。
std::thread t(&Manager::run,this);
configure();
mSystemManager->configure();
initialize();
t.join();
在run()里进行action系统的更新就可以。
其他数据驱动就是状态机机制。根据时间及io做出变换即可。
用boost::boost::signals2.或者Event。
signals需要写一些包装便于与现有实体组件联合使用。
主窗口的渲染不能是分线程,所以需要手动将渲染循环放在主线程。
详情见附件。
http://download.youkuaiyun.com/detail/undercallfile/6481915