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

SDL Discussion :

Singleton et OpenGL


Sujet :

SDL

  1. #1
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut Singleton et OpenGL
    Bonjour,

    J'ai un petit code à vous montrer, si ça vous dérange pas de regarder ça deux minutes ^^.

    Voilà je crois que j'ai du le dire sur un autre topic (je crois), mais je reçoi bientôt (normalement) un livre sur l'OpenGL mais le truc c'est qu'il utilise pour le fenêtrage et les événements, ainsi que pour la souris (enfin tout ce qu'OpenGL gère pas), l'API Win32. Après l'avoir essayer dans la programmation de jeux c'est vraiment chiant comme API. Beaucoup de choses à écrire pour peu. C'est pour ça que j'ai commencé à regarder SDL en attendant de recevoir le livre, il parait que le couple OpenGL / SDL est un bon choix.

    Bref, au niveau de l'implantation (d'un coup j'ai un doute, implantation ou implémentation ? ), je préfère tout séparer du main (je faisais comme ça en Win32), j'ai cru comprendre que ça portait le nom de Singleton ou un truc du genre. Et d'ailleurs, avant de copier le code, une question : pourquoi tous les codes que je vois commencent avec des C ? Du genre CAffichage, CMachin, CBidule,... Tu dois voir de quoi je parle ^^.

    Bref, j'ai donc ça :

    FenetrageSDL.h :

    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
    // Classe FenetrageSDL
    // Cette classe est un singleton dont le seul but est d'afficher le fenêtrage, le reste de l'affichage
    // est relegué à OpenGL.
     
    #ifndef FENETRAGESDL_H
    #define FENETRAGESDL_H
     
    #include <iostream>
    #include <SDL/SDL.h>
     
    class FenetrageSDL
    {
       public:
          FenetrageSDL (int iLargeur = 640, int iHauteur = 480, int iBPP = 16); // Constructeur
          ~FenetrageSDL (); // Destructeur
     
          bool Init (); // Initialisation de l'affichage
          SDL_Surface * LireEcran () {return m_pEcran;}
          void ChangerDimensions (int, int);
     
       private:
          int m_iLargeur, m_iHauteur, m_iBPP;
          SDL_Surface * m_pEcran; // Pointeur vers la fenêtre
    };
     
    #endif // FENETRAGESDL_H
    FenetrageSDL.cpp :

    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
    #include "FenetrageSDL.h"
     
    FenetrageSDL::FenetrageSDL (int iLargeur, int iHauteur, int iBPP)
       : m_iLargeur (iLargeur), m_iHauteur (iHauteur), m_iBPP (iBPP)
    {
       // Rien à faire
    }
     
    FenetrageSDL::~FenetrageSDL()
    {
       SDL_Quit (); // Se charge de tout nettoyer
    }
     
    bool FenetrageSDL::Init ()
    {
       // Initialise les sous-systèmes SDL
       if (SDL_Init (SDL_INIT_VIDEO) < 0)
       {
          std::cerr << "Impossible d'initialiser SDL : " << SDL_GetError ();
          return false;
       }
     
       m_pEcran = SDL_SetVideoMode (m_iLargeur, m_iHauteur, m_iBPP, SDL_HWSURFACE | SDL_DOUBLEBUF);
     
       // On vérifie la valeur de retour de la fonction
       if (m_pEcran == NULL)
       {
          std::cerr << "Impossible d'initialiser la video : " << SDL_GetError ();
          return false;
       }
     
       return true; // Tout s'est déroulé comme prévu, on renvoie true
    }
     
    void FenetrageSDL::ChangerDimensions (int iLargeur, int iHauteur)
    {
       m_iLargeur = iLargeur;
       m_iHauteur = iHauteur;
     
       m_pEcran = SDL_SetVideoMode (m_iLargeur, m_iHauteur, m_iBPP, SDL_HWSURFACE | SDL_DOUBLEBUF);
    }
    Et main :

    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
    // Inclusion des en-têtes
    #include <cstdlib>
    #include <iostream>
    #include <boost/shared_ptr.hpp>
    #include <SDL/SDL.h>
     
    #include "FenetrageSDL.h"
     
    // Structure contenant toutes les variables globales
    typedef struct VARGlobales
    {
       SDL_Surface * pEcran; // Pointeur vers la fenêtre d'affichage
       SDL_Surface * pBitmapCB; // Pointeur intelligent vers un bitmap
       SDL_Event event;
    } VARGlobales;
     
    VARGlobales sParam = {NULL, NULL, 0};
     
    // Prototypes de fonction
    bool ChargerImages ();
    void Dessiner ();
    void Nettoyer ();
     
    int main (int argc, char** argv)
    {
       atexit (SDL_Quit);
     
       // Pointeur intelligent vers un objet FenetrageSDL
       boost::shared_ptr <FenetrageSDL> pFenetre (new FenetrageSDL (800, 600, 32));
     
       if (pFenetre->Init () == false)
          return 1;
     
       // On initialise le pointeur de la structure, pour plus de facilité
       sParam.pEcran = pFenetre->LireEcran ();
     
       // On charge l'image
       if (!ChargerImages())
          return 1;
     
       Dessiner ();
     
       SDL_Flip (sParam.pEcran);
     
       bool bFin = false;
     
       while (bFin == false)
       {
          // Boucle principale
          while (SDL_PollEvent (&sParam.event))
          {
             switch (sParam.event.type)
             {
                case SDL_QUIT:
                   bFin = true;
                   break;
                case SDL_KEYDOWN:
                   if (sParam.event.key.keysym.sym == SDLK_ESCAPE)
                      bFin = true;
                   else if (sParam.event.key.keysym.sym == SDLK_UP)
                   {
                      pFenetre->ChangerDimensions (1024, 768);
                      sParam.pEcran = pFenetre->LireEcran ();
                      Dessiner ();
                      SDL_Flip (sParam.pEcran);
                   }
                   else if (sParam.event.key.keysym.sym == SDLK_DOWN)
                   {
                      pFenetre->ChangerDimensions (640, 480);
                      sParam.pEcran = pFenetre->LireEcran ();
                      Dessiner ();
                      SDL_Flip (sParam.pEcran);
                   }
                   break;
             }
          }
       }
     
       void Nettoyer ();
     
       return 0;
    }
     
    bool ChargerImages ()
    {
        // On charge l'image
       sParam.pBitmapCB = SDL_LoadBMP ("cb.bmp");
     
       if (sParam.pBitmapCB == NULL)
       {
          std::cerr << "Impossible de charger le bitmap : " << SDL_GetError ();
          return false;
       }
     
       return true; // Tout s'est bien passé
    }
     
    void Dessiner ()
    {
       // On dessine l'image
       SDL_Rect offset;
       offset.x = 0;
       offset.y = 0;
     
       SDL_BlitSurface (sParam.pBitmapCB, NULL, sParam.pEcran, &offset);
    }
     
    void Nettoyer ()
    {
       SDL_FreeSurface (sParam.pBitmapCB);
    }
    1) J'ai toujours été étonné sur tous les codes SDL de ne jamais voir de SDL_FreeSurface (sParam.pEcran);. Pourquoi le pointeur vers l'écran n'est jamais deleté ? (d'ailleurs, SDL_FreeSurface == delete ??!!).

    2) Est-ce que le atexit (SDL_Quit) au début du code est nécessaire étant donné que j'utilise un pointeur intelligent pour l'objet FenetrageSDL qui a dans son destructeur le SDL_Quit () ?

    3) Est-ce une bonne technique d'implantation de séparer l'initialisation de l'affichage de la fenetre du main (je veux dire par là, n'est-ce pas pire que de le faire dans le main, car moi je trouve ça plus clair) ? Juste au niveau de ça, après toutes les fonctions de dessin seront gérées par OpenGL.

    4) Y a t'il un petit exemple d'un code affichant une simple fenêtre en mélangeant SDL et OpenGL afin que je voille quelles modifications apporter à SDL pour utiliser OpenGL (le livre que j'ai commandé n'utilise hélas que Win32 pour le fenêtrage, pas d'exemple avec SDL malgré le fait qu'ils en parlent comme étant une solution portable...).

    5) Y a t'il des fuites de mémoires dans mon code ? J'avoue que je me perds un peu avec la SDL_Surface * pEcran de la classe et celle de la structure de variables globales qui pointent vers celle-ci (je préfère faire comme ça, c'est plus simple d'y acceder, sinon il faudrait faire un truc du genre : pFenetre->LirePointeur()->Bidule.

    6) EDIT : j'oubliais, j'ai toujours les deux warning unused variable argc et argv. Et ta technique du void (argc), void (argv) a la fin du code ne fonctionne pas :/

    Mirci ^^

  2. #2
    Membre expert
    Avatar de Eusebe
    Inscrit en
    Mars 2006
    Messages
    1 992
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 992
    Points : 3 344
    Points
    3 344
    Par défaut
    Citation Envoyé par TicTac
    Bonjour,
    Salut,

    Citation Envoyé par TicTac
    Bref, au niveau de l'implantation (d'un coup j'ai un doute, implantation ou implémentation ? ), je préfère tout séparer du main (je faisais comme ça en Win32), j'ai cru comprendre que ça portait le nom de Singleton ou un truc du genre. Et d'ailleurs, avant de copier le code, une question : pourquoi tous les codes que je vois commencent avec des C ? Du genre CAffichage, CMachin, CBidule,... Tu dois voir de quoi je parle ^^.
    Moi je dirais 'implémentation'. Si tout commence par C, c'est que tu dois travailler avec visual C++ ou quelque chose comme ça, non ? Dans ca cas, évites de les utiliser si tu veux que ton code soit portable (enfin, je crois, je ne suis pas un expert, je n'ai jamais utilisé ces classes... ).

    Citation Envoyé par TicTac
    1) J'ai toujours été étonné sur tous les codes SDL de ne jamais voir de SDL_FreeSurface (sParam.pEcran);. Pourquoi le pointeur vers l'écran n'est jamais deleté ? (d'ailleurs, SDL_FreeSurface == delete ??!!).
    La surface créée avec SDL_SetVideoMode est automatiquement libérée par la SDL. Donc il est inutile de le faire.
    SDL_FreeSurface n'est pas delete, car la SDL est écrite en C, et qu'en C Delete n'existe pas .

    Citation Envoyé par TicTac
    2) Est-ce que le atexit (SDL_Quit) au début du code est nécessaire étant donné que j'utilise un pointeur intelligent pour l'objet FenetrageSDL qui a dans son destructeur le SDL_Quit () ?
    Non, ce qu'il faut, c'est que SDL_Quit soit appelé avant la fin du programme. Mais tu peux tout à fait le gérer différemment. Dans ton code, si SDL_Init échous, tu appeleras tout de même SDL_Quit() lors de la destruction de ton objet. Je ne sais pas trop ce que ça fera... Tu pourrais stocker dans ta classe que la SDL a bien été initialisée, pour n'exécuter SDL_Quit() que si tu en as besoin.

    Citation Envoyé par TicTac
    3) Est-ce une bonne technique d'implantation de séparer l'initialisation de l'affichage de la fenetre du main (je veux dire par là, n'est-ce pas pire que de le faire dans le main, car moi je trouve ça plus clair) ? Juste au niveau de ça, après toutes les fonctions de dessin seront gérées par OpenGL.
    Personnellement je trouve ça pas mal. En général, dans mes programmes, main ne contient que quelques lignes, le temps de créer un objet 'application', de l'initialiser et de le lancer...

    Citation Envoyé par TicTac
    4) Y a t'il un petit exemple d'un code affichant une simple fenêtre en mélangeant SDL et OpenGL afin que je voille quelles modifications apporter à SDL pour utiliser OpenGL (le livre que j'ai commandé n'utilise hélas que Win32 pour le fenêtrage, pas d'exemple avec SDL malgré le fait qu'ils en parlent comme étant une solution portable...).
    Je n'ai jamais essayé, mais tu as au moins trois tutoriels dessus sur libsdl.org : http://www.libsdl.org/tutorials.php

    Citation Envoyé par TicTac
    5) Y a t'il des fuites de mémoires dans mon code ? J'avoue que je me perds un peu avec la SDL_Surface * pEcran de la classe et celle de la structure de variables globales qui pointent vers celle-ci (je préfère faire comme ça, c'est plus simple d'y acceder, sinon il faudrait faire un truc du genre : pFenetre->LirePointeur()->Bidule.
    Ca, j'avoue ne pas avoir regardé en détail. En C++, essaie d'utiliser la RAII pour éviter les fuites : http://c.developpez.com/faq/cpp/?pag...POINTEURS_raii

    Citation Envoyé par TicTac
    6) EDIT : j'oubliais, j'ai toujours les deux warning unused variable argc et argv. Et ta technique du void (argc), void (argv) a la fin du code ne fonctionne pas :/
    Si tu ne les utilises pas, pourquoi ne pas simplement faire ça :
    Citation Envoyé par TicTac
    Mirci ^^
    De rien, j'espère que ça t'aide

  3. #3
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par TicTac
    Après l'avoir essayer dans la programmation de jeux c'est vraiment chiant comme API.
    Certes beaucoup de gens aiment bien pourtant (pas moi par contre )

    C'est pour ça que j'ai commencé à regarder SDL en attendant de recevoir le livre, il parait que le couple OpenGL / SDL est un bon choix.
    Tout à fait, les deux vont bien ensembles...

    Bref, au niveau de l'implantation (d'un coup j'ai un doute, implantation ou implémentation ? )
    Implémentation

    je préfère tout séparer du main (je faisais comme ça en Win32), j'ai cru comprendre que ça portait le nom de Singleton ou un truc du genre.
    Un singleton est une classe qui ne permet d'avoir qu'une seule instance créée dans le programme à un moment donné (généralement du début à la fin du programme).
    Donc pour le moment ce n'est pas ton cas...

    Et d'ailleurs, avant de copier le code, une question : pourquoi tous les codes que je vois commencent avec des C ? Du genre CAffichage, CMachin, CBidule,...
    C pour Classe...


    Bref, j'ai donc ça :
    Voyons voir cela...


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
          FenetrageSDL (int iLargeur = 640, int iHauteur = 480, int iBPP = 16); // Constructeur
    Pourquoi 16 ? J'aurais mis 32 par défaut...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    FenetrageSDL::~FenetrageSDL()
    {
       SDL_Quit (); // Se charge de tout nettoyer
    }
    Dangereux dans le sens où il n'est pas conseillé d'appeler plusieurs fois SDL_Quit (bien que les programmeurs de SDL ont bien fait leur boulot, pour le moment, cela n'a pas d'incidences mais ce n'est pas spécifié).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void FenetrageSDL::ChangerDimensions (int iLargeur, int iHauteur)
    {
       m_iLargeur = iLargeur;
       m_iHauteur = iHauteur;
     
       m_pEcran = SDL_SetVideoMode (m_iLargeur, m_iHauteur, m_iBPP, SDL_HWSURFACE | SDL_DOUBLEBUF);
    }
    Attention, si tu vises une fenêtre OpenGL, il faudra réinitialiser tout le contexte OpenGL (textures, Display lists...) à cet endroit...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    // Structure contenant toutes les variables globales
    typedef struct VARGlobales
    {
       SDL_Surface * pEcran; // Pointeur vers la fenêtre d'affichage
       SDL_Surface * pBitmapCB; // Pointeur intelligent vers un bitmap
       SDL_Event event;
    } VARGlobales;
    Je ne comprends pas l'avantage de mettre une variable locale (event) dans la structure globale. Ce n'est pas pratique et dangereux à mon avis...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    VARGlobales sParam = {NULL, NULL, 0};
    event étant une structure, il faudrait écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    VARGlobales sParam = {NULL, NULL, {0}};
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
       atexit (SDL_Quit);
    Pourquoi le faire ici, tu le fais dans le destructeur de ton futur singleton... (Par contre, il faut arriver à prouver que la destruction de ton singleton se fera après tous les appels SDL... (donc il n'y en aura plus après...)

    Je crois que c'est une des questions, non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
       if (pFenetre->Init () == false)
          return 1;
    Non, utiliser EXIT_SUCCESS et EXIT_FAILURE !!!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
       // On initialise le pointeur de la structure, pour plus de facilité
       sParam.pEcran = pFenetre->LireEcran ();
    Je ne suis pas d'accord... Il y a une redondance dans ton code. Dans un programme aussi simple, cela est mauvais signe...

    Soit la surface représentant l'écran est dans la structure globale, soit elle est dans le singleton mais ne fait pas une copie... Que se passe-t-il si tu changes la taille de la fenêtre, est-ce que tu peux garantir que si tu modifies la surface du singleton, la variable globale sera mise à jour ??

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       // On charge l'image
       if (!ChargerImages())
          return 1;
    EXIT_FAILURE ou EXIT_SUCCESS...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       Dessiner ();
     
       SDL_Flip (sParam.pEcran);
    Ce n'est pas la façon habituelle de procéder... Ce code devrait se trouver dans la boucle événementielle et on redessine même si rien ne change... Bien que cela marche ici, ce code est un cas particulier, autant prendre les bonnes habitudes...

    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
     
                   else if (sParam.event.key.keysym.sym == SDLK_UP)
                   {
                      pFenetre->ChangerDimensions (1024, 768);
                      sParam.pEcran = pFenetre->LireEcran ();
                      Dessiner ();
                      SDL_Flip (sParam.pEcran);
                   }
                   else if (sParam.event.key.keysym.sym == SDLK_DOWN)
                   {
                      pFenetre->ChangerDimensions (640, 480);
                      sParam.pEcran = pFenetre->LireEcran ();
                      Dessiner ();
                      SDL_Flip (sParam.pEcran);
                   }
    Ok tu mets bien tout à jour mais attention, dans un code plus compliqué cette redondance va te coûter cher...

    Pourquoi le void ? Et c'est ici que tu peux mettre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Nettoyer();
    (void) argc;
    (void) argv;

    Ok maintenant les questions...

    1) J'ai toujours été étonné sur tous les codes SDL de ne jamais voir de SDL_FreeSurface (sParam.pEcran);. Pourquoi le pointeur vers l'écran n'est jamais deleté ? (d'ailleurs, SDL_FreeSurface == delete ??!!).
    C'est normal, la surface de l'écran sera libérée par SDL_Quit, ce n'est pas au programmeur de le faire...

    D'ailleurs, dans l'implémentation actuelle, SDL_FreeSurface ne fera rien dans le cas où on lui passe sParam.pEcran...

    Vu que la SDL est plutôt en C qu'en C++ (du moins à ce que j'ai vu) il y a un free dans SDL_FreeSurface mais penser que SDL_FreeSurface == free serait naïf , il y a beaucoup plus de choses dans le code de cette fonction...

    2) Est-ce que le atexit (SDL_Quit) au début du code est nécessaire étant donné que j'utilise un pointeur intelligent pour l'objet FenetrageSDL qui a dans son destructeur le SDL_Quit () ?
    En principe non, mais il faut prouver que l'appel à SDL_Quit se fait en dernier et que donc aucun autre appel à SDL se fait après. Ce qui est plus difficile à faire qu'utiliser simplement atexit...
    Personnellement, je n'utilise ni l'un ni l'autre. Je me débrouille pour sortir du programme au même endroit et j'ajoute explicitement un SDL_Quit à cet endroit...


    3) Est-ce une bonne technique d'implémantation de séparer l'initialisation de l'affichage de la fenetre du main (je veux dire par là, n'est-ce pas pire que de le faire dans le main, car moi je trouve ça plus clair) ? Juste au niveau de ça, après toutes les fonctions de dessin seront gérées par OpenGL.
    Je ne trouve pas cela pose beaucoup de problème de le laisser dans le main mais effectivement, on peut le séparer...

    4) Y a t'il un petit exemple d'un code affichant une simple fenêtre en mélangeant SDL et OpenGL afin que je voille quelles modifications apporter à SDL pour utiliser OpenGL (le livre que j'ai commandé n'utilise hélas que Win32 pour le fenêtrage, pas d'exemple avec SDL malgré le fait qu'ils en parlent comme étant une solution portable...).
    Il y a la réponse dans la FAQ :
    http://jeux.developpez.com/faq/sdl/?...OPENGL_fenetre

    Sinon dans la page sources SDL, je crois que tous les sources Graphisme sont en OpenGL (au moins celui là : Application de textures OpenGL )

    http://jeux.developpez.com/sources/sdl/?page=graphisme

    5) Y a t'il des fuites de mémoires dans mon code ? J'avoue que je me perds un peu avec la SDL_Surface * pEcran de la classe et celle de la structure de variables globales qui pointent vers celle-ci (je préfère faire comme ça, c'est plus simple d'y acceder, sinon il faudrait faire un truc du genre : pFenetre->LirePointeur()->Bidule.
    Pas que je vois... Il ne faut pas libérer le pEcran. Non tu peux utiliser une variable locale lorsque tu en as besoin :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SDL_Surface *monecran = pFenetre->LirePointeur();
    int blabla = monecran->Bidule;
    6) EDIT : j'oubliais, j'ai toujours les deux warning unused variable argc et argv. Et ta technique du void (argc), void (argv) a la fin du code ne fonctionne pas :/
    J'ai répondu à cette question je crois...

    Jc

  4. #4
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par Eusebe
    Si tu ne les utilises pas, pourquoi ne pas simplement faire ça :
    Certaines EDI demandent que le main soit déclaré avec argc et argv (je pense à CodeBlocks avec SDL par exemple). On doit donc les mettre (ou alors peut-être cherché dans les options...)

    Jc

  5. #5
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    Magnifique réponse, comme à ton habitude !
    Certes beaucoup de gens aiment bien pourtant (pas moi par contre )
    Disons que pour initialiser la fenêtre c'est assez compliqué, il faut remplir la structure, sauvegarder la classe de fenêtre... Là tout est plus simple ^^.

    Tout à fait, les deux vont bien ensembles...
    Ok donc il faudra que je fasse : fenêtrage + événements + son avec SDL, et l'affichage avec OpenGL...

    Implémentation
    Ok.

    Un singleton est une classe qui ne permet d'avoir qu'une seule instance créée dans le programme à un moment donné (généralement du début à la fin du programme).
    Donc pour le moment ce n'est pas ton cas...
    Ben pourquoi ? Il n'y a qu'une instance de cet objet (le smart pointer).

    C pour Classe...
    Ok donc ça n'a pas de rapport avec le langage. Bon je vais les mettre alors, ça fait joli en plus . (je suis le seul à trouver ça joli un code bien propre ? )

    Voyons voir cela..
    Voyons tes conseils ^^

    Pourquoi 16 ? J'aurais mis 32 par défaut...
    Euh... Changé :nerd:. En parlant de ça ou j'ai mis 32 par défaut, j'ai toujours eu l'habitude d'écrire les constructeurs comme ça : CFenetrageSDL (int iLargeur = 640, int iHauteur = 480, int iBPP = 32);

    Toutefois souvent ils disent (même dans la FAQ), de mettre des constructeurs par défaut sans arguments, mais là si on ne mets pas d'argument, ça prend ces fonctions par défaut ? Donc inutile d'avoir un constructeur vide ?

    Dangereux dans le sens où il n'est pas conseillé d'appeler plusieurs fois SDL_Quit (bien que les programmeurs de SDL ont bien fait leur boulot, pour le moment, cela n'a pas d'incidences mais ce n'est pas spécifié).
    Ok donc il faut mieux utiliser le atexit (SDL_Quit) dans main ? Car si le programme se termine anormalement et que le shared_ptr n'est pas détruit et donc le destructeur n'est pas appelé, yaura des fuites mémoires non ? Alors que même en cas de terminaison anormale, le atexit sera appelé ?

    Attention, si tu vises une fenêtre OpenGL, il faudra réinitialiser tout le contexte OpenGL (textures, Display lists...) à cet endroit...
    Je m'en doute, en fait le redimensionnement je l'ai fait à l'arrache juste comme ça sans me documenter voir si il existait des fonctions pour ça,... Je vais l'enlever.

    Je ne comprends pas l'avantage de mettre une variable locale (event) dans la structure globale. Ce n'est pas pratique et dangereux à mon avis...
    C'est vrai, j'avais pas pensé que de toute façon la variable pour les événements ne pourra être utiliser que dans la boucle évenementielle. Je l'ai mis en variable locale.

    Pourquoi le faire ici, tu le fais dans le destructeur de ton futur singleton... (Par contre, il faut arriver à prouver que la destruction de ton singleton se fera après tous les appels SDL... (donc il n'y en aura plus après...)
    Alors,... le atexit dans main ou dans le destructeur ^^ ? Comment pourrais-je savoir que le pointeur intelligent sera détruit en dernier ? Je pourrais peut-être utiliser un simple pointeur et faire un delete en toute fin de programme, comme ça je suis sur que c'est le dernier détruit. Mais j'aimerais garder un pointeur intelligent dans mon main, c'est tellement joli

    Non, utiliser EXIT_SUCCESS et EXIT_FAILURE !!!
    Euh ok, mais pourquoi ? En C++ console j'ai toujours utilisé le return 0 pour annoncer que le programme s'est bien terminé ^^/ et 1 pour l'inverse.

    Ce n'est pas la façon habituelle de procéder... Ce code devrait se trouver dans la boucle événementielle et on redessine même si rien ne change... Bien que cela marche ici, ce code est un cas particulier, autant prendre les bonnes habitudes...
    J'ai changé, voir code plus bas.

    Pourquoi le void ? Et c'est ici que tu peux mettre :
    Erreur d'inatention Pour tes (void) argc, (void) argv, ça marche, plus de warning, j'avais mis les parenthèses entre les argc et argv :/

    Je ne suis pas d'accord... Il y a une redondance dans ton code. Dans un programme aussi simple, cela est mauvais signe...

    Soit la surface représentant l'écran est dans la structure globale, soit elle est dans le singleton mais ne fait pas une copie... Que se passe-t-il si tu changes la taille de la fenêtre, est-ce que tu peux garantir que si tu modifies la surface du singleton, la variable globale sera mise à jour ??
    Ok donc tu dis qu'il faut pas que j'ai cette variable globale et que je garde seulement celle de la classe pour tout ?

    C'est normal, la surface de l'écran sera libérée par SDL_Quit, ce n'est pas au programmeur de le faire...

    D'ailleurs, dans l'implémentation actuelle, SDL_FreeSurface ne fera rien dans le cas où on lui passe sParam.pEcran...

    Vu que la SDL est plutôt en C qu'en C++ (du moins à ce que j'ai vu) il y a un free dans SDL_FreeSurface mais penser que SDL_FreeSurface == free serait naïf , il y a beaucoup plus de choses dans le code de cette fonction...
    Ce que je voulais dire, c'est que le FreeSurface nous empêche de faire le delete sur le pointeur, ou il faut faire delete quand même ?

    En principe non, mais il faut prouver que l'appel à SDL_Quit se fait en dernier et que donc aucun autre appel à SDL se fait après. Ce qui est plus difficile à faire qu'utiliser simplement atexit...
    Personnellement, je n'utilise ni l'un ni l'autre. Je me débrouille pour sortir du programme au même endroit et j'ajoute explicitement un SDL_Quit à cet endroit...
    Ben alors il suffit de tout simplement faire un SDL_Quit avant le dernier return Sucess du main ? mais que ce passe t'il si le programme termine anormalement et n'arrive pas jusqu'à là ?

    Merci pour les autres liens OpenGL.

    Eusebe >

    Ca, j'avoue ne pas avoir regardé en détail. En C++, essaie d'utiliser la RAII pour éviter les fuites : http://c.developpez.com/faq/cpp/?pag...POINTEURS_raii
    Vais voir ça.


    Voici le code corrigé (j'ai supprimé la fonction ChangerDimensions car je sais pas trop comment on fait ça proprement) :

    CFenetrageSDL (avec un joli C devant :nerd :

    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
    // Classe CFenetrageSDL
    // Cette classe est un singleton dont le seul but est d'afficher le fenêtrage, le reste de l'affichage
    // est relegué à OpenGL.
     
    #ifndef CFENETRAGESDL_H
    #define CFENETRAGESDL_H
     
    #include <iostream>
    #include <SDL/SDL.h>
     
    class CFenetrageSDL
    {
       public:
          CFenetrageSDL (int iLargeur = 640, int iHauteur = 480, int iBPP = 32); // Constructeur
          ~CFenetrageSDL (); // Destructeur
     
          bool Init (); // Initialisation de l'affichage
          SDL_Surface * LireEcran () {return m_pEcran;}
     
       private:
          int m_iLargeur, m_iHauteur, m_iBPP;
          SDL_Surface * m_pEcran; // Pointeur vers la fenêtre
    };
     
    #endif // CFENETRAGESDL_H
    CFenetrageSDL.cpp :
    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
     
    #include "CFenetrageSDL.h"
     
    CFenetrageSDL::CFenetrageSDL (int iLargeur, int iHauteur, int iBPP)
       : m_iLargeur (iLargeur), m_iHauteur (iHauteur), m_iBPP (iBPP)
    {
       // Rien à faire
    }
     
    CFenetrageSDL::~CFenetrageSDL()
    {
       // Rien à faire, le SDL_Quit() étant appelé dans main() à l'arrêt du programme
    }
     
    bool CFenetrageSDL::Init ()
    {
       // Initialise les sous-systèmes SDL
       if (SDL_Init (SDL_INIT_VIDEO) < 0)
       {
          std::cerr << "Impossible d'initialiser SDL : " << SDL_GetError ();
          return false;
       }
     
       m_pEcran = SDL_SetVideoMode (m_iLargeur, m_iHauteur, m_iBPP, SDL_HWSURFACE | SDL_DOUBLEBUF);
     
       // On vérifie la valeur de retour de la fonction
       if (m_pEcran == NULL)
       {
          std::cerr << "Impossible d'initialiser la video : " << SDL_GetError ();
          return false;
       }
     
       return true; // Tout s'est déroulé comme prévu, on renvoie true
    }
    main :

    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
    // Inclusion des en-têtes
    #include <cstdlib>
    #include <iostream>
    #include <boost/shared_ptr.hpp>
    #include <SDL/SDL.h>
     
    #include "CFenetrageSDL.h"
     
    // Structure contenant toutes les variables globales
    typedef struct VARGlobales
    {
       SDL_Surface * pEcran; // Pointeur vers la fenêtre d'affichage
       SDL_Surface * pBitmapCB; // Pointeur intelligent vers un bitmap
    } VARGlobales;
     
    VARGlobales sParam = {NULL, NULL};
     
    // Prototypes de fonction
    bool ChargerImages ();
    void Dessiner ();
    void Nettoyer ();
     
    int main (int argc, char** argv)
    {
       atexit (SDL_Quit);
     
       // Pointeur intelligent vers un objet FenetrageSDL
       boost::shared_ptr <CFenetrageSDL> pFenetre (new CFenetrageSDL (800, 600, 32));
     
       if (pFenetre->Init () == false)
          return EXIT_FAILURE;
     
       // On initialise le pointeur de la structure, pour plus de facilité
       sParam.pEcran = pFenetre->LireEcran ();
     
       // On charge l'image
       if (!ChargerImages())
          return EXIT_FAILURE;
     
       bool bFin = false;
       SDL_Event event;
     
       while (bFin == false)
       {
          // Boucle principale
          while (SDL_PollEvent (&event))
          {
             switch (event.type)
             {
                case SDL_QUIT:
                   bFin = true;
                   break;
                case SDL_KEYDOWN:
                   if (event.key.keysym.sym == SDLK_ESCAPE)
                      bFin = true;
                   break;
             }
             Dessiner ();
             SDL_Flip (sParam.pEcran);
          }
       }
     
       Nettoyer ();
       (void) argc;
       (void) argv;
     
       return EXIT_SUCCESS;
    }
     
    bool ChargerImages ()
    {
        // On charge l'image
       sParam.pBitmapCB = SDL_LoadBMP ("cb.bmp");
     
       if (sParam.pBitmapCB == NULL)
       {
          std::cerr << "Impossible de charger le bitmap : " << SDL_GetError ();
          return false;
       }
     
       return true; // Tout s'est bien passé
    }
     
    void Dessiner ()
    {
       // On dessine l'image
       SDL_Rect offset;
       offset.x = 0;
       offset.y = 0;
     
       SDL_BlitSurface (sParam.pBitmapCB, NULL, sParam.pEcran, &offset);
    }
     
    void Nettoyer ()
    {
       SDL_FreeSurface (sParam.pBitmapCB);
    }
    Voilà, j'espère qu'on arrive bientôt à un bon petit truc bien propre pour l'affichage de ma fenêtre dans mes futurs programme OGL. ^^

    Pour le problème du pEcran que tu as soulevé, le problème c'est que le pointeur intelligent est dans main, et que dans les autres fonctions (Dessiner,...), j'ai besoin de ce pointeur vers la surface de l'écran, je suis obligé de mettre une copie en globale :/.

    EDIT : ah ouais j'avais une autre question à propos du Double buffering. Dans mon premier livre de prog de jeux (celui avec l'API Win32), on devait le coder nous même (on utilisait un contexte de périphérique en mémoire manuellement, puis un bitmap temporaire, on écrivait tout sur ce bitmap temporaire puis on copiait ce bitmap temporaire sur le contexte principale). Là tout est geré automatiquement ?

    Merci ^^

  6. #6
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Magnifique réponse, comme à ton habitude
    Pas la peine de me lancer des fleurs

    Citation Envoyé par TicTac
    Ok donc il faudra que je fasse : fenêtrage + événements + son avec SDL, et l'affichage avec OpenGL...
    Oui

    Ben pourquoi ? Il n'y a qu'une instance de cet objet (le smart pointer).
    Non, un singleton ne permet pas de créer deux instances séparés. Ton code permet de faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       // Pointeur intelligent vers un objet FenetrageSDL
       boost::shared_ptr <CFenetrageSDL> pFenetre (new CFenetrageSDL (800, 600, 32));
       // 2ème Pointeur intelligent vers un objet FenetrageSDL
       boost::shared_ptr <CFenetrageSDL> pFenetre2 (new CFenetrageSDL (800, 600, 32));
    Ok donc ça n'a pas de rapport avec le langage. Bon je vais les mettre alors, ça fait joli en plus . (je suis le seul à trouver ça joli un code bien propre ? )
    Non j'aime du code bien propre après mettre le C ou non, cela m'indiffére...


    Toutefois souvent ils disent (même dans la FAQ), de mettre des constructeurs par défaut sans arguments, mais là si on ne mets pas d'argument, ça prend ces fonctions par défaut ? Donc inutile d'avoir un constructeur vide ?
    Par définition, tu as déjà écrit le constructeur vide par les valeurs par défaut. Doncc tu suis bien ce qui est dit dans les FAQ. Personnellement, je déclare explicitement les différents constructeurs mais probablement parce que je suis un programmeur C faisant du C++...

    Ok donc il faut mieux utiliser le atexit (SDL_Quit) dans main ? Car si le programme se termine anormalement et que le shared_ptr n'est pas détruit et donc le destructeur n'est pas appelé, yaura des fuites mémoires non ? Alors que même en cas de terminaison anormale, le atexit sera appelé ?
    C'est en effet ce que je ferais si j'étais sérieux (voir la discussion sur le atexit et les sorties anormales qui va venir bientôt...)

    Je m'en doute, en fait le redimensionnement je l'ai fait à l'arrache juste comme ça sans me documenter voir si il existait des fonctions pour ça,... Je vais l'enlever.
    C'est en effet un truc lourd à gérer sans demander de relancer le programme...

    C'est vrai, j'avais pas pensé que de toute façon la variable pour les événements ne pourra être utiliser que dans la boucle évenementielle. Je l'ai mis en variable locale.
    C'est plus sûr à mon humble avis...

    Alors,... le atexit dans main ou dans le destructeur ^^ ? Comment pourrais-je savoir que le pointeur intelligent sera détruit en dernier ? Je pourrais peut-être utiliser un simple pointeur et faire un delete en toute fin de programme, comme ça je suis sur que c'est le dernier détruit. Mais j'aimerais garder un pointeur intelligent dans mon main, c'est tellement joli
    Tu ne peux pas le savoir, c'est pour cela que atexit est plus sûr...

    Ben alors il suffit de tout simplement faire un SDL_Quit avant le dernier return Sucess du main ? mais que ce passe t'il si le programme termine anormalement et n'arrive pas jusqu'à là ?
    Ok, voici la discussion sur SDL_Quit et toute libération de mémoire :

    Sur une sortie anormale genre segfault, il n'y a rien à faire. Aucune solution ne sera satisfaisante, ce sera au système de tout gérer et tout libérer.

    Sur une sortie contrôlée (les fichiers de données ne sont pas présents ou corrompus), alors atexit est mieux mais en principe tu n'as pas seulement SDL_Quit à appeler, il y a sûrement des allocations dynamiques à libérer, des textures OpenGL à enlever...

    Bref, il y aurait énormément de choses à faire. Généralement, sur une sortie anormale du programme, on quitte tout en courant aussi vite que possible et on laisse le système le gérer.

    C'est pas forcément la meilleure solution et la plus propre serait d'avoir une fonction Nettoyer (comme tu as) qui se fait appeler grâce à la fonction atexit et libére toute la mémoire allouée dynamiquement, ferme tous les fichiers ouverts et fait un SDL_Quit.

    Euh ok, mais pourquoi ? En C++ console j'ai toujours utilisé le return 0 pour annoncer que le programme s'est bien terminé ^^/ et 1 pour l'inverse.
    Parce que dépendant du système sous lequel tu te trouves, 0 ne veut pas forcément dire que tu quittes correctement et 1 l'inverse... Ton code sera plus portable en utilisant EXIT_SUCCESS et EXIT_FAILURE...


    Ok donc tu dis qu'il faut pas que j'ai cette variable globale et que je garde seulement celle de la classe pour tout ?
    En effet, si tu as une seule utilisation alors oui. Sinon je passerais par l'intermédiaire d'une variable locale pour l'ensemble de la fonction qui en a besoin. Mais dans un programme SDL/OpenGL cette surface est presque jamais utilisée.

    Ce que je voulais dire, c'est que le FreeSurface nous empêche de faire le delete sur le pointeur, ou il faut faire delete quand même ?
    SDL_FreeSurface empêche de libérer la surface écran et il ne faut pas le faire à la main. SDL_Quit s'en charge.

    Pour le problème du pEcran que tu as soulevé, le problème c'est que le pointeur intelligent est dans main, et que dans les autres fonctions (Dessiner,...), j'ai besoin de ce pointeur vers la surface de l'écran, je suis obligé de mettre une copie en globale :/.
    En effet, quelque chose doit être en global. Généralement, j'ai les modules du jeu qui le seront, par exemple le moteur du jeu sera en global. De toute façon puisque je mets mon code d'initialisation dans le main et le code pour appeler le rendu et le flip dans le main, le problème ne se pose pas vraiment. SDL/OpenGL n'utilise pas cette surface pour autre chose (sauf cas rares)

    EDIT : ah ouais j'avais une autre question à propos du Double buffering. Dans mon premier livre de prog de jeux (celui avec l'API Win32), on devait le coder nous même (on utilisait un contexte de périphérique en mémoire manuellement, puis un bitmap temporaire, on écrivait tout sur ce bitmap temporaire puis on copiait ce bitmap temporaire sur le contexte principale). Là tout est geré automatiquement ?
    Plus personne ne le gére tout seul. C'est à cela que sert SDL_Flip... Donc la réponse est oui tout est géré automatiquement...

    Jc

  7. #7
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    Ben merci, j'ai plus rien à dire ^^. Me reste plus qu'à apprendre OpenGL maintenant ^^. Pour le Singleton, je vais revoir le tutorial sur Developpez.com, je ne sais pas trop comment faire pour empêcher d'avoir plusieurs objets :/.

  8. #8
    Membre expert
    Avatar de Eusebe
    Inscrit en
    Mars 2006
    Messages
    1 992
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 992
    Points : 3 344
    Points
    3 344
    Par défaut
    Citation Envoyé par TicTac
    Pour le Singleton, je vais revoir le tutorial sur Developpez.com, je ne sais pas trop comment faire pour empêcher d'avoir plusieurs objets :/.
    Et quand tu auras un singleton, plus besoin de shared_ptr ou de variable globale, ton objet sera accessible de toute ton appli comme une variable globale...

    Pour la discussion sur l'emplacement de SDL_Quit(), il me semblait qu'en cas de levée d'exception, à moins que l'exception ne soit lancée dans le constructeur d'un objet, les objets créés (et locaux) étaient détruits au fur et a mesure du 'déroulage de la pile'. Donc, placer SDL_Quit() dans le destructeur du singleton me semblait une solution tout aussi sûre que d'utiliser atexit(). En plus, ça me parait une solution plus propre, car plus proche de l'idiome RAII (du moins si je l'ai bien compris ^^').

  9. #9
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par Eusebe
    Et quand tu auras un singleton, plus besoin de shared_ptr ou de variable globale, ton objet sera accessible de toute ton appli comme une variable globale...

    Pour la discussion sur l'emplacement de SDL_Quit(), il me semblait qu'en cas de levée d'exception, à moins que l'exception ne soit lancée dans le constructeur d'un objet, les objets créés (et locaux) étaient détruits au fur et a mesure du 'déroulage de la pile'. Donc, placer SDL_Quit() dans le destructeur du singleton me semblait une solution tout aussi sûre que d'utiliser atexit(). En plus, ça me parait une solution plus propre, car plus proche de l'idiome RAII (du moins si je l'ai bien compris ^^').
    Dans le cas général, on ne peut rien prouver. Il suffit que l'objet soit détruit avant le déroulage ou alors qu'il y a des fonctions SDL dans un autre constructeur...

    Rien n'est moins sûr...

    Jc

  10. #10
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 519
    Points : 5 168
    Points
    5 168
    Par défaut
    tu peux regarder mon post :
    http://www.developpez.net/forums/sho...d.php?t=194798

    j'y ai mis la source de mon singleton gérant le fenêtrage SDL pour OpenGL
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  11. #11
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    Merci, j'irais y jeter un coup d'oeil. Par contre j'ai trouvé un tutorial sur le net, et en français, expliquant comment créer un Singleton, maintenant j'ai bien compris, ce que j'ai fait n'était en effet pas un Singleton.

    Et concernant ton Singleton, j'ai une petite question :

    CDisplay::CDisplay(void)

    CDisplay* CDisplay::Initialize(void)
    {
    if(!m_pInstance)
    m_pInstance = new CDisplay;

    return m_pInstance;
    }

    Tu as ton constructeur et ta fonction Initialize qui va appeler le constructeur ou non. Toutefois si on veut préciser la taille de l'écran, comment cela est mis en place chez toi ? Tu seras obligé de modifier ta fonction Initialize pour lui faire passer les arguments largeur et hauteur puis les passer aux aussi au constructeur ?

    http://tfc.duke.free.fr/coding/singleton.html

    Peut-être un ajout dans les liens du site, car le tuto est vraiment bien foutu. Il y en a un autre sur les listes chaînées sur le même site, extrêmement clair lui ausssi .

  12. #12
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 519
    Points : 5 168
    Points
    5 168
    Par défaut
    Citation Envoyé par TicTac
    Tu as ton constructeur et ta fonction Initialize qui va appeler le constructeur ou non. Toutefois si on veut préciser la taille de l'écran, comment cela est mis en place chez toi ? Tu seras obligé de modifier ta fonction Initialize pour lui faire passer les arguments largeur et hauteur puis les passer aux aussi au constructeur ?
    J'ai réfléchi longuement à ce sujet, finalement j'avais opté pour une initialisation sans paramètres
    en fait, le constructeur possède des paramètres par défaut et comme on crée une fenêtre ça ne fait pas flasher l'écran
    donc quelques modifs des paramètres d'affichage puis un Update et hop tu passes dans la résolution choisie
    c'est un choix

    éventuellement on pourrait lui passer une structure que l'on remplit
    je vais me pencher sur cette possibilité dès que j'ai un instant

    tu peux aussi modifier le code si tu veux
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  13. #13
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    J'ai réfléchi longuement à ce sujet, finalement j'avais opté pour une initialisation sans paramètres
    en fait, le constructeur possède des paramètres par défaut et comme on crée une fenêtre ça ne fait pas flasher l'écran
    donc quelques modifs des paramètres d'affichage puis un Update et hop tu passes dans la résolution choisie
    c'est un choix

    éventuellement on pourrait lui passer une structure que l'on remplit
    je vais me pencher sur cette possibilité dès que j'ai un instant

    tu peux aussi modifier le code si tu veux
    Ben le truc, c'est qu'au début, ça ira, tu pourras passer ta structure :
    Initialize (structure); mais si à chaque fois que tu as besoin d'acceder à l'instance (car d'après ce que je comprends de ton code, en gros dès que tu veux avoir accès à m_pInstance, tu dois appeler la fonction Initialize, là tu devras à chaque fois à avoir à passer ta structure ? Ou soit, tu peux faire ta fonction Initialize et une autre fonction qui se charge juste de retourner le pointeur, comme ça c'est reglé ^^

    D'ailleurs, je sais pas si tu as pensé, mais imaginons que l'utilisateur change de résolution, logiquement quand on quitte et retourne dans le jeu, on doit retrouver la même résolution que celle qu'on a choisi précédemment, mais là vu que t'as pas d'arguments, ça va toujours être tes variables par défaut et donc obliger de rechanger la résolution,... A moins que tu gardes dans un fichier la résolution, que tu créé ton objet normalement avec les valeurs par défaut puis qu'ensuite tu changes dès le départ du jeu avec les données du fichier, mais ça va être lourd,...

    Enfin je dis ça, tu es sans aucun doute mieux placé que moi ^^.

  14. #14
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par TicTac
    Tu as ton constructeur et ta fonction Initialize qui va appeler le constructeur ou non. Toutefois si on veut préciser la taille de l'écran, comment cela est mis en place chez toi ? Tu seras obligé de modifier ta fonction Initialize pour lui faire passer les arguments largeur et hauteur puis les passer aux aussi au constructeur ?
    mmmh... Et si tu avait un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Class *MyScreen = Class::get();
     
    MyScreen->ChangeParam( /* Mes parametres comme ca m'amuse */ );
     
    MyScreen->SpawnWindow(); /* avec les parametres donnés avant */
     
    /* Ensuite pour la 2eme utilisation, il suffit de faire */
    Class *MyScreen2 = Class::get();
    Tu as le droit de sauver dans des variables de classe tes différents parametres, comme ca, pas de probleme pour savoir si c'est dans le constructeur ou non. Le constructeur ne s'occupe même pas d'ouvrir la fenetre.

  15. #15
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 519
    Points : 5 168
    Points
    5 168
    Par défaut
    Citation Envoyé par TicTac
    Ben le truc, c'est qu'au début, ça ira, tu pourras passer ta structure :
    Initialize (structure); mais si à chaque fois que tu as besoin d'acceder à l'instance (car d'après ce que je comprends de ton code, en gros dès que tu veux avoir accès à m_pInstance, tu dois appeler la fonction Initialize, là tu devras à chaque fois à avoir à passer ta structure ? Ou soit, tu peux faire ta fonction Initialize et une autre fonction qui se charge juste de retourner le pointeur, comme ça c'est reglé ^^
    En fait, comme tu y a pensé, il y a une autre fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CDisplay* Instance(void);
    qui retourne l'instance active du singleton

    initialise ne doit être appelée qu'une seule fois au début du programme pour... initialiser l'affichage

    D'ailleurs, je sais pas si tu as pensé, mais imaginons que l'utilisateur change de résolution, logiquement quand on quitte et retourne dans le jeu, on doit retrouver la même résolution que celle qu'on a choisi précédemment, mais là vu que t'as pas d'arguments, ça va toujours être tes variables par défaut et donc obliger de rechanger la résolution,... A moins que tu gardes dans un fichier la résolution, que tu créé ton objet normalement avec les valeurs par défaut puis qu'ensuite tu changes dès le départ du jeu avec les données du fichier, mais ça va être lourd,...

    Enfin je dis ça, tu es sans aucun doute mieux placé que moi ^^.
    La fonction GetCurrent retourne la structure contenant les paramètres de l'affichage courant, ce qui permet de les stocker dans un fichier comme le font tous les jeux et logiciels où on peut modifier des paramètres

    créer une fenêtre avec une résolution par défaut pour ensuite la détruire ça peux parître lourd mais pas tant que cela, seule la fenêtre est créée, pas d'affichage, ensuite elle est détruite puis recréée avec les nouveaux paramètres
    la fenêtre peut permettre par exemple d'afficher des informations de chargement ou un splash screen, une console comme le fait quake avant de se lancer, ect

    mais je comprend et je suis d'accord avec toi sur le principe, on devrait pouvoir initialiser directement l'affichage avec des paramètres sauvegardés
    je suis peut-etre mieux placé pour parler du code que j'ai fait mais en débattre peut permettre de l'améliorer et en discuter avec toi ma donner des idées pour cela

    et puis ce n'est pas l'exemple absolu, c'est ma façon de faire, une façon parmis des dizaines d'autres, n'hésites pas à continuer la discussion, après tout on est là pour ça
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  16. #16
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    En tout cas moi aussi tu m'as donné quelques idées, demain je vais réflechir à d'autres méthodes. Parceque je suis sûr que j'aurais pas encore reçu mon livre OpenGL (foutu poste américaine, 14 jours et toujours rien,... )

    Désolé pour la courte réponse, je sais plus quoi dire . Demain je mettrai mes idées sur papier, ce sera la bäst method ever

  17. #17
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    Voilà j'ai reçu mon bouquin OpenGL aujourd'hui, j'ai pu commencer à créer un triangle qui tourne ^^. Et j'ai aussi essayer d'adapter le code Win32 à SDL, je pensais pas que c'était plus facile, et quel économie de ligne, et cette fois-ci, avec un vrai Singleton (enfin je crois ^^) !! Premièrement j'ai une petite question qui me tarautait, au niveau de la portabilité : ya pas une histoire avec les TRUE-true FALSE-false, en miniscule c'est moins portable je crois ou un truc comme ça non ?

    Enfin bref, voici le code, ça me semble pas mal, je vais pouvoir faire les autres exemples OpenGL du livre avec ma fenêtre SDL ^^

    Ah oui est une autre question, les cerr << que je fais lors des erreurs,... ils s'écrivent ou ?

    EDIT : voici un fichier RAR avec les fichiers OGL et l'exe, ce sera plus facile . Pour tourner en pleine écran, il faut, dans le fichier main.cpp, ligne 27, il faut changer le false par true :
    VarGlob.pFenetreSDL = CFenetrageSDL::Init (VarGlob.iLargeur, VarGlob.iHauteur, false); // Mode fenetre, si true, full screen

    http://www.megaupload.com/fr/?d=VCASFON5 (258 Ko)

    main.cpp :

    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
     
    // Fichiers include
    #include <iostream>
    #include <SDL/SDL.h>
    #include <boost/shared_ptr.hpp>
     
    #include "CFenetrageSDL.h"
    #include "CGfxOpenGL.h"
     
    // Structure contenant les variables globales
    typedef struct tagVARGlobales
    {
       const int iLargeur;
       const int iHauteur;
       CFenetrageSDL * pFenetreSDL;
       CGfxOpenGL * pOpenGL;
    } VARGlobales;
     
    VARGlobales VarGlob = {800, 600, NULL, NULL};
     
    // Prototypes de fonction
    void BoucleEvenements ();
    void Nettoyer ();
     
    int main (int argc, char** argv)
    {
       // Initialisation de la fenêtre via la classe CFenetrageSDL
       VarGlob.pFenetreSDL = CFenetrageSDL::Init (VarGlob.iLargeur, VarGlob.iHauteur);
     
    	// Initialisation d'OpenGL
    	VarGlob.pOpenGL = new CGfxOpenGL ();
    	VarGlob.pOpenGL->SetupProjection (VarGlob.iLargeur, VarGlob.iHauteur);
     
       if (!VarGlob.pOpenGL->Init ())
          return EXIT_FAILURE;
     
       // Boucle évenementielle
       BoucleEvenements ();
     
       Nettoyer (); // On est sortie de la boucle, on a plus qu'à tout nettoyer
     
    	(void) argc; // Ces deux lignes évitent simplement deux warnings
    	(void) argv;
     
    	return EXIT_SUCCESS; // En espérant que le programme arrive toujours jusqu'ici
    }
     
    void BoucleEvenements ()
    {
       SDL_Event event;
       bool bQuit = false;
     
    	while (!bQuit)
    	{
    	   VarGlob.pOpenGL->Prepare (0.0f);
    	   VarGlob.pOpenGL->Render ();
     
    		if (SDL_PollEvent (&event))
    		{
    			switch (event.type)
    			{
    			   case SDL_QUIT:
    				   bQuit = true;
    				   break;
                case SDL_KEYDOWN:
                   if (event.key.keysym.sym == SDLK_ESCAPE)
                      bQuit = true;
                   break;
                default:
                   break;
    			}
          }
       }
    }
     
    void Nettoyer ()
    {
       delete VarGlob.pOpenGL;
       VarGlob.pOpenGL = NULL;
     
       VarGlob.pFenetreSDL->Detruire ();
       VarGlob.pFenetreSDL = NULL;
    }
    CFenetrageSDL.cpp :

    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
    #include "CFenetrageSDL.h"
     
    CFenetrageSDL * CFenetrageSDL::m_pInstance = NULL; // Initialise le pointeur static à NULL
     
    CFenetrageSDL::CFenetrageSDL (const int iLargeur, const int iHauteur, bool bFullScreen)
       : m_iLargeur (iLargeur), m_iHauteur (iHauteur)
    {
       // On initialise le sous-système vidéo
       if (SDL_Init (SDL_INIT_VIDEO) < 0)
       {
          std::cerr << "Echec à SDL_Init : " << SDL_GetError ();
          return;
       }
     
       // On effectue des tâches particulières afin que SDL soit compatible avec OpenGL
       SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); // On active le double buffering
       SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
       SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
       SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
       SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
       SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
     
       if (bFullScreen) // Si bFullScreen vaut true, on active le mode plein écran
          m_pEcran = SDL_SetVideoMode (800, 600, 32, SDL_OPENGL | SDL_FULLSCREEN);
     
       else // Mode fenetré
          m_pEcran = SDL_SetVideoMode (800, 600, 32, SDL_OPENGL);
    }
     
    CFenetrageSDL::~CFenetrageSDL ()
    {
    }
     
    CFenetrageSDL * CFenetrageSDL::Init (const int iLargeur, const int iHauteur, bool bFullScreen)
    {
       if (m_pInstance == NULL) // Premier appel à la fonction Init
       {
          m_pInstance = new CFenetrageSDL (iLargeur, iHauteur, bFullScreen);
       }
     
       return m_pInstance; // On retourne le pointeur
    }
     
    void CFenetrageSDL::Detruire ()
    {
       SDL_Quit ();
     
       if (m_pInstance != NULL)
       {
          delete m_pInstance;
          m_pInstance = NULL;
       }
    }
    CFenetrageSDL.h :

    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
    // Classe CFenetrageSDL
    // Singleton chargé d'initialiser la fenêtre d'affichage SDL
     
    #ifndef CFENETRAGESDL_H
    #define CFENETRAGESDL_H
     
    #include <iostream>
    #include <SDL/SDL.h>
     
    class CFenetrageSDL
    {
       private:
          // Constructeur / Destructeur, déclarés private
          CFenetrageSDL (const int = 800, const int = 600, bool = false);
          virtual ~CFenetrageSDL ();
     
       public:
          static CFenetrageSDL * Init (const int = 800, const int = 600, bool = false); // Initialise
          static void Detruire ();
          SDL_Surface * LireFenetre () {return m_pEcran;} // Retourne un pointeur vers la fenêtre
     
       private:
          static CFenetrageSDL * m_pInstance; // Pointeur static
          SDL_Surface * m_pEcran;
          int m_iLargeur, m_iHauteur;
    };
     
    #endif // CFENETRAGESDL_H
    Le code OGL on s'en fout un peu donc je vais pas le mettre ^^. Si quelqu'un a des conseils pour améliorer encore ça ^^

  18. #18
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par Bakura
    Voilà j'ai reçu mon bouquin OpenGL aujourd'hui, j'ai pu commencer à créer un triangle qui tourne ^^.
    C'est par là qu'il faut commencer

    Premièrement j'ai une petite question qui me tarautait, au niveau de la portabilité : ya pas une histoire avec les TRUE-true FALSE-false, en miniscule c'est moins portable je crois ou un truc comme ça non ?
    Tu codes en C++ donc c'est true et false. En C ce serait TRUE et FALSE ou 1 et 0...

    Ah oui est une autre question, les cerr << que je fais lors des erreurs,... ils s'écrivent ou ?
    Si tu codes sous Windows, la SDL redirige les sorties standard et erreurs vers des fichiers stdout.txt et stderr.txt à mon souvenir. Cherche sur ce forum, shenron avait parler d'une technique pour l'enlever facilement...

    EDIT : voici un fichier RAR avec les fichiers OGL et l'exe, ce sera plus facile . Pour tourner en pleine écran, il faut, dans le fichier main.cpp, ligne 27, il faut changer le false par true :
    Beurk un rar et un exe... Le source et un makefile, c'est tellement mieux...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
       const int iLargeur;
       const int iHauteur;
    Je ne vois pas l'intérêt d'avoir une variable constante dans une structure, généralement j'ai un fichier Define.h qui contient toutes mes constantes...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // Prototypes de fonction
    void BoucleEvenements ();
    void Nettoyer ();
    Il est temps de mettre ces fonctions en static non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	   VarGlob.pOpenGL->Prepare (0.0f);
    	   VarGlob.pOpenGL->Render ();
    Sans voir le code, est-ce nécessaire la fonction Prepare(0.0f) ? Render ne pourrait pas commencer par là ?

    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
     
    		if (SDL_PollEvent (&event))
    		{
    			switch (event.type)
    			{
    			   case SDL_QUIT:
    				   bQuit = true;
    				   break;
                case SDL_KEYDOWN:
                   if (event.key.keysym.sym == SDLK_ESCAPE)
                      bQuit = true;
                   break;
                default:
                   break;
    			}
    Bien indenté serait sympa aussi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void Nettoyer ()
    {
       delete VarGlob.pOpenGL;
       VarGlob.pOpenGL = NULL;
     
       VarGlob.pFenetreSDL->Detruire ();
       VarGlob.pFenetreSDL = NULL;
    }
    On préfére ceci généralement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void Nettoyer()
    {
       delete VarGlob.pOpenGL,VarGlob.pOpenGL = NULL;
     
       VarGlob.pFenetreSDL->Detruire (),VarGlob.pFenetreSDL = NULL;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
       if (bFullScreen) // Si bFullScreen vaut true, on active le mode plein écran
          m_pEcran = SDL_SetVideoMode (800, 600, 32, SDL_OPENGL | SDL_FULLSCREEN);
     
       else // Mode fenetré
          m_pEcran = SDL_SetVideoMode (800, 600, 32, SDL_OPENGL);
    Hmmm, si tu as des constantes pour la taille de la fenêtre, pourquoi ne pas s'en servir ??

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void CFenetrageSDL::Detruire ()
    {
       SDL_Quit ();
     
       if (m_pInstance != NULL)
       {
          delete m_pInstance;
          m_pInstance = NULL;
       }
    }
    Le test sur m_pInstance est inutile :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void CFenetrageSDL::Detruire ()
    {
       SDL_Quit ();
     
       delete m_pInstance,m_pInstance = NULL;
    }
    Ensuite, ce n'est pas encore un vrai singleton, faut mettre en private la fonction operator= et une autre qui m'échappe à l'heure qu'il est...

    Jc

  19. #19
    Membre expert
    Avatar de Eusebe
    Inscrit en
    Mars 2006
    Messages
    1 992
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 992
    Points : 3 344
    Points
    3 344
    Par défaut
    Citation Envoyé par fearyourself
    Ensuite, ce n'est pas encore un vrai singleton, faut mettre en private la fonction operator= et une autre qui m'échappe à l'heure qu'il est...
    Peut-être CFenetrageSDL(CFenetrageSDL const &) ?

  20. #20
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par Eusebe
    Peut-être CFenetrageSDL(CFenetrageSDL const &) ?
    c'était celui là (cela se voit que le C++ n'est pas ma spécialité ?)

    Jc

Discussions similaires

  1. [SOURCE][SDL][OPENGL]Singleton pour gérer le fenêtrage
    Par shenron666 dans le forum Contribuez
    Réponses: 26
    Dernier message: 24/08/2006, 12h01
  2. Directx ou opengl
    Par scorpiwolf dans le forum DirectX
    Réponses: 13
    Dernier message: 07/02/2003, 09h29
  3. OpenGL et *.3ds
    Par tintin22 dans le forum OpenGL
    Réponses: 4
    Dernier message: 06/05/2002, 14h51
  4. OpenGL ou DirectX
    Par Nadir dans le forum DirectX
    Réponses: 6
    Dernier message: 02/05/2002, 13h48
  5. Opengl -- Les surfaces
    Par Anonymous dans le forum OpenGL
    Réponses: 2
    Dernier message: 02/05/2002, 11h14

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