我创建了一个物理系统,可以处理任何碰撞对象到任何碰撞对象,如下所示:
namespace Collision
{
template <typename T, typename U>
inline void Check(T& t, U& u)
{
if(u.CheckCollision(t.GetCollider()))
{
u.HitBy(t);
t.Hit(u);
}
}
}
还有其他几个帮助对象使其易于使用,但要点是有动态对象需要针对静态对象和其他动态对象进行测试,而静态对象不需要检查。
我想要的是这样的:
void func()
{
PhysicsWorld world;
shared_ptr<CSphere> ballPhysics(new CSphere(0,0,ballSprite->Width()));
BallCommand ballBehavior;
CBounds bounds(0, 0, 640, 480);
CBox obstacle(200, 150, 10, 10);
Collision::Collidable<CBounds> boundC(bounds);
Collision::Collidable<std::shared_ptr<CSphere>, BallCommand&> ballC(ballPhysics, ballBehavior);
Collision::Collidable<CBox> obstC(obstacle);
world.addStatic(boundC);
world.addDynamic(ballC);
world.addStatic(obstC);
...
...
world.Update();
...
...
}
我很想通过添加函数来推断容器,因此使用系统会自动更新类型列表。我想我知道如何使用模板函数生成类型列表,但不知道如何在我需要的地方获得它,或者在编译的什么时候完成。
如果不是这样,那么某些系统使用两个类型列表,然后在内部编写更新函数来迭代所有列表,使它们相互配对。
我已经阅读了一些 boost MPL 的书,并多次阅读了 Andrei 的书。但是,我似乎陷入了它的工作原理,并没有真正将其转化为我如何使用它。我希望他们在 MPL 书中有更多关于现实世界示例的部分。
我已经能够让游戏引擎的所有部分与渲染、物理、碰撞(我将检测与反应分开)、输入、网络、声音等以通用方式进行交互。现在我只需要以一种通用的方式来保存所有的东西。在完成了所有通用工作之后,要求继承只是为了让我可以在容器中保存一些东西是很愚蠢的,而且我不想手动编写每个集合的可能性,因为这是通用编程的一大好处。
我看到 Jalf 曾表示他/她使用 MPL 做了类似的事情,但没有详细说明,我无法弄清楚。如果有人知道实际使用示例或者我可以在哪里获得有关使用 MPL 的更多信息,我将不胜感激。
再次感谢!
更新
boost MPL 和 boost Fusion 似乎都可以满足我的要求,但是这两个库的真实生活示例似乎都很少。MPL 的文档只不过是这个模板所做的,祝你好运理解它的含义。“这是一个例子,但这只是冰山一角!” Fusion 更好一些。
一个典型的 boost MPL 示例是 has_xxx。他们在示例中使用了 XXX 和 xxx,因此很难看出可以使用 XXX(所需文本)和 Test 或 CheckType 或任何更可区分的用户类型来代替 xxx 的区别。另外,没有提到这些都不在命名空间中。现在我知道为什么斯科特迈耶斯将其与《惊魂记》中的淋浴场景相提并论了。
真的很遗憾,因为我编译和理解的一点点确实有用的东西,但是很难弄清楚如果我在运输产品上我永远不会花这么多精力。
如果有人知道真实世界的示例或更好的参考资料、解释或教程,我将不胜感激。
更新
这里有更多代码:
template <typename T, typename V = VictimEffect, typename M = MenaceEffect>
class Collidable
{
T m_Collider;
V m_HitBy;
M m_Hit;
public:
Collidable(T collide, V victim, M menace) : m_Collider(collide), m_HitBy(victim), m_Hit(menace) {;}
Collidable(T collide) : m_Collider(collide) {;}
Collidable(T collide, V victim) : m_Collider(collide), m_HitBy(victim) {;}
T& GetCollider()
{
return m_Collider;
}
template <typename V>
void HitBy(V& menace)
{
m_HitBy.HitBy(menace.GetCollider());
}
template <typename V>
void Hit(V& victim)
{
m_Hit.Hit(victim.GetCollider());
}
template <typename V>
bool CheckCollision(V& menace)
{
return m_Collider.CheckCollision(menace);
}
};
然后使用它我这样做
Collidable<Boundary, BallCommand> boundC(boundary, ballBehavior);
Collidable<CollisionBox> ballC(circle);
然后我所需要的就是调用与我所有的主动可碰撞对象碰撞我所有的主动和被动对象。
我没有使用 std::function ,因为添加函数名称使代码对我来说更清晰。但也许这只是传统思维。