Je suis en train de mettre en œuvre une sorte de moteur de jeu « juste pour-moi » et l'intrigue du problème va de la façon suivante:C++ la conception du jeu et polymorphisme question
Supposons que j'ai une interface abstraite pour une entité renderable , par exemple IRenderable
.
Et il est déclaré de la manière suivante:
interface IRenderable {
// (...)
// Suppose that Backend is some abstract backend used
// for rendering, and it's implementation is not important
virtual void Render(Backend& backend) = 0;
};
Ce que je fais est en ce moment quelque chose comme déclarant différentes classes comme
class Ball : public IRenderable {
virtual void Render(Backend& backend) {
// Rendering implementation, that is specific for
// the Ball object
// (...)
}
};
Et puis tout semble bien. Je peux facilement faire quelque chose comme std::vector<IRenderable*> items
, pousser certains articles comme new Ball()
dans ce vecteur et ensuite faire une similaire d'appel à foreach (IRenderable* in items) { item->Render(backend); }
Ok, je suppose que c'est la façon « polymorphes », mais si je veux avoir différents types de objets dans mon jeu et une capacité à manipuler leur état, où chaque objet peut être manipulé via sa propre interface?
que je pouvais faire quelque chose comme
struct GameState {
Ball ball;
Bonus bonus;
// (...)
};
puis changer facilement des objets état via leurs propres méthodes, comme ball.Move(...)
ou bonus.Activate(...)
, où Move(...)
est spécifique pour seulement Ball
et Activate(...)
- pour seulement Bonus
cas.
Mais dans ce cas, je perds l'opportunité d'écrire foreach IRenderable*
simplement parce que je stocke ces boules et bonus comme des instances de leurs classes dérivées, pas de base. Et dans ce cas, la procédure de rendu se transforme en un désordre comme
ball.Render(backend);
bonus.Render(backend);
// (...)
et il est mauvais parce que nous perdons en fait notre polymorphisme cette façon (pas de besoin réel pour la fabrication virtuelle, etc.
fonction Render
L'autre approche signifie l'invocation par dynamic_cast
ou coulée en descente quelque chose avec typeid
pour déterminer le type d'objet que vous souhaitez manipuler et cela semble encore pire pour moi et cela brise aussi ce « polymorphes » idée.
Alors, ma question est - Y a-t-il une sorte d'approche (probablement) alternative à ce que je veux faire ou mon pattern actuel peut-il être modifié de manière à stocker IRenderable*
pour mes objets de jeu (pour que je puisse invoquer la méthode virtuelle Render
sur chacun d'entre eux) tout en préservant la possibilité de changer facilement l'état de ces objets?
Peut-être que je fais quelque chose de tout à fait tort dès le début, le cas échéant, s'il vous plaît le signaler :)
Merci à l'avance!
Est-ce que quelqu'un connaît une méthode C++ efficace pour implémenter la deuxième boucle à travers ces éléments Renderable qui a pour résultat de ne trouver que le sous-ensemble des objets Movable? Soit je suis tout simplement stupide ou cela peut être fait seulement en invoquant la coulée dynamique/typeid/votre propre implémentation RTTI ... Merci pour la réponse :) –
@Kotti suffit de créer une autre liste d'entre eux. Par exemple. vous avez une liste de Renderables, une liste de Movables, une liste de Collectibles. Ensuite, chaque fois que vous voulez opérer sur un sous-ensemble, il suffit de parcourir la liste appropriée. (Encore une fois, ajoutez les Renderables à la liste de rendu dans le constructeur Renderable.) –