Ich möchte, dass der Compiler die Verbindungen der Funktionen für ein Physik-Kollisionssystem erstellt. Ich habe die Funktion test collision:
template <typename T, typename U>
inline void Collision(T& t, U& u)
{
if(u.CheckCollision(t.GetCollider()))
{
u.HitBy(t);
t.Hit(u);
}
}
Dann verwende ich ein Collider-Objekt, um das Kollisionsobjekt zu halten.
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);
}
};
Ich habe eine indirekte Ebene für die Effektfunktionen hinzugefügt
class VictimEffect
{
public:
template<typename C>
void HitBy(C&)
{;}
};
class MenaceEffect
{
public:
template<typename C>
void Hit(C&)
{;}
};
Was ich am Ende mit ist ein Weg, um Funktionen in jedem Objekt, das die richtige Funktionssignatur hat, aber nicht erfordern Typen, die nicht getroffen werden aufrufen.
class Wall;
class Ball : public MenaceEffect
{
public:
void Hit(Wall& wall);
void Hit(Ball& ball);
};
class Wall : public VictimEffect
{
public:
void HitBy(Ball& ball);
};
Beachten Sie, dass ich keine Funktion für das Auftreffen einer Wand auf eine Wand haben möchte. Ich möchte nur Funktionen für Interaktionen schreiben oder bereitstellen, die stattfinden sollen. Ich weiß, dass dies nicht funktioniert, weil der VictimEffect die abgeleitete Funktion nicht "sieht".
Ich möchte den Versand durchführen, ohne die Vorlagenparameter überall angeben zu müssen, wo sie verwendet werden. Ich möchte meinen kollidierbaren Effekt unabhängig von collidable erstellen und ihn dem collidable-Objekt generisch übergeben. Ich möchte nicht für jede Sammlung von Dingen, mit denen man kollidieren kann, ein anderes kollidierbares Objekt haben. Im Grunde möchte ich
vector<collidable> movingThings;
vector<collidable> staticThings;
// get iterators ...
Collide(Moving, Static);
Ich brauche hier mehr indirekte Ebenen, aber ich kann sie einfach nicht sehen. Ich weiß, dass es möglich ist, weil alle Informationen zur Kompilierzeit verfügbar sind. Es besteht keine Notwendigkeit für eine dynamische polymorphe Lösung.
Jede Hilfe ist sehr willkommen!
更新情報 Ich versuche, meine eigene moderne (wie in Andrei's Buch) Spielebibliothek aufzubauen. Bis jetzt habe ich die meisten Beziehungen geklärt, aber bei diesem Spiel bin ich ratlos. Dies ist kein zeitkritisches Problem, sondern eher ein ergebniskritisches Problem. Ich arbeite seit vielen, vielen Jahren an Spielen und ich mag keine der Spiel-Engines, an denen ich gearbeitet habe. Diese Engine soll einfach zu benutzen und leicht zu erweitern sein. Sie wird auf jeder Plattform funktionieren, da die Konsolen-Compiler nicht mehr so schlecht sind.
Hier ist ein einfaches Beispiel dafür, was ich schreiben können möchte.
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();
}
}
Die gesamte Physik ist WIP und ist nicht dort, wo ich sie haben möchte, aber sie ist auf dem Weg dahin. Das System-Objekt initialisiert Windows und den plattformspezifischen Renderer. In diesem Fall ist es OpenGL. Es erstellt alle Windows-Komponenten, obwohl es als Konsolenanwendung kompiliert ist. Ich wollte nicht, dass sich die Leute mit main() vs winmain() beschäftigen. Außer bei Physics gibt es keine Vererbung. Die drei Render-Aufrufe werden durch einen ersetzt, sobald ich Scenes in das System integriert habe. Ich habe vor, etwas zu verwenden, das ich vor einiger Zeit geschrieben habe, kombiniert mit der View Template Library von Gary Powell und Martin Weiser.
Ich weiß, dass ich es einfach nicht richtig anschaue. Der Besucher könnte mir helfen, meinen Ansatz zu ändern.
Das ist es, was ich zu tun versuche.
Aktualisierung 2 GUT. Ich habe mich von den Kommentaren und Antworten inspirieren lassen und bin zu diesem Punkt gekommen, aber ich bin noch nicht fertig.
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);
}
};
Um sie zu verwenden, muss ich dann Folgendes tun
Collidable<Boundary, BallCommand> boundC(bounds, ballBehavior);
Collidable<CollisionBox> ballC(ballPhysics);
Omnifarious hatte Recht. Ich habe die Typinformationen verloren, indem ich die Basis einfügte. Jetzt ist die Basis nur noch dazu da, um Dinge aufzufangen, die mir egal sind.
Ich denke, dass ich für meinen Container eine Typenliste verwenden kann, um jeden Typ, der dem Container hinzugefügt wird, zu sammeln, und diese verwenden kann, um typspezifische Container zu deklarieren, die dann Informationen verarbeiten. Ein Haken ist allerdings, dass ich keine normalen Iteratoren verwenden kann, es wäre einfacher, Funktionsobjekte zu übergeben.
vielleicht kann C++ 0X bei dieser neuen Variablen unbekannten Typs helfen. (Ich habe vergessen, wie sie heißt).