Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape  (Lu 3919 fois)

0 Membres et 1 Invité sur ce sujet

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« le: Septembre 10, 2013, 12:34:17 pm »
Bonjour à toutes et à tous.

Je suis face à un soucis d'héritage avec la SFML 2.1.
Ci-dessous un schéma représentant ce que je voudrais mettre en place :

class AGraphObject : public sf::Drawable
|
|
class GWall : public AGraphObject, public sf::RectangleShape

Selon la doc de sf::Drawable (http://www.sfml-dev.org/documentation/2.1/classsf_1_1Drawable.php), je dois définir la fonction " virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const" dans la classe AGraphObject.
Or le tutoriel utilise un sf::Sprite (membre de la classe AGraphObject). Dans mon cas, il n'y a pas de sf::Sprite car l'objet qui doit être affiché est de type GWall.

J'ai donc pensé à faire ceci dans les .hpp :
class           AGraphObject : public sf::Drawable
{
public:
  AGraphObject(AObject *parent);
  virtual ~AGraphObject(void);

  virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const = 0;
}
 
class           GWall : public sf::RectangleShape, public AGraphObject
{
public:
  GWall(AObject *parent);
  ~GWall(void);

  virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;
};
 

Et dans le GWall.cpp
// -------------------------------------------------------------------------                                                                                                
void                    GWall::draw(sf::RenderTarget& target,
                                    sf::RenderStates states) const
{
  target.draw(*this, states);
}
 

Or à la compilation j'ai une erreur de type (avec clang++) :
client/GraphicalEngine/src/GWall.cpp:46:15: error: ambiguous conversion from derived class 'const GWall' to base class 'const sf::Drawable':
    class GWall -> sf::RectangleShape -> class sf::Shape -> class sf::Drawable
    class GWall -> class AGraphObject -> sf::Drawable
  target.draw(*this, states);
              ^~~~~
 

Quelqu'un pourrait-il m'aiguiller ?

Merci d'avoir pris le temps de lire mon post !
Cordialement.
« Modifié: Septembre 10, 2013, 12:42:27 pm par PetitPoney »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #1 le: Septembre 10, 2013, 02:24:52 pm »
Ton design est foireux : tu dérives deux fois de sf::Drawable. Du coup le compilo ne s'y retrouve pas quand il faut appeler la fonction draw : est-ce celle qui provient de AGraphObject  ou bien celle qui vient de sf::RectangleShape ?

Est-ce ta classe doit réellement hériter de l'interface publique de la classe sf::RectangleShape ? Ce n'est pas plutôt un membre servant à son implémentation ? L'héritage publique est la relation la plus forte, elle impose de nombreuses contraintes en terme de conception, il faut l'utiliser avec parcimonie.
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #2 le: Septembre 10, 2013, 02:43:59 pm »
Justement c'est un problème de design que je n'arrive pas à résoudre.

Ce que je souhaite atteindre :

Avoir une classe abstraite (AGraphObject) afin de ne manipuler qu'un seul conteneur pour mon affichage. Cependant mon AGraphObject n'est pas une classe de la SFML. Je dois donc la faire hériter de sf::Drawable et definir la fonction draw(...) pour pouvoir l'afficher.

Mais je veux également avoir des sous classes (héritant de AGraphObject, et donc de sf::Drawable), qui ont les propriétés de sf::XXXXShape.

Donc évidemment cela pose problème (multiple héritage de sf::Drawable), mais je ne vois pas vraiment comment le résoudre.

J'aurais bien utilisé des sf::Sprite, cependant je ne trouve pas ça très clean de gérer la taille des élement avec des "setScale(...)".

Merci de votre réponse si rapide !
Cordialement.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #3 le: Septembre 10, 2013, 02:51:56 pm »
Tu as vraiment besoin que ton GWall ait exactement les mêmes fonctions que sf::RectangleShape ? Tu n'as pas une API qui t'es propre, quitte à ce que certaines fonctions soient des appels directs aux fonctions de RectangleShape ?
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #4 le: Septembre 10, 2013, 03:22:24 pm »
J'ai finalement trouvé une solution à mon problème.
Je sais pas si c'est très propre mais vous pourrez me dire ce que vous en pensez.

class           AGraphObject
{
public:
  AGraphObject(AObject *parent);
  virtual ~AGraphObject(void);

  virtual void draw(sf::RenderTarget& target) const = 0;
};
 

class           GWall : public AGraphObject, public sf::RectangleShape
{
public:
  GWall(AObject *parent);
  ~GWall(void);

  virtual void draw(sf::RenderTarget& target) const;
};

void                    GWall::draw(sf::RenderTarget& target) const
{
  target.draw(*this);
}
 

Et pour le tracage :

  std::list<AGraphObject*>::iterator it = _graphObjects.begin();
  std::list<AGraphObject*>::iterator end = _graphObjects.end();

  while (it != end)
    {
      (*it)->draw(*_window);
      ++it;
    }
 

De cette manière, je n'ai pas de multi-héritage et j'utilise la méthode "draw(...)" de chaque AGraphObject au lieu de directement écrire quelque chose du genre "_window.draw(MonObjet)".
En tout cas ça compile, et ça s'affiche également  :D.

Merci pour votre aide et votre travail !

Cordialement

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #5 le: Septembre 10, 2013, 04:00:48 pm »
Ca marche, mais c'est pas terrible non plus. Là tu peux toujours écrire window.draw(wall), qui sera routé vers sf::RectangleShape::draw.

Comme ça fait 2 fois que je pose la même question et que tu ne me réponds pas, je peux pas te dire grand chose de plus pour t'aider.
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #6 le: Septembre 10, 2013, 04:17:19 pm »
Citer
Comme ça fait 2 fois que je pose la même question et que tu ne me réponds pas, je peux pas te dire grand chose de plus pour t'aider.
C'est vrai. Je vous prie de m'excuser.

Pour répondre à votre question, oui j'ai besoin que mon GWall dispose des même fonctions que les classes sf::XXXShape.
C'est justement ce que j'ai tenté d'expliquer au début du post  :-\. J'ai plusieurs sous-classes (qui héritent de AGraphObject) mais qui doivent hériter de différentes sf::XXXShape.
La classe sf::Sprite ne me convient pas car il n'est pas possible de définir une zone à couvrir sur la fenêtre (en pixel) contrairement à la classe sf::RectangleShape par exemple.

Je ne comprends pas ce que vous dites par
Citer
Tu n'as pas une API qui t'es propre ?

Cordialement.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #7 le: Septembre 10, 2013, 04:49:36 pm »
Citer
Pour répondre à votre question, oui j'ai besoin que mon GWall dispose des même fonctions que les classes sf::XXXShape.
Vraiment toutes sans exception ?? Le nom "GWall" suggère une classe de plus haut niveau, qui pourrait avoir une API plus spécifique à ce que la classe représente ; du coup l'héritage public de sf::RectangleShape paraît peu approprié ici.

SFML est une boîte à outils te permettant d'implémenter tes propres classes, pas un framework. Le fait que tu dérives publiquement d'une classe graphique (hormis celles qui sont prévues pour, sf::Drawable et sf::Transformable) soulève donc quelques questions.
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #8 le: Septembre 10, 2013, 05:29:50 pm »
Donc en gros si je résume bien je me suis complètement planté dans ma compréhension de la SFML. Pour un projet précédent, je m'étais basé sur le même principe c'est à dire : Une classe Abstraite "maîtresse" qui dérivait de sf::Sprite et plusieurs sous classes qui dérivaient de ma classe Abstraite. Ce n'était donc pas la bonne solution ?

En clair, si je veux faire une classe GWall ou GPlayer (classe uniquement destinée à faire de l'affichage), je dois partir du plus bas niveau SFML (c'est à dire sf::Drawable, sf::Transformable, etc) ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #9 le: Septembre 10, 2013, 07:02:41 pm »
Oui :)
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #10 le: Septembre 10, 2013, 07:31:20 pm »
Au moins ce topic m'aura évité de partir n'importe où et n'importe comment ! (même si j'aurais surement d'autres questions dans les jours qui viennent)  :D.
Merci beaucoup pour votre temps et vos explications !

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #11 le: Septembre 10, 2013, 08:49:01 pm »
Pour voir si j'ai bien compris le principe voilà une nouvelle base. C'est un peu près la même chose que tout à l'heure mais sans héritage WTF cette fois (je stock en tant que membre ce que je dois afficher, comme dans l'exemple de la doc).

Classe commune à tous les objets graphiques.
class           AGraphObject : public sf::Drawable
{
public:
  AGraphObject(AObject *parent);
  virtual ~AGraphObject(void);

  virtual void  draw(sf::RenderTarget &target, sf::RenderStates states) const = 0;
};
 

Une classe pour afficher un mur (d'autres seraient exactement pareil, sauf qu'elle pourrait contenir en tant que membre un sf::CircleShape par exemple).
class           GWall : public AGraphObject
{
public:
  GWall(AObject *parent);
  virtual ~GWall(void);

  virtual void  draw(sf::RenderTarget &target, sf::RenderStates states) const;

private:
  sf::RectangleShape    _objectToDraw;
};
 
void            GWall::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
  target.draw(_objectToDraw, states);
}
 

Suis-je sur la bonne voie ?

Cordialement
« Modifié: Septembre 10, 2013, 09:19:32 pm par PetitPoney »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #12 le: Septembre 10, 2013, 09:37:50 pm »
Oui, ça me paraît pas mal  ;)
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Héritage sf::Drawable / sf::RectangleShape / sf::CircleShape
« Réponse #13 le: Septembre 10, 2013, 09:42:08 pm »
C'est plus clair dans ma tête maintenant (et dans le code aussi d'ailleurs  :) ). Merci beaucoup !