次のように、任意の衝突オブジェクトを任意の衝突オブジェクトに処理する物理システムを作成しました。
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();
...
...
}
add 関数を使用してコンテナーを推測したいので、システムを使用するとタイプ リストが自動的に更新されます。テンプレート関数を使用してタイプリストを生成する方法はわかったと思いますが、必要な場所やコンパイルのどの時点でそれを取得するかはわかりません。
そうでない場合は、2 つのタイプリストを使用するシステムが更新関数を内部的に記述して、すべてのリストを反復処理し、それらを相互にペアリングします。
私はブースト MPL の本をいくつか読み、Andrei の本を数回読みました。しかし、私はそれがどのように機能するかに夢中になっているようで、実際にそれをどのように使用するかには変換していません. MPLの本に実世界の例に関するセクションがもう1つあればいいのにと思います。
ゲーム エンジンのすべての部分を、レンダリング、物理、衝突 (検出と反応を分けています)、入力、ネットワーク、サウンドなどと相互作用させることができました。すべて一般的な方法で行います。今、私はすべてのものを一般的な方法で保持する必要があります。すべての汎用的な作業の後、コンテナーに何かを保持できるようにするためだけに継承を要求するのはばかげています。コレクションのすべての可能性をコードに渡したくありません。これは汎用プログラミングの大きな利点の 1 つです。
Jalf は、MPL を使用して同様のことを行っていることを示していましたが、それを理解するのに十分なほど詳しく説明していませんでした。誰かが実際の使用例を知っているか、MPL の使用に関する詳細情報を入手できる場所を知っていれば、私は感謝します。
再度、感謝します!
アップデート
boost MPL と boost Fusion はどちらも私が望んでいるように見えますが、どちらのライブラリの実際の良い例もほとんどないようです。MPL のドキュメントは、このテンプレートがこれを行う以上のものではありません。その意味を理解してください。フュージョンは、「例を示しますが、これは氷山の一角にすぎません!」の方が少し優れています。
ブースト 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 は使用していません。しかし、それは単なるレガシー思考なのかもしれません。