Forum de la communauté SFML
Général => Suggestions de nouvelles fonctionnalités => Discussion démarrée par: L01man le Avril 27, 2012, 10:52:05 am
-
EDIT : une page sur le wiki (https://github.com/SFML/SFML/wiki/TutorialDrawableGroup) a été créée.
Je pense qu'il manque un dernier enfant à Drawable pour que la famille soit complète. Dans d'autres frameworks, comme Pygame ou Pyglet, j'ai récemment remarqué que cette classe était déjà implémentée. Avant, j'avais vite trouvé le besoin de la créer, et je pense qu'à partir d'un certain niveau d'abstraction tout le monde en a besoin.
#ifndef GROUP_INCLUDED_HPP
#define GROUP_INCLUDED_HPP
#include "Drawable.hpp"
class Group : public sf::Drawable, public std::vector<sf::Drawable*> {
public:
Group();
~Group();
void render(sf::RenderTarget&) const;
};
#endif
#include "group.hpp"
Group::Group() :
sf::Drawable(),
std::vector<sf::Drawable*>() {
}
Group::~Group() {
for(std::vector<sf::Drawable*>::iterator i = begin(); i != end(); ++i) {
delete *i;
}
}
void Group::render(sf::RenderTarget& Tar) const {
for(std::vector<sf::Drawable*>::iterator i = begin(); i != end(); ++i) {
Tar.draw(*i);
}
}
-
Ouaip, sauf qu'il y a un choix à faire quant à l'ownership des éléments, et que ce choix sera certainement différent pour chacun. Et comme la moitié du code de la classe concerne ce truc, ça ne servirait à rien d'en fournir une version officielle qui de toute façon ne satisfera jamais à 100% les gens.
-
Excuse-moi, que veux-tu dire par "ownership des éléments" ?
-
Qui prend la responsabilité de les détruire.
-
Ca serait pas plus cool d'hériter de std::vector<std::unique_ptr<sf::Drawable*>> et du coup pas de prise de tête d'ownership? (et de destructeur)
-
Je pense que hériter de std::vector est une mauvaise idée en général. Il serait mieux de garder std::vector comme membre et d'offrir quelques méthodes pour l'accès (si nécessaire).
Et lezebulon, tu veux dire std::unique_ptr<sf::Drawable> sans étoile ;)
-
Ca serait pas plus cool d'hériter de std::vector<std::unique_ptr<sf::Drawable*>> et du coup pas de prise de tête d'ownership? (et de destructeur)
Mon point n'était pas technique mais conceptuel : parfois tu voudras que le groupe prenne l'ownership des éléments, et parfois au contraire tu voudras simplement qu'il stocke des pointeurs vers des objets gérés ailleurs. On ne peut pas trancher définitivement.
-
Ah, le problème est donc Group::~Group(). Dans ce cas, on peut ajouter une variable "hasOwnership" qui détermine si, à sa destruction, le groupe détruit ses items ou non.
-
Et peut-être que quelqu'un voudra des responsabilités partagés, et donc utiliser des std::shared_ptr dans sa classe Group.
On peut toujours trouver des solutions techniques qui semblent résoudre le problème immédiat, mais si on prend du recul ça ne marche pas. Comme je l'ai déjà dit c'est un problème de conception, ça ne sert à rien d'ajouter des booléens ou autre.
-
Je vois. Pourtant, dans Pygame & cie., cette classe est bien présente et semble convenir à tous ! A vrai dire, les cas de figure qui seraient problématiques ne me viennent pas à l'esprit. On devrait les énumérer pour voir si une solution est possible. Par exemple, rendre Group abstraite pour que chacun l'implémente comme il veut ou fournir plusieurs Group qui couvrent toutes les utilisations.
En ce qui me concerne, je vois trois utilisations :- mettre ensemble les backgrounds, les tirs, ou les tiles ou autres éléments pour des calculs de collision sur leur ensemble par exemple ;
- créer des couches pour l'ordre d'affichage ;
- créer un objet complexe composé de parties articulées - des Sprite par exemple -, qui sont positionnées à partir des coordonnées de ce Group.
Dans le premier cas, le Group est sensé n'être détruit qu'à la fin du programme. Dans le deuxième, aussi. Dans le troisième, le Group est bien considéré comme un objet et pas comme un "tiroir", et ses éléments lui appartiennent. Donc, pour tous ces cas, il est normal que le Group détienne l'ownership.
On peut aussi très bien copier l'adresse d'un élément vers un autre endroit et faire un erase() pour que le Group n'ait plus cet ownership.
-
Pourtant, dans Pygame & cie., cette classe est bien présente et semble convenir à tous !
Python est un langage interprété qui possède un ramasse-miettes, il n'y a pas notion explicite d'ownership pour le programmeur.
Par exemple, rendre Group abstraite pour que chacun l'implémente comme il veut
Ca n'avancerait pas beaucoup les gens dans ce cas, ça ne ferait que leur imposer une interface figée.
ou fournir plusieurs Group qui couvrent toutes les utilisations.
Plusieurs variantes d'une classe pour une seule fonctionnalité bien spécifique, ça ferait un peu bourrin pour SFML ;)
-
D'accord x). Pourrait-on au moins en proposer une version dans les tutoriels, afin que les débutants aient une base ?
-
Pas dans les tutoriels non, mais mets-en une sur le wiki si tu veux :)
-
C'est fait. (https://github.com/SFML/SFML/wiki/TutorialDrawableGroup)
-
Pourquoi est-ce que personne ne lit jamais les règles avant de créer des pages sur le wiki ? C'est vraiment pénible >:(
Sinon :
- tu devrais indiquer que ton code est pour SFML 1.6
-- pourquoi ne pas le faire en 2.0 ? plus personne n'utilisera 1.6 bientôt
- le code de ton destructeur a trop de lignes de code pour ce qu'il fait :P
-
Désolé pour le titre. C'était pourtant un paragraphe sur l'accueil du wiki, mais peut-être pas assez visible. Il n'y a pas moyen d'afficher ce message sur la page d'édition ?
Voilà, j'ai précisé. En fait, qu'est-ce qui change, pour ce code, avec SFML 2.0 ? J'en déduis que je suis l'un des rares à encore utiliser la 1.6 :D. Je ferai bientôt le changement, alors.
Ca va mieux, pour le dtor ?
-
Il n'y a pas moyen d'afficher ce message sur la page d'édition ?
Non, malheureusement. Ce serait bien pratique en effet.
En fait, qu'est-ce qui change, pour ce code, avec SFML 2.0 ?
La classe Drawable n'est plus la même, les fonctions sont en lowerCamelCase, etc.
Ca va mieux, pour le dtor ?
Oui, mais :
- ce serait mieux avec un itérateur ;D
- le clear() est inutile, ton objet est en train d'être détruit de toute façon
-
Et voilà ! Notons quand-même qu'avec Haskell, par exemple, on écrirait simplement :
map draw group pour remplacer la méthode Draw().
-
Je suis pas sur d'avoir vraiment compris l'utilité d'une telle classe.
En gros c'est un tableau de pointeur sur ce que tu dois dessiner ?
-
Ca permet d'aggréger plusieurs entités comme étant une seule, et d'affecter une position, rotation, ... à tout le groupe, en plus des transformations individuelles des entités qui le composent.
-
EDIT : grillé
C'est ça. Mais on peut appeler Draw dessus, puisque c'est un Drawable lui-même. Ca permet de faire des
layers, de faire des corps articulés, des calculs de collisions sur un groupe précis d'objets en évitant de parcourir une liste entière d'objets, etc.
-
Ah ok, merci