【发布时间】:2011-04-26 07:16:25
【问题描述】:
我创建了一个物理系统,可以处理任何碰撞对象到任何碰撞对象,如下所示:
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 的文档只不过是这个模板所做的,祝你好运理解它的含义。 “这是一个例子,但这只是冰山一角!”
一个典型的 boost MPL 示例是 has_xxx。他们在示例中使用了 XXX 和 xxx,因此很难看出可以使用 XXX(所需文本)和 Test 或 CheckType 或任何更可区分的用户类型来代替 xxx 的区别。另外,没有提到这些都不在命名空间中。现在我知道为什么 Scott meyers 将其与 Psycho 中的淋浴场景进行比较了。
真的很遗憾,因为我编译和理解的很少内容确实有用,但很难弄清楚如果我是在出货产品上,我永远不会花这么多精力。
如果有人知道真实世界的示例或更好的参考资料、解释或教程,我将不胜感激。
更新
这里有更多代码:
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);
那么我所需要的就是调用 collide with all my active collidable objects 来对抗我所有的主动和被动对象。
我没有使用 std::function ,因为添加了函数名使代码对我来说更清晰。但也许这只是传统思维。
【问题讨论】:
-
mpl 容器没有运行时数据,请改用融合容器
-
谢谢,我正在调查他们。
-
另外,我认为您所追求的模式是
multiple dispatch。所以你可以重新阅读安德烈书中的related chapter ...干杯 -
@sehe 我会再看一遍那一章。我有一段时间没读过了。我已经完成了双重调度。我没有的是一个自动的碰撞世界容器,它知道里面有哪些序列,哪些是动态的,哪些是静态的。
-
@Tavison:也许我只是不完全理解 :) 我已经 +1 这个问题了
标签: c++ templates metaprogramming boost-mpl