Partage
  • Partager sur Facebook
  • Partager sur Twitter

[SDL] Problème d'affichage

Pas d'erreur, mais pas d'affichage

    31 juillet 2007 à 11:45:08

    Bonjour tout le monde !

    J'ai commencé a faire un jeu du type snake en C++ avec SDL :) . ( j'utilise Code::blocks avenc mingw sous windows )

    Pour l'instant, j'ai fait le menu du jeu et l'éditeur de niveaux.

    Mon problème : le niveau n'est pas affiché à l'écran au démarrage !


    J'ai utilisé une classe menu qui me permet d'afficher les options du menu, et une classe carte qui contient le niveau, et à des méthode pour, afficher la carte dans l'éditeur, ou dans le jeu, pour modifier la carte, sauver ou charger le niveau.

    J'ai vérifié le fichier niveaux.lvl que j'utilise : dans l'éditeur, il sauvegarde bien les modifications dans le fichier, puis quand je demande un cout des valeur du niveau au chargement, j'ai bien les bonnes valeurs ... et il n'afficher pas la carte ! o_O

    Je pense que c'est un problème d'ordre en un SDL_FillRect et les blittage ou le SDL_Flip, mais j'ai pas trouvé l'erreur. :o

    ( mon projet utilise SDL et SDL_ttf )

    Voici les codes :

    classe Carte
    niveaux.h
    /* niveaux.h */

    #ifndef DEF_NIVEAUX
    #define DEF_NIVEAUX

    #define NB_BLOCS_LARGEUR 20
    #define NB_BLOCS_HAUTEUR 20

    class Carte
    {
        public :
        Carte() ;
        ~Carte() ;
        int chargerCarte(std::string fichier = "niveaux.lvl") ;
        int sauverCarte(std::string fichier = "niveaux.lvl") ;

        // méthode à utiliser pour blitter la carte dans l'éditeur
        int afficherJeu(SDL_Surface *ecran) ;

        // méthode à utiliser pour blitter la carte dans le jeu
        int afficherEditeur(SDL_Surface *ecran) ;
        int modifierCarte(int i, int j, int valeur) ;

        // méthode à utiliser pour afficher le terrain choisis dans l'éditeur sous le curseur de la souris
        int afficherTampon(int valeur, SDL_Rect &position,SDL_Surface *ecran) ;


        private :
        char _carte[NB_BLOCS_LARGEUR][NB_BLOCS_HAUTEUR] ;
        SDL_Surface *_vide, *_mur, *_tete, *_queue, *_pommePossible ;
    };

    #endif

     


    niveaux.cpp
    /* niveaux.cpp */

    #include <iostream>
    #include <fstream>

    #include <SDL/SDL.h>
    #include <string>
    #include "constantes.h"
    #include "niveaux.h"

    using namespace std ;

    Carte::Carte()
    {
        // le vide est mis en tout point de la carte
        for(int i = 0 ; i < NB_BLOCS_LARGEUR ; i ++)
        {
            for (int j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
            {
                _carte[i][j] = 0 ;
            }
        }

        // création des surfaces ...
        _vide = SDL_CreateRGBSurface(SDL_HWSURFACE,TAILLE_BLOC,TAILLE_BLOC,BIT_PAR_PIXEL,0,0,0,0);
        _mur = SDL_CreateRGBSurface(SDL_HWSURFACE,TAILLE_BLOC,TAILLE_BLOC,BIT_PAR_PIXEL,0,0,0,0);
        _tete = SDL_CreateRGBSurface(SDL_HWSURFACE,TAILLE_BLOC,TAILLE_BLOC,BIT_PAR_PIXEL,0,0,0,0);
        _queue = SDL_CreateRGBSurface(SDL_HWSURFACE,TAILLE_BLOC,TAILLE_BLOC,BIT_PAR_PIXEL,0,0,0,0);
        _pommePossible = SDL_CreateRGBSurface(SDL_HWSURFACE,TAILLE_BLOC,TAILLE_BLOC,BIT_PAR_PIXEL,0,0,0,0);

        // ... et remplissage de ces surfaces
        SDL_FillRect(_vide,NULL,SDL_MapRGB(_vide->format,128,128,64));
        SDL_FillRect(_mur,NULL,SDL_MapRGB(_mur->format,192,192,192));
        SDL_FillRect(_tete,NULL,SDL_MapRGB(_tete->format,0,255,0));
        SDL_FillRect(_queue,NULL,SDL_MapRGB(_queue->format,128,255,128));
        SDL_FillRect(_pommePossible,NULL,SDL_MapRGB(_pommePossible->format,0,0,128));
    }

    int Carte::afficherEditeur(SDL_Surface *ecran)
    {
        SDL_Rect position ;

        for (int j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
        {
            for (int i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
            {
                // position de la case en pixel
                position.x = i * TAILLE_BLOC ;
                position.y = j * TAILLE_BLOC ;

                // blittage en fonction de la donnée de la carte
                switch(_carte[i][j])
                {
                    case VIDE :
                        SDL_BlitSurface(_vide,NULL,ecran,&position) ;
                    break ;

                    case MUR :
                        SDL_BlitSurface(_mur,NULL,ecran,&position) ;
                    break ;

                    case TETE :
                        SDL_BlitSurface(_tete,NULL,ecran,&position) ;
                    break ;

                    case QUEUE :
                        SDL_BlitSurface(_queue,NULL,ecran,&position) ;
                    break ;

                    case POMMME_POSSIBLE :
                        SDL_BlitSurface(_pommePossible,NULL,ecran,&position) ;
                    break ;
                }
            }
        }
        return EXIT_SUCCESS ;
    }

    int Carte::afficherJeu(SDL_Surface *ecran)
    {
        // comme afficherEditeur
        SDL_Rect position ;

        for (int j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
        {
            for (int i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
            {
                position.x = i * TAILLE_BLOC ;
                position.y = j * TAILLE_BLOC ;
                switch(_carte[i][j])
                {
                    case VIDE :
                        SDL_BlitSurface(_vide,NULL,ecran,&position) ;
                    break ;

                    case MUR :
                        SDL_BlitSurface(_mur,NULL,ecran,&position) ;
                    break ;
                }
            }
        }
        return EXIT_SUCCESS ;
    }

    int Carte::chargerCarte(string fichier)
    {
        // ouverture en lecture seule
        ifstream niveaux(fichier.c_str(),ios::out) ;

        // lecture si le fichier est bien ouvert
        if (niveaux.is_open())
        {
            char caractere = '0' ;

            for (int j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
            {
                for ( int i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
                {
                    niveaux.get(_carte[i][j]) ;
                }
            }
            return EXIT_SUCCESS ;
        }

        else
        {
            cerr << "Le fichier " << fichier << " n'a pas pu etre ouvert" << endl ;
            return EXIT_FAILURE ;
        }

        niveaux.close() ;
    }
    int Carte::sauverCarte(string fichier)
    {
        // ouverture en écriture seule
        ofstream niveaux(fichier.c_str(),ios::in) ;

        // écriture si le fichier est bien ouvert
        if (niveaux.is_open())
        {
            for (int j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
            {
                for ( int i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
                {
                    switch(_carte[i][j])
                    {
                        case VIDE :
                            niveaux << VIDE ;
                        break ;

                        case MUR :
                            niveaux << MUR ;
                        break ;

                        case TETE :
                            niveaux << TETE ;
                        break ;

                        case QUEUE :
                            niveaux << QUEUE ;
                        break ;

                        case POMMME_POSSIBLE :
                            niveaux << POMMME_POSSIBLE ;
                        break ;
                    }
                }
            }
            return EXIT_SUCCESS ;
        }

        else
        {
            cerr << "Le fichier " << fichier << " n'a pas pu etre ouvert" << endl ;
            return EXIT_FAILURE ;
        }

        niveaux.close() ;
    }

    int Carte::modifierCarte(int i, int j, int valeur)
    {
        // test pour savoir si les coordonnées sont bien dans la carte
        if ( i >= 0 && i < NB_BLOCS_LARGEUR && j >= 0 && j < NB_BLOCS_HAUTEUR )
        {
            // test pour savoir si on a pas une mauvaise valeur
            if ( valeur == VIDE || valeur == MUR || valeur == TETE || valeur == QUEUE || valeur == POMMME_POSSIBLE)
                _carte[i][j] = valeur ;

            else
            {
                cerr << "La valeur indiquée n'est pas connue" << endl ;
                return EXIT_FAILURE ;
            }
        }

        else
        {
            cerr << "Les coordonnées demandées sont en dehors de la carte" << endl ;
            return EXIT_FAILURE ;
        }
        return EXIT_SUCCESS ;
    }

    int Carte::afficherTampon(int valeur,SDL_Rect &position,SDL_Surface *ecran)
    {
        switch(valeur)
        {
            case VIDE :
                SDL_BlitSurface(_vide,NULL,ecran,&position);
            break ;

            case MUR :
                SDL_BlitSurface(_mur,NULL,ecran,&position);
            break ;

            case TETE :
                SDL_BlitSurface(_tete,NULL,ecran,&position);
            break ;

            case QUEUE :
                SDL_BlitSurface(_queue,NULL,ecran,&position);
            break ;

            case POMMME_POSSIBLE :
                SDL_BlitSurface(_pommePossible,NULL,ecran,&position);
            break ;
        }
    }

    Carte::~Carte()
    {
        SDL_FreeSurface(_vide) ;
        SDL_FreeSurface(_mur) ;
        SDL_FreeSurface(_tete) ;
        SDL_FreeSurface(_queue) ;
        SDL_FreeSurface(_pommePossible) ;
    }

     


    editeur.h
    /* editeur.h */

    #ifndef DEF_EDITEUR
    #define DEF_EDITEUR

    void editeur(SDL_Surface *ecran);

    #endif

     


    editeur.cpp
    /* editeur.cpp */

    #include <iostream>

    #include <SDL/SDL.h>

    #include "constantes.h"
    #include "niveaux.h"
    #include "editeur.h"

    using namespace std ;

    void editeur(SDL_Surface *ecran)
    {
        // variables
        Carte carte ;
        bool clic = false ;
        bool continuer = true ;
        int tampon = VIDE ;
        SDL_Event event ;
        SDL_Rect positionTampon ;

        carte.chargerCarte("niveaux.lvl") ;

        // boucle principale
        while(continuer)
        {
            SDL_WaitEvent(&event) ;
            switch(event.type)
            {
                case SDL_QUIT :
                    continuer = false ;
                break ;

                case SDL_KEYDOWN :
                    switch(event.key.keysym.sym)
                    {
                        case SDLK_ESCAPE :
                            continuer = false ;
                        break ;

                        case SDLK_1 :           // choix du terrain à placer
                            tampon = VIDE ;
                        break ;

                        case SDLK_2 :
                            tampon = MUR ;
                        break ;

                        case SDLK_3 :
                            tampon = TETE ;
                        break ;

                        case SDLK_4 :
                            tampon = QUEUE ;
                        break ;

                        case SDLK_5 :
                            tampon = POMMME_POSSIBLE ;
                        break ;

                        case SDLK_s :           // sauvegarde du niveau
                            carte.sauverCarte("niveaux.lvl") ;
                        break ;
                    }
                break ;

                // edition de la carte
                case SDL_MOUSEMOTION :
                    positionTampon.x = event.motion.x - TAILLE_BLOC / 2 ;
                    positionTampon.y = event.motion.y - TAILLE_BLOC / 2 ;
                    if (clic)
                        carte.modifierCarte(event.motion.x/TAILLE_BLOC,event.motion.y/TAILLE_BLOC,tampon) ;
                break ;

                case SDL_MOUSEBUTTONDOWN :
                    switch(event.button.button)
                    {
                        case SDL_BUTTON_LEFT :
                            clic = true ;
                        break ;
                    }
                break ;

                case SDL_MOUSEBUTTONUP :
                    switch(event.button.button)
                    {
                        case SDL_BUTTON_LEFT :
                            clic = false ;
                        break ;
                    }
                break ;
            }

            // affichage
            SDL_FillRect(ecran,NULL,SDL_MapRGB(ecran->format,0,0,0));

            // blittage de la carte
            carte.afficherEditeur(ecran);

            // blittage du tampon
            carte.afficherTampon(tampon,positionTampon,ecran);

            SDL_Flip(ecran);
        }
    }
     


    menu.h
    /* menu.h */

    #ifndef DEF_MENU
    #define DEF_MENU

    #include <iostream>
    #include <string>
    #include <SDL/SDL.h>
    #include <SDL/SDL_ttf.h>

    class Menu
    {
        public :
        Menu();
        void titre(std::string titre, SDL_Color couleur,int x,int y, SDL_Surface *ecran);

        private :
        SDL_Rect m_position ;
    };

    #endif

     


    menu.cpp
    /* menu.cpp */

    #include "menu.h"

    using namespace std ;

    Menu::Menu()
    {
        m_position.x = 0 ;
        m_position.y = 0 ;
    }

    void Menu::titre(string titre, SDL_Color couleur,int x,int y, SDL_Surface *ecran)
    {
        // création du texte voulu
        TTF_Font *arial22 = TTF_OpenFont("arial.ttf",22) ;
        SDL_Surface *texte = TTF_RenderText_Blended(arial22,titre.c_str(),couleur) ;

        // vérification : peut - on placer le texte ?
        if ( x < 0 || x > ecran->w - texte->w/2 || y < 0 || y > ecran->h - texte->h/2)
        {
            cerr << "La position du texte ne permet pas un affichage correct" << endl ;
            return ;
        }

        // blittage du texte
        else
        {
            m_position.x = x - texte->w/2 ;
            m_position.y = y - texte->h/2 ;
            SDL_BlitSurface(texte,NULL,ecran,&m_position);
        }

        SDL_FreeSurface(texte);
        return ;
    }

     


    main.cpp
    /* main.cpp*/

    #ifdef __cplusplus
        #include <cstdlib>
    #else
        #include <stdlib.h>
    #endif

    #include <iostream>
    #include <string>
    #include <SDL/SDL.h>
    #include <SDL/SDL_ttf.h>

    #include "constantes.h"
    #include "Menu.h"
    #include "niveaux.h"
    #include "editeur.h"
    // TODO (PePeDeLuXe#1#): Problème d'affichage dans l'éditeur :\
    il y a bien chargement du fichier, écriture du fichier lors de la sauvegarde.\
    Il reste à vérifier que lors du chargement _carte[i][j] est bien mis à jour\
    \
    On remarque aussi que l'affiche est réalisé lorsque l'éditeur est en marche, mais pas à l'initialisation : le fond est noir au lei d'afficher la carte ...

    using namespace std ;

    int main ( int argc, char** argv )
    {
        // variables
        SDL_Color blanc = {255,255,255} ;

        Menu menu ;

        // initialisation SDL
        if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 )
        {
            printf( "Erreur de chargement de la SDL: %s\n", SDL_GetError() );
            return 1;
        }

        // initialisation TTF
        if(TTF_Init()==-1)
        {
            printf("TTF_Init: %s\n", TTF_GetError());
            exit(EXIT_FAILURE);
        }

        // on s'assure de libérer la mémoire à la fin
        atexit(SDL_Quit);
        atexit(TTF_Quit);

        // initialisation de l'ecran
        SDL_Surface *ecran = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE, BIT_PAR_PIXEL,
                                               SDL_HWSURFACE|SDL_DOUBLEBUF);
        SDL_WM_SetCaption("Jeu du serpent",NULL);

        if ( !ecran )
        {
            printf("Impossible de créer la surface ecran : %s\n", SDL_GetError());
            return EXIT_FAILURE;
        }

        // boucle principale
        bool continuer = true;
        SDL_Event event;
        while (continuer)
        {
            // gestion des évènements
            SDL_WaitEvent(&event) ;
            switch (event.type)
            {
                case SDL_QUIT:                  // on demande d'arreter
                    continuer = false;
                break;

                case SDL_KEYDOWN:
                    switch(event.key.keysym.sym)
                    {
                        case SDLK_ESCAPE :      // on demande d'arreter
                            continuer = false;
                        break;

                        case SDLK_1 :
                            //jouer(ecran) ;
                        break ;

                        case SDLK_2 :
                            editeur(ecran) ;
                        break ;
                    }
            }

            // affichage
            SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0));

            menu.titre("1. Jouer",blanc,LARGEUR_FENETRE/2,(HAUTEUR_FENETRE)/2-25,ecran);
            menu.titre("2. Editeur",blanc,LARGEUR_FENETRE/2,(HAUTEUR_FENETRE)/2+25,ecran);
            menu.titre("Jeu du serpent",blanc,LARGEUR_FENETRE/2,30,ecran);

            SDL_Flip(ecran);
        }

        printf("Fin du programme propre\n");
        return EXIT_SUCCESS ;
    }

     


    constantes.h
    /* constantes.h */

    #ifndef DEF_CONSTANTES
    #define DEF_CONSTANTES

    // constantes d'affichage
    #define NB_BLOCS_LARGEUR 20 // Ces 2 valeurs sont aussi dans
    #define NB_BLOCS_HAUTEUR 20 // niveaux.h ...
    #define BIT_PAR_PIXEL 32
    #define TAILLE_BLOC 20
    #define HAUTEUR_DONNEES_JOUEUR 20

    #define LARGEUR_FENETRE TAILLE_BLOC * NB_BLOCS_LARGEUR
    #define HAUTEUR_FENETRE TAILLE_BLOC * NB_BLOCS_HAUTEUR + HAUTEUR_DONNEES_JOUEUR

    enum {VIDE, MUR, TETE, QUEUE, POMMME_POSSIBLE, SERPENT, POMME } ;
    enum {HAUT, BAS, GAUCHE, DROITE } ;

    #endif

     

    Ca fait beaucoups de code, mais ils comprennent tous une part de l'affichage.

    En tout cas j'ai relu et relu ces lignes de cods sans trouver le problème.
    Merci à tous ceux qui auront eu le courage de lire !
    • Partager sur Facebook
    • Partager sur Twitter
      5 août 2007 à 15:01:22

      Le problème vient d'où exactement ? Parce que c'est bien de pposte un peu de code, mais là faudrait restreindre ^^
      • Partager sur Facebook
      • Partager sur Twitter
        5 août 2007 à 15:49:13

        Vérifie, a tout hasard, que ta surface texte créé dans menu::titre te donne bien quelque chose de correct : en effet, je ne sais pas ce que renvoie SDL_ttf quand il ne trouve pas ta font. Si jamais il renvoie une surface quasiment vide, alors ça expliquerai cela.

        Un coup de debuggueur serait le binevenu pour analyser la surface texte apres son allocation.
        • Partager sur Facebook
        • Partager sur Twitter

        Notre entreprise recrute, contactez moi en MP. (CDI, Bac+5, Lyon, C++, math, décodage binaire, conversions de modèles 2D/3D...)

        [SDL] Problème d'affichage

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
        • Editeur
        • Markdown