物理衝突システムの関数の接続をコンパイラに構築させたいと考えています。私はテスト衝突機能を持っています:
template <typename T, typename U>
inline void Collision(T& t, U& u)
{
if(u.CheckCollision(t.GetCollider()))
{
u.HitBy(t);
t.Hit(u);
}
}
次に、コライダー オブジェクトを使用して衝突オブジェクトを保持します。
template <typename T>
class Collidable
{
T m_Collider;
VictimEffect m_HitBy;
MenaceEffect m_Hit;
public:
void SetCollider(const T& t) { m_Collider = t; }
void SetVictim(VictimEffect effect) { m_HitBy = effect; }
void SetMenace(MenaceEffect effect) { m_Hit = effect; }
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);
}
};
エフェクト関数に一定レベルの間接性を追加しました
class VictimEffect
{
public:
template<typename C>
void HitBy(C&)
{;}
};
class MenaceEffect
{
public:
template<typename C>
void Hit(C&)
{;}
};
私が行き着きたいと思っているのは、正しい関数シグネチャを持ち、ヒットしない型を必要としない任意のオブジェクトで関数を呼び出す方法です。
class Wall;
class Ball : public MenaceEffect
{
public:
void Hit(Wall& wall);
void Hit(Ball& ball);
};
class Wall : public VictimEffect
{
public:
void HitBy(Ball& ball);
};
壁にぶつかる壁の機能を持たせたくないことに注意してください。発生する必要がある相互作用の関数のみを作成または提供したい。VictimEffect は派生関数を「認識」しないため、これが機能しないことはわかっています。
テンプレートパラメーターが使用されているすべての場所で、テンプレートパラメーターを指定せずにディスパッチしたい。衝突可能とは別に衝突可能効果を構築し、それを衝突可能オブジェクトに一般的に与えたいと考えています。衝突できるもののコレクションごとに異なる衝突可能なオブジェクトを持ちたくありません。基本的に欲しい
vector<collidable> movingThings;
vector<collidable> staticThings;
// get iterators ...
Collide(Moving, Static);
ここには間接的な層がもっと必要ですが、それが見えません。コンパイル時にすべての情報が利用可能であるため、それが可能であることはわかっています。動的なポリモーフィック ソリューションは必要ありません。
どんな助けでも大歓迎です!
更新 私がやろうとしているのは、独自の最新の (Andrei の本のように) ゲーム ライブラリを構築することです。これまでのところ、私はほとんどの関係を解決してきましたが、これには困惑しています. これは時間的に重要な問題ではなく、結果が重要な問題です。私は何年もの間ゲームの仕事をしてきましたが、私が取り組んできたゲーム エンジンはどれも好きではありません。これは、使いやすく、拡張しやすいことを目的としています。コンソール コンパイラがそれほどひどくなくなったので、どのプラットフォームでも動作します。
これは、私が書きたいことの簡単な例です。
int main()
{
// System must come first
System system(640, 480, false);
Renderer renderer;
Mouse mouse;
Keyboard keys;
// Make the ball
Bounce ball;
Sprite ballSprite("02.bmp");
CollisionBox ballPhysics;
BallCommand ballBehavior;
ball.SpriteMover = boost::bind(&Sprite::Observer<Pos2D>, &ballSprite, _1);
ball.PhysicsMover = boost::bind(&CollisionBox::Move, &ballPhysics, _1);
// Make the bounds
Boundary bounds;
// Set up Physics
Collidable<Boundary> boundC;
boundC.SetCollider(bounds);
boundC.SetVictim(ballBehavior);
Collidable<CollisionBox> ballC;
ballC.SetCollider(ballPhysics);
PretendPhysics physics;
physics.SetBall(ballC);
physics.SetBounds(boundC);
while(!mouse.LeftClick() && !keys.AnyKey())
{
ball.MoveRel(ballBehavior.Delta());
physics.Update();
renderer.Clear();
renderer.Render(ballSprite);
renderer.SwapBuffers();
}
}
すべての Physics は WIP であり、私が望むところには行き着いていませんが、それは達成されつつあります。System object は、Windows とプラットフォーム固有のレンダラーを初期化します。この場合はopenGLです。コンソール アプリとしてコンパイルされますが、すべての Windows コンポーネントを作成します。私は人々に main() と winmain() を扱いたくありませんでした。物理学を除いて、継承はありません。シーンをシステムに取り込むと、3 つのレンダー コールが 1 つに置き換えられます。少し前に書いたものを、Gary Powell と Martin Weiser の View テンプレート ライブラリと組み合わせて使用する予定です。
私はそれを正しく見ていないことを知っています。訪問者は、私のアプローチを変えるのに役立ちます。
それが私がやろうとしていることです。
更新 2 OK。これまでのコメントと回答からインスピレーションを得て、ここに行きましたが、まだ終わっていません。
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(bounds, ballBehavior);
Collidable<CollisionBox> ballC(ballPhysics);
万能は正しかった。ベースを渡すことで型情報を失っていました。今のベースは、どうでもいいことをキャッチするためだけにあります。
私のコンテナでは、タイプリストを使用してコンテナに追加されたすべてのタイプを収集し、それを使用して情報を処理するタイプ固有のコンテナを宣言できると思います。ただし、関数オブジェクトを渡す方が簡単な通常のイテレータを取り出すことができないという問題があります。
おそらく、C++ 0X はその新しい未知の型変数に役立つでしょう。(名前は忘れました)。