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

Langage C++ Discussion :

Comment passer un pointeur (d'un std::unique_ptr) à une fonction template ?


Sujet :

Langage C++

  1. #41
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Citation Envoyé par Lolilolight Voir le message
    Ok, bah dans ce cas je n'ai qu'à, changer le singleton, et déclarer le gestionnaire de ressources en l'utilisant seulement là ou j'en ai besoin, et rendre les ids invalide plutôt que de les supprimer.

    Bref si j'ai fais ça c'est parce que je ne voulais pas faire de trous en laissant des ids invalide alors j'ai fais en sorte qu'on ne puisse créer qu'une seule instance d'un même type du gestionnaire de ressource, de ce fait, je n'avais pas à remettre à jour les ids pour toutes les instances d'un même type de gestionnaire de ressources utilisée à chaque fois que je supprimais une ressource.

    Car comme tu le dis ça aurait été plus compliqué.j'aurai du faire des effacements en cascade..., donc, j'ai préféré faire un singleton (malgré tout le mal que l'on dit à son sujet) plutôt que de faire un système qui efface les ids en cascade et qui me semble, fort compliqué à faire.
    Le fait est qu'il est tout à fait possible d'éviter le recours au singleton à partir du moment où tu rend la classe que tu voulais avoir sous la forme d'un singleton non copiable / non affectable et que tu veilles à créer l'instance de cette classe "au bon endroit"
    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

  2. #42
    Invité
    Invité(e)
    Par défaut
    Oui en réfléchissant je pourrai éviter le singleton facilement, en rendant les attibuts du singleton statique pour que tout se remette bien à jour pour toutes les instances d'un même type de gestionnaire de ressources, en laissant la classe non copiable, est le problème est réglé, bref, je vais faire ça.

    Je pense que std::recursive_mutex fait cela... (En tout cas je ne peux pas créer deux instances de cette classe et pourtant elle n'a pas l'apparence d'un singleton)

  3. #43
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Citation Envoyé par Lolilolight Voir le message
    Oui en réfléchissant je pourrai éviter le singleton facilement, en rendant les attibuts du singleton statique pour que tout se remette bien à jour pour toutes les instances d'un même type de gestionnaire de ressources, en laissant la classe non copiable, est le problème est réglé, bref, je vais faire ça.
    Tu n'as aucun besoin de rendre tes données statiques si le but est qu'elles se remettent bien à jour!!!

    Le but du mot clé static est uniquement de faire en sorte que l'instance de la donnée soit unique dans une unité de compilation donnée... Ici, l'unicité de la donnée (non seulement au niveau d'une unité de compilation, mais aussi au niveau de l'application toute entière) s'obtient simplement en veillant à ne créer effectivement qu'une seule instance de la donnée en question... Et il n'y a rien de magique ni aucune nécessité de rendre une donnée magique pour atteindre ce but

    Si tu veux faire en sorte que les modifications apportée par une fonction soient répercutées sur une données qui n'appartient pas à la fonction, tu la passe par référence, et basta
    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

  4. #44
    Invité
    Invité(e)
    Par défaut
    Mais, rendre la classe non copiable n'empêche pas de pouvoir créer plusieurs instances de celle-ci, si ?

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    NonCopiable nc1;
    NonCopiable nc2;
    Donc si je fais une variable non statique je devrait la mettre à jour dans nc1 et nc2 si je supprime un id dans l'un des deux gestionnaires de ressource de la même famille.

    A moins de faire, une factory (plutôt qu'un singleton), qui se charge de vérifier si, l'instance n'est pas déjà créée.
    Mais un singleton est fort similaire à une factory (je trouver) car il renvoie une référence sur l'unique objet crée.
    Le pattern factory il me semble sert plutôt à cloner pour éviter un slicing.

  5. #45
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Citation Envoyé par Lolilolight Voir le message
    Mais, rendre la classe non copiable n'empêche pas de pouvoir créer plusieurs instances de celle-ci, si ?
    Non, en effet, rendre ta classe non copiable n'empêchera qu'une seule et unique chose : la création d'une copie non voulue ...
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    NonCopiable nc1;
    NonCopiable nc2;
    Donc si je fais une variable non statique je devrait la mettre à jour dans nc1 et nc2 si je supprime un id dans l'un des deux gestionnaires de ressource de la même famille.

    A moins de faire, une factory (plutôt qu'un singleton), qui se charge de vérifier si, l'instance n'est pas déjà créée.
    Mais un singleton est fort similaire à une factory (je trouver) car il renvoie une référence sur l'unique objet crée.
    Le pattern factory il me semble sert plutôt à cloner pour éviter un slicing.[/QUOTE]C'est pourquoi tu dois veiller à ne créer qu'une instance de la classe qui t'intéresse dans la classe qui concerne le contexte dans lequel elle doit être utilisée.

    Ton application / ta bibliothèque n'est qu'un grand jeu de poupées russes... Tu as le contexte qui correspond à l'application qui va créer une (et une seule ! ) instance de chaque classe qui correspond à d'autres contextes comme les données métier, les vues graphiques, la gestion des sons ou de la communication réseau et, chacun de ces contextes spécifique créera une instance (unique !) des classes qui ont pour but de maintenir les données propres à ces différents contextes.

    Au final, comme tu n'as qu'une seule instance de l'application, tu n'as qu'une seule instance des différents contextes qu'elle utilise et... une seule instance des classes qui s'occupent du maintien "en vie" de tes ressources. Autrement dit, l'unicité des instances est garantie par la manière dont ton application / ta bibliothèque est construite elle-même
    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. #46
    Invité
    Invité(e)
    Par défaut
    Ok, je vois mieux comment je dois faire là.

    Je possède en effet une classe application, je pourrai donc créer les objets unique à partir de cette classe. (Et au pire utiliser l'amitier pour empêcher la création ailleurs)

    Au départ je voulais en fait éviter de devoir dépendre d'un contexte pour pouvoir instancier des classes (et donc pouvoir créer les objets unique en dehors de la classe Application au cas ou le développeur ne voudrais pas dépendre d'un contexte)

    Mais c'était peut être une mauvais idée...

    Toutefois je peux modifier le gestionnaire de ressource facilement pour me passer du singleton, et faire une variable statique dans cette classe pour que tout les objets partagent les mêmes ressources.
    Je pense que c'est ce qui serait le mieux.

  7. #47
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Citation Envoyé par Lolilolight Voir le message
    Ok, je vois mieux comment je dois faire là.

    Je possède en effet une classe application, je pourrai donc créer les objets unique à partir de cette classe. (Et au pire utiliser l'amitier pour empêcher la création ailleurs)
    A vrai dire, je te le déconseille...

    Bien sur, cela te permettrait de placer le constructeur dans l'accessibilité privée et t'assurer que ton objet ne sera construit que par une classe bien précise, mais, d'un autre coté, cela va plus ou moins à l'encontre du DIP (Dependancies Inversion Principe) qui nous dit que tout devrait dépendre d'interface et non d'élément de plus ou moins haut niveau. Or, en déclarant une classe amie, tu place malgré tout une dépendance aussi bien de la classe amie vers la classe qui déclare cette amitié que l'inverse.

    Alors, bien sur, on peut assouplir ce principe en se disant que cela doit, en tout état de cause, être vrai pour les communications "inter-modules" mais qu'il n'est pas particulièrement important de le respecter à l'intérieur d'un module donné. Ce n'est pas faux dans le sens où tu pourrais déclarer la classe qui s'occupe du contexte sonore comme amie de la classe qui s'occupe de maintenir les ressources sonores et sans doute faire pareil avec les différents modules.

    Par contre, si tu décide de rendre ta classe Application amie des classes correspondant aux différents contextes, tu est "hors module", et là, cela devient dangereux
    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

  8. #48
    Invité
    Invité(e)
    Par défaut
    Ouf, ce système de context me semble pas si simple à mettre en place, ça me fait pensé à opengl ou il faut partager un contexte entre plusieurs thread, le partager, changer les états, etc..., de plus les contextes ne peuvent être actif que dans un seul thread à la fois, mais au départ je voulais que les gestionnaires de ressources puisse être accessible par tout les modules, et pas seulement, par le contexte graphique..., ceci est plus dangereux certes car il faut que, quand un gestionnaire de ressource n'est plus utilisé il faut qu'il soit encore accessible par tout les autres modules, mais,ça devient moins dangereux je trouve avec des pointeurs intelligent, qui, eux, partagent les ressources entre les différents module en s'assurant que les ressources soient détruite au bon moment. (C'est à dire quand elles ne sont plus référencées null part)

    Bref ce système de contexte c'est de l'histoire ancienne pour moi, les nouvelles version de opengl n'utilisent plus ça et je pense que cette mode va avoir tendance à disparaître au profit de techniques plus récentes. (A cause de la programmation parallèle)

  9. #49
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    En fait, plutôt que de parler de contexte, je devrais plutôt parler de "modules", dans le sens où c'est ce pour quoi je milite... Et le principal objectif à atteindre est d'en arriver à avoir des modules les plus indépendants possibles les uns des autres : Le module son n'a absolument rien à voir avec le module "réseau" qui n'a lui-même absolument pas besoin de connaitre les ressources utilisées par le module "affichage / vue".

    Une fois que tu as compris cela, tu te rend compte que ces instances que tu veux rendre globales -- afin de les rendre disponibles entre les différents modules -- n'ont absolument aucune raison d'être pour la simple et bonne raison... qu'il n'y a aucune instance d'aucune classe qui doit réellement traverser la frontière des différents modules.

    La seule exception notable, c'est le module regroupant les données métier qui reste, malgré tout, le module central autour duquel gravitent tous les autres modules. Et encore : tu ne devras jamais transmettre une instance d'une classe ayant sémantique d'entité issue de ton module business en entier vers un autre module, quel qu'il soit. Au pire, tu transmettra un identifiant spécifique et quelques données connexes qui pourraient parfaitement n'être que des types primitifs ou des données équivalentes (une position, si tu y tiens, une chaine de caractères dans le pire des cas, ...)

    Et, une fois que ces différents modules sont capables de fonctionner tout seuls, il "n'y a plus qu'à" mettre certains contrôleurs en places qui permettront à tous tes modules de communiquer ensemble (ex : le fait que le lancé d'un sort occasionne l'émission d'un son déterminé ou le fait qu'un message reçu au travers du module réseau occasionne le déplacement d'un pnj au niveau du business et que ce déplacement se répercute sur la position à laquelle ce pnj est affiché au niveau de l'affichage).

    Quoi qu'il en soit, la règle est toujours la même : diviser pour mieux régner et limiter les informations qui sont transmises entre les modules au minimum strictement indispensable pour que cela fonctionne
    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. #50
    Invité
    Invité(e)
    Par défaut
    Oui sauf que ici le gestionnaire de ressource, ne dépend pas d'un module, de plus je n'initialise pas les ressources et les utilise au même endroit, en fait, je charge toutes les textures, sons, etc... dans une méthode load, je crée les objets dans une méthode init en leur passant les ressources que je récupère avec un alias que je passe au gestionnaire de ressource et ensuite, et je les utilisent dans un autre module, donc je me retrouve avec un module de chargement, un module d'initialisation et un module d'affichage.

    Et le développeur peut charger et utiliser les ressources là ou il le veut, mais, j'ai toujours besoin d'avoir accès aux gestionnaire de ressource pour l'utiliser dans les différents modules.

    De plus toutes mes classes sont template, et on peut très bien enregistrer plusieurs gestionnaire de ressource dans un cache, pour ensuite le réutiliser plus tard et le cache peut aussi lui être de différent type si les ressources peuvent être chargée avec une classe dérivée et utilisée avec une classe de base. (Le cache va alors convertir les pointeurs des gestionnaires de ressources dérivés et celui de base)

    Donc bon, comme j'essaye de te le dire depuis quelques posts déjà, je ne peux pas faire comme ça, vu que je veux séparer le chargement et l'utilisation dans plusieurs modules.

    Mon code ressemble à quelque chose comme ceci.

    Code cpp : 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
     
     
    void CustomAppli::onLoad() {
           //Charge toutes les ressources du jeux. (images, sons, modèles 3D, etc...)
           TextureManager& tm = TextureManager::Instance();
           tm.fromFileWithAlias("path", "texture1");
           etc...
    }
    void CustomAppli::onInit() {
           //Intialise tout les objets du jeux, les commandes ainsi que les entity systèmes qui stockeront et mettrons à jour les entitiés du jeux
           TextureManager& tm = TextureManager::Instance();
           Entity entity = Tile(tm.getResourceByAlias("texture1"), Vec3f(0, 0, 0,), Vec3f(100, 100, 0), IntRect(0, 0, 100, 100));
           etc...
           Engine::addEntity(entity);
    }
    void CustomAppli::onRender(RenderComponent* rc) {
           //Dessine les objets sur les composant de rendu, la string correspond à un groupe d'objets et on peut dessiner les objets sur plusieurs composants différents, on peut aussi passer des shaders.
           rc->drawOnComponent("E_TILE");
    }
    void CustomAppli::onDisplay(RenderWindow* window) {
          //Affiche des guis, overlay, etc... sur la fenêtre. (Au dessus des composants de rendu, à ce stade tout les objets de la frame courante du jeux son affiché)
    }
    void CustomAppli::onUpdate(Event event) {
           //Met à jour les objets du jeux.
    }
    void CustomAppli::onExec() {
          //Effectue d'autre traitement en fin de boucle comme par exemple, recevoir des messages réseau.
    }

    Bref ceci me permet d'avoir toute la boucle principale du jeux dans une seule classe, et tout ce qui est définitions des entités dans d'autre classes, et de pouvoir interagir plus facilement entre la boucle principale et les différents objets du jeux.

    Pour réduire le code j'ai aussi fait un système qui permet de sérialiser les objets avant de les transférer d'un programme à l'autre lors des envois réseaux.

    Bref, je peut donc tenir tous les modules dans une seule classe sans devoir passer par une classe pour le rendu qui charge puis qui utilise les ressources, une autre qui effectue les mises à jours, etc..., ce que je trouve quand même être assez lourd. (Enfin, tout du moins, dans les autres moteurs de jeux, je ne m'en sortait pas bien avec leur système.)

    Je trouve que lors de l'utilisation, pouvoir utiliser tout les modules dans une seule classes sans devoir passer des objets ou ce genre de choses est beaucoup plus simple, plus intuitif, si je dois commencer à faire des choses du genre, on doit dériver de tel classe (ou de tel module) pour pouvoir charger les textures et les rendre, cela va vite devenir plus compliqué à l'utilisation, plutôt que d'avoir une variable globale, et de l'utiliser dans diverses méthodes.

    Cela ne m'a jamais posé de problème jusqu'à présent même dans un context multi-thread, d'ailleurs ici j'utilise plusieurs threads (un pour mettre à jour, un pour gérer les événements et un pour afficher et il est possible que plus tard j'en utilise encore d'autres)
    Dernière modification par Invité ; 15/10/2014 à 12h42.

  11. #51
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Citation Envoyé par Lolilolight Voir le message
    Oui sauf que ici le gestionnaire de ressource, ne dépend pas d'un module, de plus je n'initialise pas les ressources et les utilise au même endroit, en fait, je charge toutes les textures, sons, etc... dans une méthode load,
    Et pourquoi ne créerais tu donc pas une fonction membre load dans la classe qui te sert de "façade" à tes différents modules

    Tu crées une fonction load qui charge les objets et les textures dans la facade de ton module... d'affichage et une autre fonction load qui charge les sons dans la facade de ton... module son, et basta !!!
    je crée les objets dans une méthode init
    Tu ne dois pas avoir de fonction init!!!

    Mettons que tu utilises OpenGl pour l'affichage. Tu crées une classe nommée FacadeAffichage, AffichageContext ou ce que tu veux dont le constructeur s'assure de créer un contexte OpenGL valide et dont le destructeur s'occupe d'en faire le ménage. Tu y ajoutes une instance de ton gestionnaire d'objets opengl et une instance de ton gestionnaire de textures sous 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
    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 GlContext{
    public:
        GlContext(int argc, char ** argv,
                        std::string const & title);
        ~GlContext();
        void loadObect(/* ... */);
        void loadTexture(/* ... */);
        void draw(); // trace tous les objets
        void draw(UnType id,/* ... */); //trace uniquement l'objet id avec les paramètres nécessaires
    private:
        ObjectManager objects_;
        TextureManager textures_;
    };
    GlContext::GlContext(int argc, char ** argv,
                        std::string const & title){
     
        glutInit(&argc,argv);
        glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
        glutInitWindowPosition(200,200);
        glutInitWindowSize(640,480);
        glutCreateWindow(title.c_str());
     
        /* initialisation des librairies liées à OpenGL */
        GLenum err = glewInit();
        if (err != GLEW_OK) {
            std::string msg("Anomalie aVec Glew, impossible d'utiliser OpenGL : ");
            msg.append((char*)glewGetErrorString(err));
            throw std::runtime_error(msg);
        }
     
        // Initialisation de SDL_Image
        int ok = IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG);
        if (!ok) {
            throw std::runtime_error("Anomalie aVec SDL_image : impossible de charger une texture");
        }
        // couleur du fond : gris foncé
        glClearColor(0.4, 0.4, 0.4, 1.0);
        /// met l'horloge à jour 
        beginTime_ =mktime(&startTime_);
    }
    GlContext::~GlContext(){
        // terminaison de SDL_Image
        IMG_Quit();
    }
    Et tu crées une classe Application qui prend 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 Application{
    public:
        Application(int argc, char ** argv,
                        std::string const & title): contextGl_(arc,argv,title){
            loadGlContext();
        }
        void run();
    private:
        void loadGlContext(){
            glContext_.loadObject(/* ... */);
            /* ... */;
            glContext_.loadTexture(/* ... */);
            /* ... */
        }
        GlContext contxtGL_;
        /* ... */
    };
    Bien sur, tu fais pareil pour les différents modules (son, réseau, whatever).

    Cela te permet d'avoir une fonction main réellement dépouillée prenant la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main(int argc, char ** argv){
        Application app(arc, argv, "le titre sympa"); // toute l'initialisation se fait ici
        app.run(); // l'application s'exécute
        return 0; // ~Application est appelé ici, le ménage est fait, bonsoir et merci!!!
    }
    en leur passant les ressources que je récupère avec un alias que je passe au gestionnaire de ressource et ensuite, et je les utilisent dans un autre module, donc je me retrouve avec un module de chargement, un module d'initialisation et un module d'affichage.
    Pourquoi vouloir transmettre des ressources entre les modules Chaque module a besoin de ressources qui leur sont propres que diable!!!! Un module son n'a aucun besoin d'avoir une texture, un module d'affichage n'a aucun besoin de disposer d'un flux récupéré du résau et un module réseau n'a aucun besoin de disposer d'un son b...del de m...de!!!

    Tu devras sans doute prévoir un moyen d'identifier les différentes ressources, afin de permettre une communication correcte, mais cela ne va pas plus loin !!!

    Et le développeur peut charger et utiliser les ressources là ou il le veut, mais, j'ai toujours besoin d'avoir accès aux gestionnaire de ressource pour l'utiliser dans les différents modules.
    Non!!!

    Si l'utilisateur veut charger une ressource nécessaire au module d'affichage, il doit le faire dans le contexte qui englobe le contexte d'affichage (autrement dit, dans l'application), mais il ne peut le faire qu'au travers du module d'affichage!!!! idem pour n'importe quel autre module!!!!
    De plus toutes mes classes sont template, et on peut très bien enregistrer plusieurs gestionnaire de ressource dans un cache, pour ensuite le réutiliser plus tard et le cache peut aussi lui être de différent type si les ressources peuvent être chargée avec une classe dérivée et utilisée avec une classe de base. (Le cache va alors convertir les pointeurs des gestionnaires de ressources dérivés et celui de base)
    Rien ne t'empêche de templatiser tes classes... Un gestionnaire de XXX va très certainement se comporter de la même manière qu'un gestionnaire de YYY... Mais cela n'empêche que le gestionnaire de XXX doit se trouver dans une classe qui sert de facade au module qui en a réellement besoin, nulle part ailleurs!!!

    Donc bon, comme j'essaye de te le dire depuis quelques posts déjà, je ne peux pas faire comme ça, vu que je veux séparer le chargement et l'utilisation dans plusieurs modules.
    C'est, justement, la raison pour laquelle la gestion des ressources utilisées par un module spécifique doit être déléguée spécifiquement à ce module particulier
    Mon code ressemble à quelque chose comme ceci.

    Code cpp : 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
     
     
    void CustomAppli::onLoad() {
           //Charge toutes les ressources du jeux. (images, sons, modèles 3D, etc...)
           TextureManager& tm = TextureManager::Instance();
           tm.fromFileWithAlias("path", "texture1");
           etc...
    }
    void CustomAppli::onInit() {
           //Intialise tout les objets du jeux, les commandes ainsi que les entity systèmes qui stockeront et mettrons à jour les entitiés du jeux
           TextureManager& tm = TextureManager::Instance();
           Entity entity = Tile(tm.getResourceByAlias("texture1"), Vec3f(0, 0, 0,), Vec3f(100, 100, 0), IntRect(0, 0, 100, 100));
           etc...
           Engine::addEntity(entity);
    }
    void CustomAppli::onRender(RenderComponent* rc) {
           //Dessine les objets sur les composant de rendu, la string correspond à un groupe d'objets et on peut dessiner les objets sur plusieurs composants différents, on peut aussi passer des shaders.
           rc->drawOnComponent("E_TILE");
    }
    void CustomAppli::onDisplay(RenderWindow* window) {
          //Affiche des guis, overlay, etc... sur la fenêtre. (Au dessus des composants de rendu, à ce stade tout les objets de la frame courante du jeux son affiché)
    }
    void CustomAppli::onUpdate(Event event) {
           //Met à jour les objets du jeux.
    }
    void CustomAppli::onExec() {
          //Effectue d'autre traitement en fin de boucle comme par exemple, recevoir des messages réseau.
    }
    Et moi, je te dis qu'il n'y a aucun besoin d'avoir un singleton (ou un monostate), je te dis que, tu n'as besoin que d'une chose : inciter l'utilisateur a créer une instance de la facade des différents modules dont il a besoin, et utiliser les fonctions de cette facade.

    Tu remarquera que l'exemple que je viens de te donner est finalement très similaire à celui que tu me propose... Si ce n'est que je n'utilise pas de singleton ni de monostate : je m'assure que les gestionnaires de ressources soient simplement créé (et détruits) en meme temps que contexte / modules qui les utilise
    Bref ceci me permet d'avoir toute la boucle principale du jeux dans une seule classe, et tout ce qui est définitions des entités dans d'autre classes, et de pouvoir interagir plus facilement entre la boucle principale et les différents objets du jeux.
    Et la manière dont je te présente les choses le fait aussi... Tout ce qu'il y a à faire, c'est d'invoquer la fonction run et d'en adapter le comportement à l'application créée.

    Alors, bien sur, il faut envisager la transmission de messages entre certains modules, mais ce n'est jamais qu'un système signal /slot à mettre en place (boost::signals2 est l'idéal pour cela )
    Pour réduire le code j'ai aussi fait un système qui permet de sérialiser les objets avant de les transférer d'un programme à l'autre lors des envois réseaux.
    Oui, et alors ?
    Bref, je peut donc tenir tous les modules dans une seule classe sans devoir passer par une classe pour le rendu qui charge puis qui utilise les ressources, une autre qui effectue les mises à jours, etc..., ce que je trouve quand même être assez lourd. (Enfin, tout du moins, dans les autres moteurs de jeux, je ne m'en sortait pas bien avec leur système.)
    Bien sur qu'il faut une classe qui fournit l'accès à toutes les fonctionnalités exposées à l'utilisateur, bien sur qu'il faut pouvoir créer une instance de cette classe, mais le singleton n'est pas le passage obligé
    Je trouve que lors de l'utilisation, pouvoir utiliser tout les modules dans une seule classes sans devoir passer des objets ou ce genre de choses est beaucoup plus simple, plus intuitif, si je dois commencer à faire des choses du genre, on doit dériver de tel classe (ou de tel module) pour pouvoir charger les textures et les rendre, cela va vite devenir plus compliqué à l'utilisation, plutôt que d'avoir une variable globale, et de l'utiliser dans diverses méthodes.
    Il ne s'agit pas de cela, bien au contraire!!!

    Au sein du module, il n'est pas impossible que tu doive, effectivement, envisager de transmettre une référence sur le gestionnaire de ressource utilisé par le module. Mais l'utilisateur du module n'a, à la limite, même pas besoin de savoir qu'il y a un gestionnaire de ressource qui entre en jeu!!! Tout ce qu'il doit savoir, c'est comment charger une ressource et comment indiquer quelle ressource spéciique doit être utilisée lorsque l'on veut spécifiquement utiliser le module sur une ressource particulière!
    Cela ne m'a jamais posé de problème jusqu'à présent même dans un context multi-thread, d'ailleurs ici j'utilise plusieurs threads (un pour mettre à jour, un pour gérer les événements et un pour afficher et il est possible que plus tard j'en utilise encore d'autres)
    Et, lorsque tu décide apporter une modification quelconque, combien de fonction en moyenne dois tu modifier pour résoudre tous les problèmes occasionnés par l'évolution :quesiton:
    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

  12. #52
    Invité
    Invité(e)
    Par défaut
    Ok bah je pense que je vais forcer l'utilisateur, à utiliser un context différent (pour le son, les textures, les shaders, etc...) et faire une seule méthode pour load et initialise, je note ça dans les améliorations à faire.

    Après tout je n'ai qu'à faire deux chose : une classe context avec les différentes fonctions de chargements (que je vais passer template car il y aura possibilité de créer plusieurs contextes pour charger des ressources de type différents), et retiré le singleton.

    Mais bon ça sera juste un contexte de chargement, après il faudra que je trouve un moyen de récupérer les ressources via le context mais je possède un système de signal et de slots pour ça.

  13. #53
    Invité
    Invité(e)
    Par défaut
    Bon voila j'avais déjà fait cela avant en fait je me demande pourquoi j'ai changé.

    En fait pour avoir un contexte graphique il suffit de dérivé de la classe Application et le contexte graphique se détruit à la destruction de l'application gui. (il y a deux constructeurs pour la classe application, un pour avoir un contexte graphique et un autre pour ne pas avoir de contexte graphique)

    La classe ResourceCache qui ne fait rien d'autre que de contenir plusieurs contextes d'un même type. (ou bien les gestionnaires de ressources qui servent de contexte) cela dépendait de quel contexte j'avais besoin) je les déclarais dans la classe qui dérive de l'application gui ainsi seul cette classe à accès au contexte pour les ressources graphiques et les ressources étaient détruite en même temps que les gestionnaires de ressources ou le cache servant de contexte.

    Bref, je vais repasser à se système là car en y réfléchissant c'est vrai que que en dehors de l'application gui, on a pas besoin d'accéder à des textures et de toute façon sans contexte graphique opengl on ne peux pas charger de textures. (Sinon elles ne s'affichent pas)

+ Répondre à la discussion
Cette discussion est résolue.
Page 3 sur 3 PremièrePremière 123

Discussions similaires

  1. Réponses: 8
    Dernier message: 29/07/2013, 18h30
  2. Réponses: 1
    Dernier message: 26/02/2008, 13h54
  3. Réponses: 15
    Dernier message: 25/06/2007, 10h35
  4. Réponses: 2
    Dernier message: 06/05/2007, 13h52
  5. Réponses: 2
    Dernier message: 26/09/2006, 09h56

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