IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

[C++] Utilisation du pattern strategie (ou pont)


Sujet :

C++

  1. #1
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut [C++] Utilisation du pattern strategie (ou pont)
    Bonjour

    J'ai deux choses � demander ^^

    1�re chose :

    J'ai �tudi� le pattern Strategie gr�ce au livre "Design Pattern - Tete la Premi�re". Cependant, quelque chose me chiffonne quand je parcours le Web et quand j'ai d�couvert le pattern Bridge (pont) qui ressemble beaucoup au pattern strat�gie :
    Le pont est un pattern Strcucturel:
    - Pont: S�pare une abstraction de son impl�mentation de sorte que les deux puissent varier ind�pendamment.

    Le strat�gie est un pattern comportemental:
    - Strat�gie: D�finit une famille d'algorithmes, encapsule chacun, et les rend interchangeables. La Strat�gie permet � un algorithme de varier ind�pendamment des clients qui l'utilisent.
    Maintenant, dans le livre pour le pattern Strat�gie, j'ai l'impression que c'est un mixte du pattern Pont et Strategie. Voil� le diagramme UML en pi�ce jointe.

    Voil� je voulais votre avis sur la question

    2�me chose :

    Je souhaiterais appliquer l'un des deux patterns (je pense le Strategie) � ma situation dans mon jeu 2D :
    Soit les interfaces IEntity, ISprite ainsi que des interfaces *Behaviours

    • La classe Player et Enemy d�rivent de l'interface IEntity.
    • La classe AnimatedSprite et ClassicalSprite d�rivent de l'interface ISprite.
    • IEntity est compos� d'un ISprite (composition) et d'interfaces de Behaviours (non impl�ment�es encore).
    • La classe World (qui g�re le monde en entier) poss�de un ensemble d'entit�s (dans un vector pour l'instant).


    Donc gr�ce au polymorphisme je peux mettre � jour et dessiner toutes mes entites en parcourant le vector.

    Pas de probl�me jusqu'� la

    MAIS si je veux rajouter dans les classes Player et Enemy des attributs sp�cifiques voires des m�thodes sp�cifiques, je ne pourrais jamais les invoquer � partir de World (car il ne manipule que des IEntity).

    De m�me, les Behaviours vont devoir manipuler des attributs des classes Player, Enemy par exemple quand un ennemie va perdre de la vie, il faudra bien baisser son attribut heath (qui sera priv� dans la classe Enemy).

    Pour �tre plus clair, prenons un exemple de Behaviours : IColissionBehaviour (celui qui g�re les collisions entre les entit�s). Imaginons une classe HitBehaviour qui impl�mente (d�rive en C++) de IColissionBehaviour.
    La classe HitBehaviour � besoin de connaitre des infos sur toutes les Entity qui impl�mentent ce comportement !

    Et hop, je suis coinc� !! Je ne vois pas comment faire...

    J'ai vraiment besoin d'aide, je n'arrive plus � avancer dans mon design

    Merci en tout cas, et bonne vacances
    Images attach�es Images attach�es  
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  2. #2
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par d�faut
    Bonjour � toi.

    Sur "bridge vs strategy" d'abord.
    * Premi�re diff�rence : leur but. L'un (bridge) est un pattern structurel et concerne donc la fa�on dont ton programme est �crit, tandis que l'autre (strategy) est un pattern comportemental qui concerne la fa�on dont ton programme s'ex�cute. Typiquement, la strat�gie utilis�e par un objet est appel�e � varier au cours de l'ex�cution alors qu'on utilisera plut�t bridge pour une impl�mentation choisie au d�marrage.
    * Seconde diff�rence : typiquement, avec "bridge", l'abstraction est presque enti�rement b�tie par-dessus cette impl�mentation et offre souvent une interface proche de cette derni�re. A l'inverse, une strat�gie est plut�t une partie seulement de son consommateur. Dans ton cas, tu as ainsi plusieurs familles de strat�gie par client, et ce dernier assure aussi d'autres services qui ne d�pendent d'aucune strat�gie.
    * Troisi�me diff�rence : le couplage est typiquement plus fort avec le pattern "strategy". Dans le cas de figure o� "bridge" est utiliser pour s'interfacer avec diff�rents SGBD, on peut �crire autant d'impl�mentations que l'on veut sans rien changer � l'abstraction. A l'inverse, si tu �cris une strat�gie pour une AI en mode berserk, tu as alors besoin de modifier ton client pour ajouter un code de s�lection de l'AI berserk.



    Sur la 2nde partie.
    * Pourquoi World aurait-il besoin de manipuler les attributs sp�cifiques � certaines classes ? Si des traitements requi�rent une connaissance d�taill�e de ces classes, ils doivent �tre effectu�s par ces classes en question et non pas par World. Cf. le Dependency Inversion Principle.

    * Sur le reste, je ne pourrais pas t'aider davantage sans savoir de quel type de jeu il s'agit mais, grosso modo, je dirais que tu dois d�finir des interfaces additionnelles (IHasHealth pour donner un probablement mauvais exemple) ainsi qu'une fa�on de savoir si un objet en question impl�mente telle ou telle interface. HitBehaviour n'aura ainsi besoin que de manipuler une certaine interface et n'aura pas besoin de conna�tre tous les d�tails de l'objet. Alternativement, ces interfaces pourraient �tre impl�ment�es par les comportements eux-m�mes plut�t que par les entit�s.

  3. #3
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Merci pour ta r�ponse, donc il s'agit bien d'une strat�gie dans mon livre

    Donc en fait, je fais un remake de Zelda en 2D :
    http://www.developpez.net/forums/d98...ake-zelda-gbc/

    En fait, j'ai du mal � me dire si je dois s�parer le Player (qui est une entit� puisqu'il a un Sprite et des Behaviours) des autres entit�s car un Player est un peu sp�cial, contrairement aux autres entit�s (porte, trou, panneau, ennemies, murs, objets...) il se d�place gr�ce au joueur et il poss�de un inventaire qui lui m�me poss�de des armes.

    Donc, faut-il faire h�rit� Player de IEntity ou le g�rer � part ? Ou mettre la classe Inventory et Item et comment les lier ?
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  4. #4
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par d�faut
    Voil� un projet bien sympathique.

    Commen�ons par le point le plus simple : je pense que l'inventaire devrait effectivement �tre totalement ind�pendant, je ne vois aucune raison pour en faire un sous-�l�ment de Link. Qui plus est pas besoin d'une classe item : l'inventaire devra simplement avoir des membres "numBombes", "numFl�ches", etc, ce sera plus facile � g�rer. Le seul cas o� un item devrait avoir une instance associ�e ce sera une entit� dans le cas o� il est par terre, attendant d'�tre ramass�.

    Maintenant, sur la question de savoir si Link doit �tre trait� comme une entit� comme les autres, ma r�ponse est positive quand je regarde ce qui les unit :
    * AI : le contr�le par le joueur n'est qu'une forme d'AI. Tous auront besoin de services communs comme "puis-je aller en (x, y) ?"
    * Collisions. Les r�actions (comportements) seront diff�rentes mais, fondamentalement, les m�canismes sont les m�mes. On a des collisions joueur-projectile, ennemi-projectile, joueur-mur, ennemi-mur, joueur-ennemi et m�me ennemi-ennemi (si on pense � ces statues amovibles : si on en d�place une elle peut pousser un monstre).
    * Comportements communs : par exemple une projection en arri�re suite � un coup, dur�e pendant laquelle l'AI ou le joueur ne peuvent rien faire. Ou le gel des AI et de Link lors d'une transition d'�cran.
    * Gestion de la vie et d�tection de la mort.

    A mes yeux �a fait beaucoup de choses en commun alors que les diff�rences peuvent tr�s bien �tre g�r�es par des comportements diff�rents.

    A priori je partirais sur une hi�rarchie de base de la sorte :
    Entity (avec entre autres propri�t�s IsMovable, IsItem, IsSpiky, IsPlayer, IsCreature)
    * Movable (statues d�pla�ables : comportements identiques, seul le graphisme change)
    * Item (bombes, f�es, etc : service d'instanciation rapide, comportements identiques)
    * Spiky (contient notamment un flag de faction IsLinkSided et des dommages au contact)
    ** Projectile (fl�ches, boules de feu, rochers qui tombent, etc)
    ** Killable (contient notamment des PV)
    *** Player
    *** Creature

  5. #5
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Salut,

    Il t'est tout � fait possible de consid�rer ton joueur comme �tant une entit� pour tout ce qui a trait � la gestion "classique" de ton joueur en tant que tel (tout ce qui a trait � l'affichage, va-t-on dire )

    Par contre, tu devras, de toutes mani�res, g�rer ton (tes) joueur(s) comme... des joueurs pour toute une s�rie de situations (tout ce qui a trait � son (leur) d�placement, ses (leurs) actions, sa (leur) "vie dans le monde", ... )

    Il faudra donc, quitte � "enregistrer" ton joueur comme �tant une entit� � afficher, pr�voir toute un syst�me de gestion du joueur en tant que tel!

    Ce syst�me de gestion du joueur s'occupera, entre autres, de la gestion des �v�nements de l'utilisateur, et les diff�rents h�ritages n'auront sans doute meme pas � intervenir � ce niveau

    Pour ce qui est de l'inventaire, un raisonnement similaire peut parfaitement etre suivi:

    Rien ne t'emp�che de consid�rer ton inventaire comme �tant une entit� affichable et de le g�rer en tant que tel pour tout ce qui a trait � l'affichage, mais, d'un autre cot�, il faudra le g�rer en tant qu'inventaire pour toute une s�rie de situation.

    La responsabilit� de l'inventaire sera, d'ailleurs, la gestion des objets qu'il contient (il agira comme une collections d'objets )

    Ce qui tombe bien, c'est que l'on peut estimer que, chaque joueur ayant son propre inventaire, on peut estimer que c'est un candidat id�al pour lui d�l�ger la gestion de celui-ci

    En r�alit�, une bonne partie de la gestion de l'inventaire en tant que tel sera sans doute d�l�gu�e au syst�me d'�v�nements de celui-ci, �tant donn� que beaucoup d'actions effectu�es par le joueurs auront trait � la gestion de l'inventaire
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  6. #6
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    D'accord, j'ai impl�ment� le Player comme �tant une entit� tout comme un ennemie (donc Player et Enemy h�ritent de IEntity).

    Voici un diagramme fait � la main (tr�s moche d�sol�) :
    http://www.tutoworld.com/temp/uml_zelda.jpg

    Citation Envoy� par koala01 Voir le message
    Par contre, tu devras, de toutes mani�res, g�rer ton (tes) joueur(s) comme... des joueurs pour toute une s�rie de situations (tout ce qui a trait � son (leur) d�placement, ses (leurs) actions, sa (leur) "vie dans le monde", ... )

    Il faudra donc, quitte � "enregistrer" ton joueur comme �tant une entit� � afficher, pr�voir toute un syst�me de gestion du joueur en tant que tel!
    Justement en faisant h�riter Player de IEntity, vu que le World ne manipule que des IEntity, je ne pourrais jamais appeler des m�thodes ou avoir acc�s � des attributs propre � la classe Player, d'o� mon probl�me.

    Voil� les classes (simplifi�es) :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    class World
    {
        private:
            std::vector<IEntity*> entities; // ensemble des entités de la zone de jeu
            Core::XmlManager* pXmlManager; // gestion du fichier xml de config du jeu
     
            IVect2D pos; // position de la zone dans la map courante
            int idCurrent; // id de la zone courante dans la map courante
            int idCurrentMap; // id de la map courante (une map contient plusieurs zones)
            int idCurrentMask; // id du masque correspondant à la map courante
     
        public:
            World();
            ~World();
     
            bool load();
            bool draw(const Core::IRenderer& r);
            bool update(int direction, int buttons);
    };
     
    // implémentation de la classe World :
    World::World()
    {
    .....
    }
     
    World::~World()
    {
    ....
    }
     
    bool World::load()
    {
        int idTemp = LOAD_FAILED;
     
    // des chargements
    ....
     
        idCurrentMap = IM->loadImage("data/map/overworld/1.bmp", false);
        idCurrentMask = IM->loadImage("data/map/overworld/1m.bmp", false);
     
        // chargement du sprite via le ImageManager
        idTemp = IM->loadImage("data/link_mouvement.bmp");
     
        // création d'un sprite
        if (idTemp != LOAD_FAILED)
        {
            AnimatedSprite* aS = new AnimatedSprite(
                IM->getImageSizeById(idTemp),
                IVect2D(100,10), idTemp, USize2D(16*3,16*3), true, 10);
     
            Player* p = new Player(aS);
     
            idTemp = IM->loadImage("data/1.bmp", true);
     
            AnimatedSprite* cS = new AnimatedSprite(
                IM->getImageSizeById(idTemp),
                IVect2D(100,10), idTemp, USize2D(16,16), false, 10);
     
            Enemy* e = new Enemy(cS);
     
            entities.push_back(e);
            entities.push_back(p);
     
            return true;
        }
        else return false;
    }
     
    bool World::draw(const Core::IRenderer& r)
    {
        bool bOk = true;
     
        // dessine le terrain
        //r.drawSurface(idCurrentMap, IVect2D(0,16), Rect(pos, USize2D(320, 256)));
     
        std::vector<IEntity*>::const_iterator it;
        for (it = entities.begin(); it != entities.end(); ++it)
        {
            bOk &= (*it)->draw(r);
        }
     
        return bOk;
    }
     
    bool World::update(int direction, int buttons)
    {
        bool bOk = true;
     
        std::vector<IEntity*>::const_iterator it;
        for (it = entities.begin(); it != entities.end(); ++it)
        {
            bOk &= (*it)->move(direction);
            bOk &= (*it)->update(direction, buttons);
        }
     
        return bOk;
    }
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class ISprite
        {
            protected:
                USize2D size; // sa taille
                IVect2D pos; // sa position
                int idImage; // son image
                int currentDir; // direction courante (haut, bas, gauche ou droite) du sprite
     
            public:
                ISprite(USize2D _size, IVect2D _pos, int _idImage) : size(_size), pos(_pos), idImage(_idImage), currentDir(0) {};
                virtual ~ISprite() {};
     
                virtual bool update(int direction, int buttons) = 0;
                virtual bool draw(const IRenderer& r) = 0;
     
                IVect2D getPos() const { return pos; }
                USize2D getSize() const { return size; }
                int getIdImage() const { return idImage; }
     
                void setPos(int x, int y) { pos = IVect2D(x,y); }
                void setDir(int dir) { currentDir = dir; }
        };
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    class IEntity
    {
        protected:
            Core::ISprite* pSprite; // pointeur sur son sprite
            IMoveBehaviour* pMoveBehaviour; // pointeur sur son type de déplacement
            bool bVisible;
     
        public:
            IEntity(Core::ISprite* _pSprite)
                : pSprite(_pSprite), bVisible(false)
            {
            };
     
            virtual ~IEntity() { delete pSprite; delete pMoveBehaviour; };
     
            virtual bool update(int directions, int buttons)
            {
                pSprite->update(directions, buttons);
                return true;
            }
     
            bool move(int directions)
            {
                return pMoveBehaviour->onMove(*pSprite, directions);
            }
     
            bool draw(const Core::IRenderer& r)
            {
                return pSprite->draw(r);
            }
    };
    1�re question : Est ce que cela choque (ou brise un des principes OO) de passer une r�f�rence du Sprite dans le "MoveBehaviour" ? car pour effectuer un d�placement, j'ai besoin d'avoir acc�s � des attributs du sprite...

    Interface IMoveBehaviour et ses 3 impl�mentations :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    // Interface IMoveBehaviour
    class IMoveBehaviour
    {
        private:
     
        public:
            IMoveBehaviour() {};
            virtual ~IMoveBehaviour() {};
     
            virtual bool onMove(Core::ISprite& pSprite, int directions) = 0;
     
    };
     
    // pas de déplacement : entité immobile
    class NoMoveBehaviour
        : public IMoveBehaviour
    {
        private:
     
        public:
            NoMoveBehaviour() {};
            ~NoMoveBehaviour() {};
     
            bool onMove(Core::ISprite& pSprite, int directions)
            {
                (void) pSprite;
                (void) directions;
     
                return true;
            }
    };
     
    // déplacement manuel : le Player avec son clavier ou son joystick
    class ManualMoveBehaviour
        : public IMoveBehaviour
    {
        private:
     
        public:
            ManualMoveBehaviour() {};
            ~ManualMoveBehaviour() {};
     
            bool onMove(Core::ISprite& pSprite, int directions)
            {
                int tempX = pSprite.getPos().x;
                int tempY = pSprite.getPos().y;
                int dirTmp = 0;
     
                // si on appuie sur une direction
                if (directions != Core::InputManager::D_NONE)
                {
                    if (Core::InputManager::isPressed(directions, Core::InputManager::D_RIGHT))
                    {
                        tempX++;
                        dirTmp= 2;
                    }
                    if (Core::InputManager::isPressed(directions, Core::InputManager::D_LEFT))
                    {
                        tempX--;
                        dirTmp = 0;
                    }
                    if (Core::InputManager::isPressed(directions, Core::InputManager::D_UP))
                    {
                        tempY--;
                        dirTmp = 3;
                    }
                    if (Core::InputManager::isPressed(directions, Core::InputManager::D_DOWN))
                    {
                        tempY++;
                        dirTmp = 1;
                    }
     
                    // controles des bords simples pour l'instant
                    if (tempX >= 0 && tempY >= 0 && tempX < SCREEN_W && tempY < SCREEN_H)
                    {
                        // on set la nouvelle position
                        pSprite.setPos(tempX, tempY);
                    }
     
                    pSprite.setDir(dirTmp);
                }
     
                return true;
            }
    };
     
    // déplacement automatique : IA pour les ennemies par exemple
    class AutoMoveBehaviour
        : public IMoveBehaviour
    {
        private:
            int tempAlea;
            int dirTmp;
     
        public:
            AutoMoveBehaviour() {};
            ~AutoMoveBehaviour() {};
     
            bool onMove(Core::ISprite& pSprite, int directions)
            {
                (void)directions;
     
                int tempX = pSprite.getPos().x;
                int tempY = pSprite.getPos().y;
     
                // sélection de la direction aléatoirement
                // si il a choisie une direction,
                // il doit avancer de 2 carrés au moins soit 2*16 pixels
                if (tempAlea >= 2*16)
                {
                    tempAlea = 0;
     
                    // choisie une nouvelle direction
                    dirTmp = rand()%4;
                }
     
                if (dirTmp == 0) tempX--;
                if (dirTmp == 1) tempY++;
                if (dirTmp == 2) tempX++;
                if (dirTmp == 3) tempY--;
     
                // controles des bords simples pour l'instant
                if (tempX >= 0 && tempY >= 0 && tempX < SCREEN_W && tempY < SCREEN_H)
                {
                    pSprite.setPos(tempX, tempY);
                    pSprite.setDir(dirTmp);
                    tempAlea++;
                }
                else // de même si il sort de l'écran
                {
                    tempAlea = 2*16;
                }
     
                return true;
            }
    };
    2�me question : Etant donn� que j'utilise une map "masque" pour savoir si une entit� peut se d�placer ou pas (exemple : couleur blanc = sol, couleur rouge = murs, bleu = trou...), vais-je �tre obliger passer l'identifiant de cette map en param�tre depuis IEntity jusqu'� *MoveBehaviour ?

    3�me question : Maintenant, le probl�me que j'ai c'est pour g�rer les collisions, �tant donn� que j'ai besoin de savoir pour l� d�placement des entit�s si j'ai des collisions ou pas (avec un murs, une autre entit�, un trou ou autre), comment vais-je faire ?

    J'aurais vraiment besoin d'un coup de pouce pour me d�bloquer

    Merci
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  7. #7
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par d�faut
    Petite remarque pr�liminaire : justement, ce n'est pas � World de d�placer le joueur.
    Pour ma part je te recommande de cr�er un PlayerBehaviour qui se substituera � l'IA pour la classe Player. D'autre part, ta fen�tre devrait mettre � jour � chaque frame une classe "Controller" dans laquelle seront stock�s les �tats des diff�rents boutons (A, B, haut, bas, etc... Vrai si press� durant la frame, faux sinon). PlayerBehaviour n'interagira qu'avec Controller et aura la responsabilit� de d�placer Link en fonction des boutons press�s. Controller est un singleton avec un membre statique exposant l'unique instance.
    Note : si le fps est faible, mieux vaut envisager une variante qui prendrait en compte la dur�e pendant laquelle le bouton a �t� press�, la pompe � messages �tant alors dans un thread de plus haute priorit�.

    1./ Ce qui serait pr�f�rable � mon avis c'est qu'Entity ait lui-m�me une position et qu'il mette � jour la position de Sprite au d�but de draw (le syst�me de coordonn�es des deux positions peut �tre diff�rent d'ailleurs). Il n'y aurait aucun probl�me � passer ton entit� en argument � tes comportements (un comportement n'est coupl� qu'aux classes entit�s de base, sauf peut-�tre les comportements tr�s sp�cifiques li�s � une classe-entit� sp�cifique).

    2./ Ta carte devrait selon moi �tre encapsul�e dans un singleton Map (ou un singleton ScreenMap pour une carte born�e � l'�cran visible) afin d'�viter d'avoir � la passer sans cesse.

    3./ Si tu fais un d�placement au pixel pr�s, Entity doit typiquement exposer un getter pour un bounding rectangle. Si tu te contentes d'un d�placement par case (je ne parle pas de l'animation qui sera toujours au pixel pr�s, je parle du fait de savoir si une pression infime sur la touche "haut" fait d�placer Link d'un pixel ou amorce un glissement d'une case), la position suffit.
    Note1 : en r�alit�, je viens de r�aliser que le sprite de Link, par exemple, grandit quand il frappe. Donc il faut dans tous les cas exposer un bounding rectangle.
    Note2 : une entit� peut �tre compos�e de plusieurs sprites, attention.
    Note3 : retour sur la note 1, un contact avec l'�p�e n'est pas identique � un contact avec le corps. Du coup, une entit� doit exposer plusieurs rectangles de collisions avec chacun un comportement diff�rent.

    Maintenant, pour le d�tail, chaque entit� va d'abord scanner les autres entit�s pour voir si l'une d'elle est en collision. Vu le peu d'entit�s, la force brute conviendra tr�s bien. Quant aux collisions avec les murs, il faut pour �a interroger la map et cela peut �tre fait � plusieurs moments et de plusieurs fa�ons (soit on v�rifie � chaque d�placement envisag� s'il est licite, soit on stocke les d�placements envisag�s sans v�rifier et, juste avant le dessin, on r�alise le d�placement avec les �ventuelles corrections n�cessaires : annulation, rebond, changement d'orientation, etc).
    Note : un cas int�ressant � consid�rer est celui d'un serpent compos� de plusieurs sprites qui bute contre un mur et rebrousse chemin.

    Autre chose � trancher : les collisions sont-elles d�tect�es deux fois (A d�tecte sa collision avec B et ce dernier en fait de m�me de son c�t�), ou bien une seule fois, ce qui implique dans ce cas une forme de n�gociation entre A et B pour savoir lequel des deux effectue le traitement (typiquement on commence avec l'un des deux, qui passe ou non le relais � l'autre) ?

    EDIT : Ajout de notes importantes.

  8. #8
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Citation Envoy� par DonQuiche Voir le message
    Petite remarque pr�liminaire : justement, ce n'est pas � World de d�placer le joueur.
    C'est � qui alors ?
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    bool World::update(int direction, int buttons)
    {
        bool bOk = true;
    
        std::vector<IEntity*>::const_iterator it;
        for (it = entities.begin(); it != entities.end(); ++it)
        {
            bOk &= (*it)->move(direction);
            bOk &= (*it)->update(direction, buttons);
        }
    
        return bOk;
    }
    Avec le polymorphisme, je ne vois que cette classe capable de d�placer toutes les entit�s.

    Citation Envoy� par DonQuiche Voir le message
    Pour ma part je te recommande de cr�er un PlayerBehaviour qui se substituera � l'IA pour la classe Player. D'autre part, ta fen�tre devrait mettre � jour � chaque frame une classe "Controller" dans laquelle seront stock�s les �tats des diff�rents boutons (A, B, haut, bas, etc... Vrai si press� durant la frame, faux sinon). PlayerBehaviour n'interagira qu'avec Controller et aura la responsabilit� de d�placer Link en fonction des boutons press�s. Controller est un singleton avec un membre statique exposant l'unique instance.
    Note : si le fps est faible, mieux vaut envisager une variante qui prendrait en compte la dur�e pendant laquelle le bouton a �t� press�, la pompe � messages �tant alors dans un thread de plus haute priorit�.
    En fait, j'ai d�j� un manager des Inputs (je n'ai pas fourni le code car y'en avait d�j� assez) et l'�tat des touches sont stock�es dans les param�tres "directions" pour les fl�ches de direction et "buttons" pour les boutons. L'�tat des Inputs sont pass�s aux m�thodes Update() de chaque classe. Sinon je n'ai pas compris, l'histoire de ton PlayerBehaviour (un petit exemple ^^) ?
    Citation Envoy� par DonQuiche Voir le message
    1./ Ce qui serait pr�f�rable � mon avis c'est qu'Entity ait lui-m�me une position et qu'il mette � jour la position de Sprite au d�but de draw (le syst�me de coordonn�es des deux positions peut �tre diff�rent d'ailleurs). Il n'y aurait aucun probl�me � passer ton entit� en argument � tes comportements (un comportement n'est coupl� qu'aux classes entit�s de base, sauf peut-�tre les comportements tr�s sp�cifiques li�s � une classe-entit� sp�cifique).
    Alors la position est stock�e dans l'interface ISprite (attribut "pos") car pour moi une Entity n'a qu'a seul sprite donc sa position est donn�es par celle de son sprite.

    Sinon m�me faire un :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    virtual bool onMove(Entity& entity, int directions) = 0;
    puis un :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
     
    bool move(int directions)
    {
        return pMoveBehaviour->onMove(*this, directions);
    }
    n'est pas choquant ? Je ne sais pas mais le "this" ne m'inspire pas confiance ^^
    Citation Envoy� par DonQuiche Voir le message
    2./ Ta carte devrait selon moi �tre encapsul�e dans un singleton Map (ou un singleton ScreenMap pour une carte born�e � l'�cran visible) afin d'�viter d'avoir � la passer sans cesse.
    Alors dans un Zelda, c'est un peu plus compliqu�, on a une grande MAP et on scrolle de zone en zone. Donc, j'ai d�cid� de cr�er une MAP de type Plaine (par exemple) qui contient 6 zones (2 lignes et 3 colonnes). Si la zone visible (l'�cran) fait 100*100 pixels pour simplifier alors la MAP PLAINE fera 3*100 = 300 par 2*100 = 200 pixels.

    Justement je me demandais comment j'allais g�rer le scroll donc si je cr�� un singleton MapLoader(), je ne vois pas trop quoi mettre comme m�thodes pour g�rer le scroll (sachant que pour scroller donc changer de zone, il faut connaitre le sprite de la zone actuelle et celui de la nouvelle zone !)
    Citation Envoy� par DonQuiche Voir le message
    3./ Si tu fais un d�placement au pixel pr�s, Entity doit typiquement exposer un getter pour un bounding rectangle. Si tu te contentes d'un d�placement par case (je ne parle pas de l'animation qui sera toujours au pixel pr�s, je parle du fait de savoir si une pression infime sur la touche "haut" fait d�placer Link d'un pixel ou amorce un glissement d'une case), la position suffit.
    Note1 : en r�alit�, je viens de r�aliser que le sprite de Link, par exemple, grandit quand il frappe. Donc il faut dans tous les cas exposer un bounding rectangle.
    Note2 : une entit� peut �tre compos�e de plusieurs sprites, attention.
    Note3 : retour sur la note 1, un contact avec l'�p�e n'est pas identique � un contact avec le corps. Du coup, une entit� doit exposer plusieurs rectangles de collisions avec chacun un comportement diff�rent.
    Alors de toute mani�re, je fonctionne avec des masques donc les collisions se font au pixels pr�s, de m�me pour les d�placements. D'o� la n�cessit� d'avoir acc�s au masque de la zone courante dans mon ManualMoveBehaviours et AutoMoveBahaviour.

    Je n'ai pas compris aussi l'histoire de l'�p�e de Link, pour moi l'�p�e sera une autre entit� qui sera cr�� pour quelques frames dans le World et une fois le coup fini elle disparaitra.
    Citation Envoy� par DonQuiche Voir le message
    Maintenant, pour le d�tail, chaque entit� va d'abord scanner les autres entit�s pour voir si l'une d'elle est en collision. Vu le peu d'entit�s, la force brute conviendra tr�s bien.
    Je suis d'accord mais comment le faire justement, c'est l� ou je bloque, je suis sur que c'est d�bile (un parcours de vector et un appel au ICollisionBehaviours des entit�s mais je bloque vraiment). Je dois �tre trop fatigu�...
    Je ne sais pas m�me quelles impl�mentations de l'interface ColissionBehaviours cr�er pour mon Zelda, ca craint
    Citation Envoy� par DonQuiche Voir le message
    Quant aux collisions avec les murs, il faut pour �a interroger la map et cela peut �tre fait � plusieurs moments et de plusieurs fa�ons (soit on v�rifie � chaque d�placement envisag� s'il est licite, soit on stocke les d�placements envisag�s sans v�rifier et, juste avant le dessin, on r�alise le d�placement avec les �ventuelles corrections n�cessaires : annulation, rebond, changement d'orientation, etc).
    J'opte plus pour la m�thode 1, c'est plus facile de v�rifier directement avec le masque si le d�placement est licite plutot que de le stocker et v�rifier plus tard.
    Citation Envoy� par DonQuiche Voir le message
    Note : un cas int�ressant � consid�rer est celui d'un serpent compos� de plusieurs sprites qui bute contre un mur et rebrousse chemin.
    Encore une fois, pour moi le serpent est un seul Sprite car m�me si il est compos� de plusieurs petits sprites, on peut tr�s bien d�cider d'en faire une seule image et donc une Entity = un Sprite = une position unique et une taille unique.
    Apr�s peut �tre que j'ai compl�tement tord, je ne dis pas le contraire
    Citation Envoy� par DonQuiche Voir le message
    Autre chose � trancher : les collisions sont-elles d�tect�es deux fois (A d�tecte sa collision avec B et ce dernier en fait de m�me de son c�t�), ou bien une seule fois, ce qui implique dans ce cas une forme de n�gociation entre A et B pour savoir lequel des deux effectue le traitement (typiquement on commence avec l'un des deux, qui passe ou non le relais � l'autre) ?
    Bonne question, je dirais qu'il est important de faire les collisions dans les deux sens. A entre en collision avec B donc A effectue le traitement mais B doit surement effectuer un autre traitement. Exemple : Link avec Ennemi => Link doit perdre de la vie et reculer, l'Ennemie quand � lui ne dois rien faire (peut �tre arr�ter d'avancer pendant quelques frames).
    Autre exemple : Ep�e de Link avec Ennemie, cette fois c'est l'Ennemie qui pert de la vie et recule et l'�p�e continue sa vie (et disparaitra � la fin de son animation).
    Donc faire les tests de collision dans les deux sens me semble appropri� ^^
    Encore une fois, je suis naze en conception, c'est pour ca que j'ai besoin de votre aide justement

    C'est bien beau tout cas, si seulement j'avais une once d'id�e d'impl�mentation
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  9. #9
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    En fait, il y a un probl�me de conception d�s le d�part...

    Pour bien pouvoir r�fl�chir en terme de conception OO, tu dois te demander, pour chaque classe, les services que tu es en droit d'en attendre.

    Cela implique un pr�requis tr�s important : savoir quelle responsabilit� tu va donner � tes classe, dans le respect absolut d'un principe simple : celui de la responsabilit� unique.

    En gros, on s'attendrait presque que la plupart de tes classes soient capables de faire le caf� ou de commander le souper au chinois du coin tellement elles ont de responsabilit�s, et ca, c'est le meilleur moyen de foncer dans le mur

    Il faut vraiment te dire que si une classe a plus d'une responsabilit�, c'est qu'elle en a (beaucoup) trop

    Tu te dis que ton monde est peupl� d'entit�s soit...

    Mais pose toi la question de savoir quels services tu attends de ton monde et de tes entit�s (pour ne parler que de ces deux classes pour commencer )

    On pourrait dire que le propre d'une entit� est d'�tre affich�e (par exemple)

    Elle n'aurait que faire de sa position r�elle, elle s'en fout tout � fait... Le syst�me de trac� se positionne � un endroit donn� (celui auquel se trouve l'entit� � tracer) et demande � l'entit� de se tracer, point barre.

    Mais, s�mantiquement parlant, on ne s'attend pas � ce qu'un monde se charge de tracer quoi que ce soit: un monde contient un certain nombre d'entit�s et permet de d�terminer la position de chacune d'elles par rapport aux autres et par rapport � un r�f�rentiel donn�, c'est tout

    Etant donn� que tu subdivise le monde en six zones distinctes, si l'on consid�re qu'il connait la position de l'ensemble des entit�s qui se trouvent dans les six zones, on s'attend en priorit� � ce qu'il puisse nous donner:
    • L'ensemble des entit�s se trouvant dans une zone donn�e
    • La position d'une entit� donn�es par rapport � un r�f�rentiel repr�sentant la coordonn�e 0,0 de la zone dans laquelle se trouve cette entit�
    Ces deux type d'informations seront, par exemple, utils�s d'un cot� par le syst�me de trac� ou le syst�me de d�tection des collisions pour leur travail respectif

    A partir de l�, on peut, effectivement, se dire que toute chose devant �tre affich�e peut etre consid�r�e comme une entit�, et que nous avons donc des entit�s particuli�res telles que sprites, ennemis, joueur, objet d'inventaires ou autres

    Chacun de ses type particulier d'entit� aurait une responsabilit� propre, et sera, par cons�quent, utilis� (en dehors de tout aspect rattach� � l'affichage ou � la gestion des collisions) de mani�re diff�rente.

    Mais, cela sous entend que, bien que toute entit� se retrouve, au final, dans le monde, il y a, pour chaque type particulier d'entit�, un syst�me qui prend en charge l'utilisation qui leur est propre.

    Tu aurais, par exemple, tout un syst�me (c'est � dire un ensemble de classes ) qui se chargerait de la cr�ation, de la vie (intelligence artificielle ) et de la mort des ennemis, un autre syst�me qui se chargerait de la g�n�ration, du d�placement et de la suppression des sprites, ou encore un syst�me prenant en charge le joueur.

    Chaque fois qu'un de ces syst�mes de gestion d'un type particulier d'entit� en cr�e une, il l'enregistre, � la position qui est sienne, aupr�s du monde, de mani�re � ce que les syst�mes d'affichage et de d�tection de collisions puissent les prendre en compte, chaque fois qu'un de ces syst�me d�truit ou d�place une entit�, il en tient effectivement le monde inform�, mais la d�cision de cr�er, de d�placer ou de d�truire cette entit� va d�pendre exclusivement... du syst�me concern�.

    Et, �videmment, le syst�me concern� ne consid�rera pas les entit�s dont il a la charge comme des entit�s, mais bien... comme des entit�s du type particulier dont il a la charge

    Je veux dire par l� que le syst�me (l'ensemble de classes) qui prend en charge la gestion des ennemis, par exemple, consid�rera l'ensemble des �l�ments qu'il cr�e, d�place ou d�truit comme �tant... des ennemis

    Apr�s, les choses peuvent sans doute n�cessiter des interm�diaires!!!

    Par exemple, la cr�ation d'un sprite peut etre demand�e par deux �l�ments distincts: l'intelligence artificielle (des ennemis) d'un cot�, un �v�nement utilisateur de l'autre.

    Ces deux �l�ments feront appel au syst�me de gestion de sprite pour lui demander de cr�er un sprite de tel type, partant de telle position et se d�pla�ant � telle vitesse dans telle direction.

    le syst�me de sprite s'occupera de cr�er le sprite en fonction de ce qui lui est demand�, de l'enregistrer aupr�s du monde (pour qu'il soit affich�), de le d�placer � la vitesse demand�e dans la direction demand�e et, quand le syst�me de d�tection des collisions d�tectera que le sprite est entr� en collision avec "quelque chose", le syst�me de gestion des sprite le "d�senregistrera" aupr�s du monde et le d�truira.

    De son cot�, le syst�me de d�tection de collision se chargera de mettre en relation le sprite avec l'objet avec lequel il est entr� en collision de mani�re � ce que les deux puissent r�agir � cette collision

    Evidemment, quand je parle ici de "syst�mes" je veux en r�alit� parler d'ensembles de classes travaillant de concert pour g�rer un type particulier d'entit�.

    Nous y trouverons sans doute chaque fois une fabrique (permettant de cr�er les entit�s attendues selon certains crit�res � d�finir), un "gestionnaire de", et une s�rie de visiteurs susceptibles de manipuler l'ensemble des entit�s d'un type particulier en fonction de leur �volution "spatio temporelle"

    Je ne vais pas commencer, vu l'heure, � te faire une analyse complete de ce qu'il te faut mettre en oeuvre, mais je crois que je t'ai donn� suffisamment de pistes � suivre pour te permettre de reprendre ta conception de mani�re correcte

    Si tu as un doute quand � la mani�re de mettre l'une ou l'autre chose en oeuvre, n'h�site pas � demander, que ce soit du point de vue conceptuel ou du point de vue de l'impl�mentation
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  10. #10
    screetch
    Invit�(e)
    Par d�faut
    bon je prends en cours de route donc je ne peux pas forc�ment �tre exhaustif
    d�j� je dirais de se m�fier des avis des gens et de les prendre avec du recul.
    c'est pas que les gens sont incomp�tents, c'est que c'est de l'architecture informatique. Et lorsqu'on demande a 1000 informaticiens de r�soudre un probl�me on obtient 1000 r�ponses diff�rentes et pas toutes sont fausses.


    je ne vodurais donc pas forc�ment t'envoyer sur une nouvelle voie qui contredit les avis des 43 posteurs pr�c�dents, ca serait contre-productif.

    je dirai simplement de mani�re g�n�rale:
    * ce que j'ai lu ici �tait souvent tr�s compliqu�. La raison, c'est un manque de g�n�ralisation du souvent au fait que tu (et d'autres gens qui ont post� aussi) restes tr�s tr�s pr�s d'un design "naturel" ou Link est une classe, un Enemy est une classe, un Mur est une classe, etc


    un peu de maths: si tu as n classes, tu as n(n-1) interactions possibles entre classe. La complexit� augmente donc au carr�, et c'est ainsi que la plupart des logiciels deviennent des plats de spaghettis.

    Pour se d�barasser de ce probl�me la seule solution est d'avoir le moins de classes possibles, au lieu de faire des classes sp�ciales pour tous les machins qui existent.


    par exemple, si Link est une classe sp�ciale, tu dois donc r�soudre deux probl�mes: que se passe t'il lorsque Link touche un mur? et que se passe t'il lorsque un Enemy touche un mur? et quand un Mur touche un Mur?
    si tu n'as qu'une seule classe "Entity" ou "Sprite" ou je ne sais pas, le probl�me devient: que se passe t'il lorsqu'une Entity touche une Entity?
    bien s�r la r�ponse est: ca d�pend des propri�t�s de l'Entity en question.
    Mais tu as donc une interaction unique Entity->Entity dont le r�sultat va d�pendre des propri�t�s (et non plus du TYPE) de l'entit�. A toi de voir les propri�t�s qui auront un sens.

    Link, le mur et l'ennemi deviennent donc des objets tr�s similaires mais aux propri�t�s diff�rentes.



    Il y a ensuite les Controllers, qui peuvent se sp�cialiser en AIController pour controller certaines entit�s et en PlayerController pour controller d'autres entit�s. Ainsi, l'IA pourrait controller Link, m�me si ce n'est pas tr�s utile mais donc tu as alors moins d'interaction.







    Donc en gros tu essayes trop de mod�liser la "vie r�elle" avec tes classes, tu donnes des r�les particuliers a certains objets. Si certains objets sont particuliers, ce n'est cependant pas une raison pour leur donner une classe particuli�re






    La deuxi�me erreur g�n�rale c'est exactement l'inverse; certains concepts abstraits n'ont rien a faire dans cette discussion, notemment les Design Patterns. J'avoue que j'en ai ma claque de lire Singleton dans un message sur deux; que ce soit un Singleton ou pas, ca ne devrait pas changer fondamentalement le r�sultat.
    Le plus dur c'est d'ailleurs de faire en sorte d'avoir le moins de liens possibles entre les classes (CF le n au carr� plus haut) et en ajoutant Singleton dans un message tu commences par te tirer une balle dans le pieds (ou pire, a tirer une balle dans le pieds d'Aspic)



    de 1, tout est faisable sans singleton et c'est m�me pas plus dur
    de 2, c'est un d�tail d'impl�mentation qui ne devrait pas appara�tre sur ce post a ce point, comme un DP Visiteur ou autre.

  11. #11
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    C'est vrai qu'au final chacun ayant sa vision de la chose, ca m'embrouille plus qu'autre chose

    Citation Envoy� par koala01 Voir le message
    En fait, il y a un probl�me de conception d�s le d�part...
    Ca je veux bien le croire

    Le principe de responsabilit� unique ne peut pas toujours �tre appliqu�. Par exemple un moteur de jeu � une m�thode de Render() pour dessiner et une m�thode de Update() pour mettre � jour les �l�ments du jeu => on a donc deux responsabilit�s et pourtant c'est pas mal si ?

    Alors dans mon cas, le moteur de jeu d�l�gue le dessin � une classe Renderer() dont sont UNIQUE but est de dessiner tout ce que je lui demande ^^

    Pour la fonction Update(), on appelle donc la fonction Update() de la classe World mais c'est c'est impossible de d�finir une responsabilit� unique. Le World est responsable de la gestion des entit�s qui le compose pour moi, donc il est responsable de g�rer les collisions, les d�placer, les supprimer quand elles meurent, en ajouter d'autres... (Ouch j'explose le SRP).

    Moi ce que je voulais faire, c'�tait d�l�gu� le d�placement � une interface IMoveBehaviour, les collisions � un ICollisionBehaviour... en utilisant le pattern strat�gie.

    Citation Envoy� par koala01 Voir le message
    Evidemment, quand je parle ici de "syst�mes" je veux en r�alit� parler d'ensembles de classes travaillant de concert pour g�rer un type particulier d'entit�.

    Nous y trouverons sans doute chaque fois une fabrique (permettant de cr�er les entit�s attendues selon certains crit�res � d�finir), un "gestionnaire de", et une s�rie de visiteurs susceptibles de manipuler l'ensemble des entit�s d'un type particulier en fonction de leur �volution "spatio temporelle"
    Voil� au final je suis toujours coinc�, car les concepts abord�s sont trop compliqu� pour moi
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  12. #12
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Citation Envoy� par Aspic Voir le message
    Le principe de responsabilit� unique ne peut pas toujours �tre appliqu�. Par exemple un moteur de jeu � une m�thode de Render() pour dessiner et une m�thode de Update() pour mettre � jour les �l�ments du jeu => on a donc deux responsabilit�s et pourtant c'est pas mal si ?
    L�, tu parles de fonction de ta classe...

    Ce sont donc des services que ta classe va rendre dans le cadre de la responsabilit� qu'elle a

    Il se peut que la responsabilit� d'une classe soit complexe: un moteur de jeu a pour but de... faire fonctionner le jeu, bien �videmment

    A partir de l�, il est "logique" que l'on s'attende � un ensemble de services divers et vari�s, tels que la possibilit� de charger une carte ou une partie, d'afficher cette carte, de g�n�rer des "mouvements" et de mettre les informations � jour, de jouer des sons, de recevoir des �v�nements d'inputs ou que sais-je

    Mais tous ces services rentrent malgr� tout dans le cadre de la responsabilit� unique de ton moteur de jeu.

    A partir de l�, chaque service sera d�l�gu� � une classe particuli�re dont la responsabilit� unique sera... "particuli�re" au service attendu:

    Ainsi, la classe monde va sans doute s'occuper, comme je le disais plus haut de g�rer les positions de l'ensemble des entit�s que l'on trouve dans le monde, et de faire "le tri" de celles qui doivent �tre consid�r�es par rapport � la partie "visible" (� un instant T) du monde.

    A cot� de la classe monde, nous aurons une classe renderer qui s'occupera de l'affichage (bas� sur les entit�s que le monde renvoie par rapport � la portion visible (� un instant T) du monde, ou une classe "SoundPlayer" qui s'occupera de jouer des sons en fonctions de certains �v�nements qui seront �mis, pour leur part, par le syst�me d'intelligence artificielle pour les ennemis et d'autre part par le syst�me de gestion d'input pour le joueur.

    Le syst�me d'intelligence artificielle ne prendra lui-m�me en compte que les ennemis (consid�r�s comme tels ), g�r�s par un classe dont c'est l'unique responsabilit� (le "gestionnaire d'ennemis") dont le monde (qui les consid�re comme des entit�s ) indique qu'ils sont visibles (comprend: dans la portion de monde � afficher � l'instant T particulier ).

    L'avantage de travailler de la sorte, c'est que tu n'as meme plus besoin de jouer avec le pattern singleton (qui est un anti pattern ), car le moteur de jeu dispose d'une (et une seule) instance de monde, de SoundPlayer ou de EnnemyManager, et, comme tu n'auras qu'une seule instance de moteur de jeu (cr��e dans main() ) tu es sur que tu n'as qu'une seule instance des diff�rents membres qui lui permettent de rendre les services attendus

    Comme le moteur de jeu est, en quelques sortes, le "chef d'orchestre" de tout le brol, c'est lui qui se chargera de fournir en tant qu'arguments les outils n�cessaires au services rendus par les diff�rents membres pour leur permettre de travailler correctement


    Alors dans mon cas, le moteur de jeu d�l�gue le dessin � une classe Renderer() dont sont UNIQUE but est de dessiner tout ce que je lui demande ^^
    Exactement
    Pour la fonction Update(), on appelle donc la fonction Update() de la classe World mais c'est c'est impossible de d�finir une responsabilit� unique. Le World est responsable de la gestion des entit�s qui le compose pour moi, donc il est responsable de g�rer les collisions, les d�placer, les supprimer quand elles meurent, en ajouter d'autres... (Ouch j'explose le SRP).
    Justement, non...

    Le monde en lui-m�me n'est qu'un r�ceptacle pour tout ce qui peut etre consid�r� comme une entit� � un instant T.

    Il ne sert qu'� permettre la cr�ation d'une "photo" instantan�e du monde

    Le cycle de vie de toutes les entit�s qu'il re�oit est g�r� par "quelque chose d'autre" dont ce sera l'unique responsabilit�

    Et quand je parle "d'autre chose", cela peut tr�s bien �tre un ensemble de classes (un syst�me ind�pendant de classes) compos�, entre autre, d'un "gestionnaire" (de sprites, d'ennemis, d'objets d'inventaire, ou que sais-je) qui se charge de les enregistrer aupr�s du monde lors de la cr�ation et de les en "d�senregistrer" lors de leur destruction.

    Mais ce "gestionnaire" travaille en relation avec un ensemble d'autres classes dont les responsabilit�s respectives sont de g�rer les diff�rentes �tapes du cycle de vie des objets et des �v�nements qui s'y rapportent

    Si je parle de syst�me de classes ind�pendantes, c'est parce que chaque syst�me de classes peut exister sans avoir la moindre connaissance des autres syst�mes de classes

    Par exemple, tu pourrais tr�s bien commencer par ne cr�er qu'un syst�me de classes dont la responsabilit� globale est la gestion des sprites, avec, "en son centre", un "SpriteManager".

    Avant que tu ne mettes au point les autres syst�mes de classes (celui dont la responsabilit� globale est la gestion des objets d'inventaires, ou d'ennemis ou de je ne sais quoi), tu pourrais tr�s bien faire en sorte que ton moteur de jeu se contente d'�mettre, de mani�re plus ou moins al�atoire des �v�nements qui provoqueront la cr�ation de sprites et tout ce que tu verrais du monde (vu que tout le reste n'existerait pas encore) lorsque tu lances ton jeu, ce serait des sprites qui partent � gauche et � droite, selon diff�rents sc�narios

    Juste apr�s, tu pourrait mettre au point le syst�me de classe dont la responsabilit� est la gestion des objets d'inventaires, qui doit aussi pouvoir travailler seul...

    Tu pourrais donc faire en sorte que ton moteur de jeu n'�mette plus d'�v�nements sp�cifiques � la gestion de sprites, mais qu'il �mette plutot des �v�nement sp�cifique � la gestion d'objets d'inventaire, et tout ce que tu verrais alors, ce sont des objets d'inventaire qui apparaissent et qui disparaissent de la carte

    Juste apr�s, tu pourrais faire pareil pour le syst�me de gestion des �l�ments du d�cors, puis avec le syst�me de gestion des ennemis et, en activant ou d�sactivant certaines parties, tu dois pouvoir voir (ou non), le d�cors, les ennemis, les sprites, les d�placements dans le monde (scroll ) etc

    Au final, lorsque tu r�active l'ensemble, tu auras tous les �l�ments constitutifs du monde qui apparaissent et qui agissent "de concert" (grace au moteur de jeu )
    Moi ce que je voulais faire, c'�tait d�l�gu� le d�placement � une interface IMoveBehaviour, les collisions � un ICollisionBehaviour... en utilisant le pattern strat�gie.
    Tu devras sans doute recourir � un DP strat�gie, mais pas au niveau de monde

    C'est au niveau de tous les ensembles de classes (tous les "syst�mes de classes") ind�pendants les uns des autres qui consid�rent chaque fois les entit�s (qui interviennent dans l'instantan� renvoy� par monde) comme �tant du type particulier "r�el" que ces strat�gies seront mise en oeuvre et utilis�e.
    Voil� au final je suis toujours coinc�, car les concepts abord�s sont trop compliqu� pour moi
    C'est justement pour cela que tu dois imp�rativement d�l�guer les responsabilit�s, de mani�re � r�fl�chir, point par point, � tout ce qui permet de g�rer le "cycle de vie" d'un type particulier d'entit�, sans t'inqui�ter des autres types particuliers d'entit�s.

    Il n'y aura que deux syst�mes de classes (hormis le monde) qui consid�reront les diff�rents types d'entit�s en tant qu'entit� "g�n�rique" (ne serait ce que provisoirement ) c'est le syst�me dont la responsabilit� globale est la gestion de l'affichage et celui dont la responsabilit� globale est la gestion des collisions

    Tous les autres syst�mes de classes travailleront sur avec des types de classes particuliers et l'ensemble aura sans doute comme "fil d'Ariane" un syst�me de "gestion d'�v�nements" permettant aux diff�rents syst�mes de communiquer entre eux (car tout r�agis en fonction des �v�nements provoqu�s par son entourage )
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  13. #13
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Citation Envoy� par koala01 Voir le message
    A partir de l�, chaque service sera d�l�gu� � une classe particuli�re dont la responsabilit� unique sera... "particuli�re" au service attendu:
    Donc selon toi, ca serait � la classe GameEngine de poss�der un pointeur sur chaque "service d�l�gu�" ? c'est � dire un pointeur sur SpriteLoader dont l'unique but est de charger des sprites, un autre sur EnemyManager dont l'unique but est de g�rer les ennemies, SoundLoader...

    Car pour moi ca serait plutot � World d'avoir tout ca...
    Voil� la code du moteur de jeu pour les fontions Update() et render() :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    bool Core::GameEngine::update()
    {
        pInputManager->update();
     
        // MAJ des controlleurs (clavier, joystick)
        int directions = pInputManager->getDirectionsPressed();
        int buttons = pInputManager->getButtonsPressed();
     
        // MAJ du jeu
        return pWorld->update(directions, buttons);
    }
     
    bool Core::GameEngine::render()
    {
        bool bOk = true;
     
        // efface l'écran
        pRenderer->clearScreen();
     
        // dessine dans le double buffer les entités du jeu
        bOk &= pWorld->draw(*pRenderer);
     
        // affiche les mises à jour sur l'écran
        pRenderer->updateWindow();
     
        if (!bOk)
           LError << "Fail to render the game.";
     
        return bOk;
    }
    On voit bien que le moteur de jeu d�l�gue � World le travail de g�rer les entit�s, les collisions, les sons, les evements... enfin tout ce qui fais un bon

    Alors que la fonction render() reset l'�cran puis d�l�gue � World l'affichage des entit�s puis blit le r�sultat sur l'�cran.
    Citation Envoy� par koala01 Voir le message
    Ainsi, la classe monde va sans doute s'occuper, comme je le disais plus haut de g�rer les positions de l'ensemble des entit�s que l'on trouve dans le monde, et de faire "le tri" de celles qui doivent �tre consid�r�es par rapport � la partie "visible" (� un instant T) du monde.
    Alors je ne l'ai pas dit (d�sol�) mais le monde ne connait pas tous les ennemies de la carte totale. En fait, le chargement des entit�s (ennemies et autres) se fait au moment su scroll (changement de zone). De ce fait, la classe World a d�j� l'ensemble des Entity visible � l'�cran
    Citation Envoy� par koala01 Voir le message
    Le monde en lui-m�me n'est qu'un r�ceptacle pour tout ce qui peut etre consid�r� comme une entit� � un instant T.

    Il ne sert qu'� permettre la cr�ation d'une "photo" instantan�e du monde

    Le cycle de vie de toutes les entit�s qu'il re�oit est g�r� par "quelque chose d'autre" dont ce sera l'unique responsabilit�
    Actuellement, c'est le monde lui m�me qui cr�� les entit�s, il ne les recoit pas de quelqu'un d'autre.

    En fait, si tu avais un exemple ou un diagramme de classe de ce que tu essayes de m'expliquer j'y verrais plus claire car l� sinc�rement, je ne suis plus du tout...
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  14. #14
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Citation Envoy� par Aspic Voir le message
    Donc selon toi, ca serait � la classe GameEngine de poss�der un pointeur sur chaque "service d�l�gu�" ? c'est � dire un pointeur sur SpriteLoader dont l'unique but est de charger des sprites, un autre sur EnemyManager dont l'unique but est de g�rer les ennemies, SoundLoader...
    Presque...

    GameEngine ne devrait avoir qu'un (meme pas pointeur) membre SpriteManager, et meme pas de SpriteLoader

    Le SpriteManager utilise un "SpriteFactory" (qu'il connait en tant que membre et c'est SpriteFactory qui fera appel � SpriteLoader, uniquement lors de l'initialisation, pour charger le "prototype" des sprites qu'elle devra g�n�rer
    Car pour moi ca serait plutot � World d'avoir tout ca...
    Voil� la code du moteur de jeu pour les fontions Update() et render() :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    bool Core::GameEngine::update()
    {
        pInputManager->update();
     
        // MAJ des controlleurs (clavier, joystick)
        int directions = pInputManager->getDirectionsPressed();
        int buttons = pInputManager->getButtonsPressed();
     
        // MAJ du jeu
        return pWorld->update(directions, buttons);
    }
     
    bool Core::GameEngine::render()
    {
        bool bOk = true;
     
        // efface l'écran
        pRenderer->clearScreen();
     
        // dessine dans le double buffer les entités du jeu
        bOk &= pWorld->draw(*pRenderer);
     
        // affiche les mises à jour sur l'écran
        pRenderer->updateWindow();
     
        if (!bOk)
           LError << "Fail to render the game.";
     
        return bOk;
    }
    On voit bien que le moteur de jeu d�l�gue � World le travail de g�rer les entit�s, les collisions, les sons, les evements... enfin tout ce qui fais un bon

    Alors que la fonction render() reset l'�cran puis d�l�gue � World l'affichage des entit�s puis blit le r�sultat sur l'�cran.
    Cela montre bien que tu veut donner beaucoup trop de responsabilit�s � ton monde : ce que tu explique l� est bien plus du ressort du gameEngine (qui devrait d'ailleurs le d�l�guer � d'autres classes )que du monde, que diable !!!!
    Alors je ne l'ai pas dit (d�sol�) mais le monde ne connait pas tous les ennemies de la carte totale. En fait, le chargement des entit�s (ennemies et autres) se fait au moment su scroll (changement de zone). De ce fait, la classe World a d�j� l'ensemble des Entity visible � l'�cran

    Actuellement, c'est le monde lui m�me qui cr�� les entit�s, il ne les recoit pas de quelqu'un d'autre.
    Ca, ce n'est qu'un d�tail mais tu comprendras assez rapidement
    En fait, si tu avais un exemple ou un diagramme de classe de ce que tu essayes de m'expliquer j'y verrais plus claire car l� sinc�rement, je ne suis plus du tout...
    j'�tais, justement, occup� � pr�parer une r�ponse avec des morceaux de code...

    Elle est assez longue � �crire, mais, si tu patiente un tout petit peu, tu verras, tout deviendra limpide
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  15. #15
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Citation Envoy� par koala01 Voir le message
    Elle est assez longue � �crire, mais, si tu patiente un tout petit peu, tu verras, tout deviendra limpide
    Ouais un exemple ^^

    Si seulement ca pouvait �tre vrai Il est vrai que je comprends 20 fois plus vite avec un exemple plut�t qu'un long discours, et j'esp�re que ca sera le cas donc je vais �tre patient

    PS : j'ai d�j� un moteur de jeu qui fonctionne bien avec la gestion du fps via des timers, un manager des Input, etc.
    Je mets la proc�dure de d�marrage du moteur de jeu, sait-on jamais ca peut servir :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    void Core::GameEngine::run()
    {
        if (!bRunning)
        {
            bool ok = true;
            int frames_done = 0;
            int old_time = 0;
     
            // lancement des timers du moteur de jeu
           .......
     
            // boucle du jeu principale
            bRunning = true;
            while (bRunning && !pInputManager->getEscape() && !GameEngine::closeWindows && ok)
            {
                // pour éviter que le CPU soit à 100%
                while(ticks == 0)
                {
                    rest(100 / fps);
                }
     
                while(ticks > 0)
                {
                    int old_ticks = ticks;
     
                    // MAJ des entites du moteur de jeu
                    ok = this->update();
     
                    ticks--;
                    if(old_ticks <= ticks)
                    {
                        LWarning << "\tABORD run()";
                        break;
                    }
                }
     
                if(gameTime - old_time >= 10)//i.e. a second has passed since we last measured the frame rate
                {
                    fps = frames_done;
                    //fps now holds the the number of frames done in the last second
                    //you can now output it using textout_ex et al.
                    LWarning << "fps : " << fps;
                    //reset for the next second
                    frames_done = 0;
                    //gameTime = 0;
                    old_time = gameTime;
                }
     
                // AFFICHAGE DU RESULTAT
                ok = this->render();
     
                frames_done++;//we drew a frame!
            }
     
            // suppression des timers
           ......
        }
    }
    Merci beaucoup !
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  16. #16
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par d�faut
    @Screetch
    Je tiens � dire que je n'ai mentionn� le pattern Singleton que parce qu'Aspic demandait s'il allait devoir passer ces donn�es en argument � chaque fois. Je ne voulais que mettre en �vidence, en utilisant le pattern le mieux connu pour �a, le fait qu'utiliser des membres statiques �tait plus adapt�. Apr�s, chacun fait ce qu'il veut et pour ma part je n'utiliserais pas un singleton.

    Ensuite, oui, je rentre parfois trop dans les d�tails. Parfois � tort, notamment dans mon dernier message post� assez tardivement, mais parfois parce qu'Aspic est demandeur.


    @Aspic
    Avant toute chose, nous semblons avoir un probl�me de s�mantique, tu comprends de travers la notion de d�tention des responsabilit�s dans le contexte de conception objet. Ainsi, quand tu nous as montr� ce code o� World parcourt les entit�s en appelant pour chacune d'elles "update", tu nous as dit que c'�tait World qui avait donc la responsabilit� de mettre � jour la position des entit�s. C'est faux : World demande aux entit�s de se mettre � jour mais ce sont bien elles-m�mes qui d�cident quoi changer et que faire des informations fournies (ou peut-�tre d�l�guent-elles � une autre classe). Dans ton exemple, c'est donc bien Entity qui poss�de cette responsabilit� et non World. World a au mieux la responsabilit� de requ�rir des entit�s qu'elles se mettent � jour. Ce qui n'a rien d'anormal, tout �a est correct. Le r�le de chef d'orchestre est de toute fa�on in�vitable puisqu'il faut bien que la pile des appels ait une racine, le tout est que cela soit fait avec un faible couplage et �a ne veut pas dire pour autant que le chef d'orchestre a toutes les responsabilit�s du monde.

    De m�me, tu nous as dit que Entity avait pour responsabilit� le rendu. C'est faux l� aussi, Entity ne fait que sp�cifier la position de chaque sprite. En somme, Entity ne fait que sp�cifier ce qui sera rendu et o� mais les d�tails du rendu (batching, appel des API graphiques, etc) sont g�r�s par autre chose, peut-�tre sprite ou peut-�tre une autre classe.



    Maintenant, tu me disais plus haut que, quand Link donne un coup d'�p�e, ton moteur cr�era une autre entit� "�p�e". L� il me semble que tu as un probl�me de d�coupage et d'assignation des responsabilit�s. En effet, imagine que durant son coup d'�p�e, Link soit touch�. L'animation doit alors �tre interrompue et Link projet� en arri�re. On voit bien que le comportement de Link et de l'�p�e, m�me s'ils sont repr�sent�s par deux sprites distincts, sont li�s. En clair, il faut un chef d'orchestre pour le personnage de Link (et, plus g�n�ralement, pour toute cr�ature, ou tout ensemble de cr�atures si tu suis la piste de Koala01). De m�me tu peux aussi avoir un ennemi compos� de zones vuln�rables ou non qui sont rattach�s au m�me pool de PV.

    Il me semble donc qu'une entit� peut �tre compos�e de N sprites et de M zones de collision ayant des cons�quences diff�rentes. Chercher � faire cette �conomie en for�ant un mod�le "une entit� = un sprite = une zone de collision", c'est � mon avis se cr�er des probl�mes et vouloir r�unir de force des responsabilit�s distinctes.

    Une entit� (ou un gestionnaire d'entit�s multiples mais similaires comme le propose Koala01) devrait a priori avoir les responsabilit�s suivantes (dont certaines sont �ventuellement d�l�gu�es � des comportements) :
    * Gestion de l'IA (ou gestion par le joueur)
    * �tats internes (vie, position, etc)
    * R�actions aux collisions (voir d�l�guer �a aux zones de collision)
    * Maintien/passage des sprites
    * Maintien/passage des zones de collision

    En vrac :
    * Passer "this" en argument n'a rien de choquant
    * Le PlayerBehaviour que j'avais mentionn� venait du fait que je croyais que tu comptais d�l�guer � des comportements la gestion de l'IA (et, dans le cas du joueur, la r�action � l'�tat du contr�leur). Accessoirement cela me semble une bonne id�e dans la mesure o� l'IA va varier au cours du temps (un bond en arri�re suite � un coup suspend le reste, un ennemi peut avoir deux comportements selon qu'il a ou non rep�r� Link, etc)
    * Pour les collisions, deux b�tes boucles for imbriqu�es feront l'affaire.

  17. #17
    Membre Expert
    Homme Profil pro
    Inscrit en
    D�cembre 2010
    Messages
    734
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : D�cembre 2010
    Messages : 734
    Par d�faut
    Citation Envoy� par DonQuiche Voir le message
    @Screetch
    Je tiens � dire que je n'ai mentionn� le pattern Singleton que parce qu'Aspic demandait s'il allait devoir passer ces donn�es en argument � chaque fois. Je ne voulais que mettre en �vidence, en utilisant le pattern le mieux connu pour �a, le fait qu'utiliser des membres statiques �tait plus adapt�.
    Je moinssoie violamment. Il est possible de proc�der diff�rement, notamment en transmettant la r�f�rence du moteur de jeu aux gestionnaires � l'instanciation pour qu'ils puissent lui relayer les �v�nements.
    C'est � mon sens mieux car du coup le lien est:
    1) plus facile � rep�rer
    2) plus facile � changer au besoin (ex: tests)

  18. #18
    Membre Expert
    Homme Profil pro
    Inscrit en
    D�cembre 2010
    Messages
    734
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : D�cembre 2010
    Messages : 734
    Par d�faut
    Ne voulant pas abuser des �dits apr�s coup, cette fois-ci je pr�cise par un second message: pour qu'on puisse changer, il est bon que la r�f�rence au moteur de jeu soit typ�e d'une interface (style gestionnaire d'�v�nements) dont on puisse fournir plusieurs impl�mentations comme:
    1) le moteur de jeu
    2) diverses classes de test permettant de tester les sous-syst�mes s�par�ment, je trouve que �a aide quand on d�veloppe un ensemble complexe.

  19. #19
    screetch
    Invit�(e)
    Par d�faut
    Citation Envoy� par DonQuiche Voir le message
    @Screetch
    Je tiens � dire que je n'ai mentionn� le pattern Singleton que parce qu'Aspic demandait s'il allait devoir passer ces donn�es en argument � chaque fois. Je ne voulais que mettre en �vidence, en utilisant le pattern le mieux connu pour �a, le fait qu'utiliser des membres statiques �tait plus adapt�. Apr�s, chacun fait ce qu'il veut et pour ma part je n'utiliserais pas un singleton.

    Ensuite, oui, je rentre parfois trop dans les d�tails. Parfois � tort, notamment dans mon dernier message post� assez tardivement, mais parfois parce qu'Aspic est demandeur.


    @Aspic
    Avant toute chose, nous semblons avoir un probl�me de s�mantique, tu comprends de travers la notion de d�tention des responsabilit�s dans le contexte de conception objet. Ainsi, quand tu nous as montr� ce code o� World parcourt les entit�s en appelant pour chacune d'elles "update", tu nous as dit que c'�tait World qui avait donc la responsabilit� de mettre � jour la position des entit�s. C'est faux : World demande aux entit�s de se mettre � jour mais ce sont bien elles-m�mes qui d�cident quoi changer et que faire des informations fournies (ou peut-�tre d�l�guent-elles � une autre classe). Dans ton exemple, c'est donc bien Entity qui poss�de cette responsabilit� et non World. World a au mieux la responsabilit� de requ�rir des entit�s qu'elles se mettent � jour. Ce qui n'a rien d'anormal, tout �a est correct. Le r�le de chef d'orchestre est de toute fa�on in�vitable puisqu'il faut bien que la pile des appels ait une racine, le tout est que cela soit fait avec un faible couplage et �a ne veut pas dire pour autant que le chef d'orchestre a toutes les responsabilit�s du monde.

    De m�me, tu nous as dit que Entity avait pour responsabilit� le rendu. C'est faux l� aussi, Entity ne fait que sp�cifier la position de chaque sprite. En somme, Entity ne fait que sp�cifier ce qui sera rendu et o� mais les d�tails du rendu (batching, appel des API graphiques, etc) sont g�r�s par autre chose, peut-�tre sprite ou peut-�tre une autre classe.



    Maintenant, tu me disais plus haut que, quand Link donne un coup d'�p�e, ton moteur cr�era une autre entit� "�p�e". L� il me semble que tu as un probl�me de d�coupage et d'assignation des responsabilit�s. En effet, imagine que durant son coup d'�p�e, Link soit touch�. L'animation doit alors �tre interrompue et Link projet� en arri�re. On voit bien que le comportement de Link et de l'�p�e, m�me s'ils sont repr�sent�s par deux sprites distincts, sont li�s. En clair, il faut un chef d'orchestre pour le personnage de Link (et, plus g�n�ralement, pour toute cr�ature, ou tout ensemble de cr�atures si tu suis la piste de Koala01). De m�me tu peux aussi avoir un ennemi compos� de zones vuln�rables ou non qui sont rattach�s au m�me pool de PV.

    Il me semble donc qu'une entit� peut �tre compos�e de N sprites et de M zones de collision ayant des cons�quences diff�rentes. Chercher � faire cette �conomie en for�ant un mod�le "une entit� = un sprite = une zone de collision", c'est � mon avis se cr�er des probl�mes et vouloir r�unir de force des responsabilit�s distinctes.

    Une entit� (ou un gestionnaire d'entit�s multiples mais similaires comme le propose Koala01) devrait a priori avoir les responsabilit�s suivantes (dont certaines sont �ventuellement d�l�gu�es � des comportements) :
    * Gestion de l'IA (ou gestion par le joueur)
    * �tats internes (vie, position, etc)
    * R�actions aux collisions (voir d�l�guer �a aux zones de collision)
    * Maintien/passage des sprites
    * Maintien/passage des zones de collision

    En vrac :
    * Passer "this" en argument n'a rien de choquant
    * Le PlayerBehaviour que j'avais mentionn� venait du fait que je croyais que tu comptais d�l�guer � des comportements la gestion de l'IA (et, dans le cas du joueur, la r�action � l'�tat du contr�leur). Accessoirement cela me semble une bonne id�e dans la mesure o� l'IA va varier au cours du temps (un bond en arri�re suite � un coup suspend le reste, un ennemi peut avoir deux comportements selon qu'il a ou non rep�r� Link, etc)
    * Pour les collisions, deux b�tes boucles for imbriqu�es feront l'affaire.
    ne prend pas mal ce que j'ai dit, je crois que c'est surtout Aspic qui rentre trop t�t dans les details.

  20. #20
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Allez, pour t'aider un peu � comprendre ce que je veux expliquer, je vais sortir du cot� abstrait de tout ce que je t'explique pour te donner une id�e de l'impl�mentation telle que je la con�ois

    Une petite pr�cision: j'ai consid�r� que l'on pouvait charger l'ensemble du monde (et je ne veux pas reprendre l'ensemble de la r�ponse que j'ai d�j� �crite pour changer )

    Nous sommes partis sur l'id�e que tout ce qui constitue le monde est "Entity", et que la responsabilit� d'une Entity est de se positionner dans le monde.

    Pour se positionner dans le monde, elle a besoin de connaitre les coordonn�es o� se placer, et de pouvoir etre trac�e.

    Seulement, elle ne peut etre trac�e que si elle est visible ( si elle se trouve dans la portion du monde que l'on aper�oit � l'�cran).

    Nous avons donc besoin d'une classe (qui a s�mantique de valeur "Coordinate" qui pourrait ressembler �
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    class Coordinate
    {
        public:
            Coordinate(int x, int y):x_(x),y_(y){}
            int x() const{return x_;}
            int y() const{return y_;}
    };
    Et la classe Entity pourrait ressembler �
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    class Entity
    {
        public:
            Entity(int xpos, int ypos, bool visible =false):pos_(x,y),visible_(visible){}
             virtual ~Entity(){}
            // permet de savoir si l'entité est visible 
            bool isVisible() const{return visible_;}
            // permet de rendre l'entité visible ou invisible
            void setVisibility(bool visibility){visible_ = visibility;}
            /* permet de connaitre la coordonnée sur l'axe des x
             * par rapport au "coin supérieur" du monde
             */
            int xpos() const{return pos_.x();}
            /* permet de connaitre la coordonnée sur l'axe des y
             * par rapport au "coin supérieur" du monde
             */
            int ypos() const{return pos_.y();}
            /* je vais considérer qu'il est possible de bouger n'importe quelle
             * entité jusqu'à ce qu'on ait la preuve qu'on ne peut pas le faire
             * cela limitera les redéfinitions à la classe dérivée de Entity
             * qui servira de base aux objet non mobiles (éléments de décors
             * et / ou objets d'inventaire
             */
            virtual void moveTo(Coordinate const & c){pos_=c;}
            /* et j'ai la possibilité de la dessiner... j'utilise l'idiome NVI
             * car je veux que le tracé de l'objet ne se fasse que s'il est visible ;)
             */
             void draw() const 
             {
                 if(isVisible())
                     drawMe();
             }
        private:
            Coordinate pos_; // pour avoir la position de l'entité
            bool visible_; // pour savoir s'il est visible
            /* la fonction qui devra être redéfinie quand on saura comment 
             * l'afficher :D (dans les classes dérivées)
             */
            virtual void drawMe() const = 0;
    };
    Il existe deux grandes cat�gories d'entit�s: celles qui peuvent bouger (on y retrouve le joueur, les ennemis, les sprites, ... et, pourquoi pas,quelques �l�ments de d�cors sur lesquels on ne peut pas agir (un cerf passant au loin ) ) et celles qui ne peuvent pas bouger (�l�ments de d�cors, objets d'inventaire, ...)

    Autant faire la distinction tout de suite, de mani�re � pouvoir g�rer tous les objets qui peuvent bouger d'un cot� et tous ceux qui ne peuvent pas bouger de l'autre

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class MovableEntity : public Entity
    {
        public:
            MovableEntity (int xpos, int ypos, bool visible =false):Entity(xpos, ypos){}
    };
    class NonMovableEntity : public Entity
    {
        public:
            NonMovableEntity (int xpos, int ypos, bool visible =false):Entity(xpos, ypos){}
            /* si on invoque la fonction move sur quelque chose qui ne peut pas
             * bouger, il ne se passe tout simplement rien :D
             */
            virtual void moveTo(Coordinate const & c){}
    }
    Le monde se contente de connaitre toutes les entit�s qui le composent (quelles qu'elles soient) et de les marquer visibles ou non en fonction de leur position par rapport � la portion visible

    On doit donc pouvoir y rajouter ou en retirer des entit�s "� la demande"
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    class World
    {
        /* il faut etre clair : le monde n'a aucune responsabilité quant à la
         * gestion de la durée de vie des entités qu'il connait : il ne fait que
         * les utiliser :D
         */
        void registerEntity(Entity* entity)
        {
             entities_.push_back(entity);
             needSorting_ = true;
        }
        void unregisterEntity(Entity * entity)
        {
            if(needSorting_)
                sort();
            std::vector<Entity*>::iterator it = std::find( entities_.begin(), entities_.end(), entity);
            if(it!=entities_.end())
            {
                entities_.erase(it);
                needSorting_= true;
             }
        }
        /* met à jour la visibilié de toutes les entités qu'il connait
         * sur base de la position du coin supérieur gauche de la partie
         * à afficher 
         */
        void updateVisibility(Coordinate const & topLeft)
        {
            /* je vais considérer que la portion affichée est de 100 * 200...
             * à toi d'adapter ;)
             */
            Coordiante bottomRight(topLeft.x()+100, topLeft.y()+200);
            for(std::vector<Entity*>::iterator it= entities_.begin();it!=entities_.end(); ++ it)
            {
                bool temp= ( (*it)->xpos >=topLeft ().x()||
                             (*it)->xpos <= bottomRight.x()) &&
                           ( (*it)->ypos >=topLeft ().y()||
                             (*it)->xpos <= bottomRight.y());
                 (*it)->setVisibility(temp);
     
            }
        }
        std::vector<Entity*> visibleEntities() const
        {
            std::vector<Entity*> visibles;
            for(std::vector<Entity*>::iterator it= entities_.begin();it!=entities_.end(); ++ it)
           {
                if((*it)->isVisible())
                    visibles.push_back(*it);
           }
           return visibles;
        }
        private:
            std::vector<Entity*> entities_;
            bool needSorting_;
            void sort()
            {
                std::sort(entities_.begin(), entities_.end();
            }
    }
    Et c'est tout

    La plupart des gestionnaires (de sprites, d'ennemis, d'objet d'inventaire et autres) agiraient en r�alit� comme sur base de gestionnaires d'�v�nement, et pourraient tr�s bien �tre consid�r�s comme des "visiteurs" d'�v�nement

    Nous avons donc une hi�rarchie d'�v�nements (qui seraient les objets visit�s) et une hi�rarchie de gestionnaires d'�v�nements

    La classe de base de l'�v�nement ressemblerait �
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    class EventManager;
    class Event
    {
        public:
            virtual ~Event(){}
    };
    et serait, d�riv�e en plusieurs grandes cat�gories d'�v�nement, comme, par exemple, les �v�nements propres � des sprites:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class SpriteEvent : public Event
    {
        public:
           /* on sait, quand on travaille sur un événement propre aux sprites
            * que c'est le SpriteManager qui devra gérer l'événement :D
            * seulement, on ne sait pas encore comment il va le gérer ;)
            */
            virutal void accept(SpriteManager &) = 0;
    };
    et cette classe sera, par exemple, elle-m�me d�riv�e en SpriteCreationEvent (l'�v�nement qui provoquera la cr�ation du sprite ) et SpriteDestructionEvent (l'�v�nement qui en provoquera la destruction )

    Cela prendra la forme de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    class SpriteCreationEvent : public SpriteEvent
    {
        public:
            virtual void accept(SpriteManager & sm)
            {
                sm.visit(*this);
            }
            /* les informations requises pour la création du sprite ;) */
    };
    class SpriteDestructionEvent : public SpriteEvent
    {
        public:
            virtual void accept(SpriteManager & sm)
            {
                sm.visit(*this);
            }
            const Sprite * toDestruct() const {return sprite_;}
        private:
            Sprite * sprite_;
    };
    Quant au SpriteManager, il va r�agir � ces �v�nements, et g�rer le sprite dont la construction est demand�e par l'un et la destruction demand�e par l'autre
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    class SpriteManager
    {
        public:
            /* pour la facilité, on peut décider que le spriteManager connait le 
             * monde, mais l'idéal serait quand meme de faire sans :D
             */
            SpriteManger(World &w):world_(w){}
            void visit(SpriteCreationEvent const & sce)
            {
                /* on récupère ici les informations nécessaires à la création
                 * du sprite
                 */
                /* puis on en demande la création à la fabrique de sprites */
                Sprite* toadd = facotry_.create(/* paramètres utiles */);
                registerSprite(toadd);
            }
            void visit(SpriteDestructionEvent const & sde)
            {
                const Sprite* todell = sde.toDestruct();
                unregisterSprite(todell);
            }
            void update()
            {
                 /* on calcule le temps, qui servira de base pour la mise à jour
                  * de tous les sprites ;)
                  */
                 int time = /* ... */
                /* puis on demande à tous les sprites de se mettre à jour en
                 * fonction de ce temps ;)
                 */
                for(std::vector<Sprite*>:iterator it=sprites_.begin(); it!=sprites_.end(); ++it)
                    (*it)->updatePosition(time);
            }
        private:
            World & world_;
            SpriteFactory factory_;
            std::vector<Sprite*> sprites_;
            bool needSorting_;
            /* l'enregistrement d'un sprite se fait en deux temps :
             * auprès du monde pour qu'il puisse le gérer en tant qu'entité
             * et auprès du gestionnaire lui meme, pour qu'il puisse le gérer en
             * tant que sprite ;)
             */
             void registerSprite(Sprite * toadd)
             {
                 world_.registerEntity(toadd);
                 sprites_.push_back(toadd);
             }
            /* le "désenregistrement" d'un sprite se fait de la meme manière ;)
             */
             void registerSprite(Sprite * torem)
             {
                 world_.unregisterEntity(torem);
                 if( needSorting_)
                     sort();
     
                std::vector<Sprite*>::iterator it = std::find( sprites_.begin(), sprites_.end(), torem);
                if(it!=sprites_.end())
                {
                    sprites_.erase(it);
                    needSorting_= true;
                 }
                 delete  torem;
             }
            void sort()
            {
                std::sort(entities_.begin(), entities_.end();
                 needSorting_ = false;
            }
    };
    et tu aurais, bien �videmment, quelque chose de tr�s similaire pour ce qui est de la gestion des ennemis, des �l�ments de d�cors (mobiles, s'il y en a et non mobiles), des objets d'inventaire ou de toute grande cat�gorie d'Entity que tu pourrais g�n�raliser

    Le render pourrait alors prendre une forme proche de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class Render
    {
        public:
            void draw(World const &w)
            {
                std::vector<Entity*>  todraw= w.visibleEntities();
                for(std::vector<Entity*>::iterator it= todraw_.begin(); it!=todraw_.end(); ++ it)
               {
                    (*it)->draw();
               }
            }
            void clear()
            {
                /* ce qu'il faut pour faire le ménage */
            }
            /* le reste qui peut l'aider dans sa tache :D */
    };
    Le tout serait amoureusement mis en oeuvre et utilis� par... ton GameEngine, sous une forme sans doute proche de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    class GameEngine
    {
        public:
            GameEngine():spriteManager_(world_),
                          ennemiManager_(world_),
                          itemsManager_(world_),
                          setsManager_(world_){}
             void run()
             {
                  setManager_load("filename");
                  while(!stop)
                  {
                     /* en fait, il faudrait une machine à état, car on devra
                      * sans doute gérer le menu principal et / ou la gestion
                      * des options de jeu, mais pour ce qui en est du jeu,
                      * cela pourrait se limiter à 
                      */
                      computeChanges();
                      update();
                      soundPlayer_.play();
                      draw();
                  }
              }
        private:
            World world_;
            Coordinate visiblePositionStart_;
            SpriteManager spriteManager_;
            EnnemyManager ennemiManager_;
            ItemsManager itemsManager_;
            /* tout ce qu'il faut pour que le gameEngine fonctionne :D */
            void comupteChanges()
            {
                /* gestion du temps, des événements, de la popote interne ;)
                 */
            }
            void update()
            {
                /* toutes les mises à jour utiles, dont */
                world.updateVisibility(visiblePositionStart_);
            }
             void draw()
             {
                  render_.clear();
                  render_.draw(world_);
    };
    J'ai fait tout cela en vitesse, et je n'ai pas test� le code, bien entendu...

    Il y a donc tr�s certainement des choses � rajouter, � modifier ou � adapter, mais tu devrais maintenant avoir tout ce qu'il te faut pour y arriver
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

Discussions similaires

  1. [DESIGN J2ME] Utilisation du pattern STATE ?
    Par BerBiX dans le forum Java ME
    R�ponses: 0
    Dernier message: 04/12/2008, 15h55
  2. [Strat�gie] Pattern Strategie avec parametres variables
    Par new.proger dans le forum Design Patterns
    R�ponses: 3
    Dernier message: 10/06/2007, 20h48
  3. BDS - utilisation des Patterns
    Par RamDevTeam dans le forum Delphi .NET
    R�ponses: 1
    Dernier message: 05/11/2006, 17h35
  4. R�ponses: 4
    Dernier message: 22/12/2004, 14h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo