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 :

[C++/SDL]Affichage de menus dans un jeu vidéo


Sujet :

SDL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2009
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 41
    Par défaut [C++/SDL]Affichage de menus dans un jeu vidéo
    Bonjour à tous, dans l'optique de développer un jeu (qui est déjà bien avancé), je dois afficher des menus de sélections de façon successives (par exemple : écran-titre > choisir niveau > niveau 01 > difficulté) comme dans les jeux professionnels quoi.
    Voilà alors ma méthode habituel fonctionne bien lors du jeu, mais lorsque je quitte (SDL_Quit ou l'appui sur la touche echap), on dirait que le jeu remonte en arrière dans les niveaux, et j'ai des grosses fuites de mémoires quand je mets la fonction DeleteWindow() qui a pourtant le rôle de la vider des différents sons et images. Donc en regardant, j'ai mis un seul DeleteWindow() à l'écran titre (le premier menu) et ça résout le problème, mais j'aimerai un code plus propre, et surtout plus stable.

    Voici ma façon de faire actuelle, je copie cette boucle pour chaque menu, en changeant l'affichage et la gestion de l'appui sur Espace pour accéder au sous menu suivant :

    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
     
    void Window::EventsTitle()
    {	
       	//Boucle Principal
     
    	menu = 0;
    	menuGameOver = 0;
     
    	//Tant que l'utilisateur n'a pas quitter
    	while (continuer)
    	{
    		while (SDL_PollEvent(&event) )
     
    		{						
    			switch(event.type)
    			{
     
    			case SDL_QUIT :
    				continuer = 0;
    				break;
    			case SDL_KEYDOWN :	
    				if(event.key.keysym.sym == SDLK_ESCAPE)
    				continuer = 0;
    				if(menu > 0)
    				{
    				if(event.key.keysym.sym == SDLK_UP)
    				{
    					FSOUND_PlaySound(FSOUND_FREE, menuSound);
    					menu--;
    				}
    				}
    				if(menu < 2)
    				{
    				if(event.key.keysym.sym == SDLK_DOWN)
    				{
    					menu++;
    					FSOUND_PlaySound(FSOUND_FREE, menuSound);
    				}
    				}
    				if(event.key.keysym.sym == SDLK_SPACE)
    				{
    					FSOUND_PlaySound(FSOUND_FREE, valideSound);
    					if(menu == 0)
    					{
     
    						EventsChoice();
     
    					}
    					if(menu == 2)
    					continuer = 0;
    				}
    				break;
    			}
     
     
    		}	
    			tempsActuel = SDL_GetTicks();
    		if (tempsActuel - tempsPrecedent > FPS)
    			{ 
    				SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
     
    				SDL_BlitSurface(Title[menu], 0, SDL_GetVideoSurface(), &posTitle);
    				heroTitle->Draw();
     
    				SDL_Flip(ecran);
     
    				tempsPrecedent = tempsActuel;
    			}
    		else // Si ça fait moins de 30ms depuis le dernier tour de boucle, on endort le programme le temps qu'il faut
    			{
     
    				SDL_Delay(FPS - (tempsActuel - tempsPrecedent));
    			}	
     
     
    	}
     
     
    	 DeleteWindow();
    }
    par exemple le menu suivant sera EventsChoice() :

    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
     
    void Window::EventsChoice()
    {	
       	//Boucle Principal
     
    	menu = 0;
     
    	//Tant que l'utilisateur n'a pas quitter
    	while (continuer)
    	{
    		while (SDL_PollEvent(&event) )
     
    		{						
    			switch(event.type)
    			{
     
    			case SDL_QUIT :
    				continuer = 0;
    				break;
    			case SDL_KEYDOWN :	
    				if(event.key.keysym.sym == SDLK_ESCAPE)
    				continuer = 0;
    				if(menu > 0)
    				{
    				if(event.key.keysym.sym == SDLK_LEFT)
    				{
    					FSOUND_PlaySound(FSOUND_FREE, menuSound);
    					menu--;
    				}
    				}
    				if(menu < 1)
    				{
    				if(event.key.keysym.sym == SDLK_RIGHT)
    					{FSOUND_PlaySound(FSOUND_FREE, menuSound);
    					menu++;}
    				}
    				if(event.key.keysym.sym == SDLK_SPACE)
    				{
    					FSOUND_PlaySound(FSOUND_FREE, valideSound);
    					if(menu == 1)
    					{
    						SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
    						SDL_BlitSurface(ready, 0, SDL_GetVideoSurface(), &posready);
    						SDL_Flip(ecran);
    						SDL_Delay(1000);
    						InitGame(1);
     
    					}
    					if(menu == 0)
    						{
    						SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
    						SDL_BlitSurface(ready, 0, SDL_GetVideoSurface(), &posready);
    						SDL_Flip(ecran);
    						SDL_Delay(1000);
    						InitGame(0);
    						}
    				}
    				break;
    			}
     
     
    		}	
    			tempsActuel = SDL_GetTicks();
    		if (tempsActuel - tempsPrecedent > FPS)
    			{ 
    				SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
     
    				SDL_BlitSurface(Choice[menu], 0, SDL_GetVideoSurface(), &posTitle);
    				heroTitle->Draw();
     
    				SDL_Flip(ecran);
     
    				tempsPrecedent = tempsActuel;
    			}
    		else // Si ça fait moins de 30ms depuis le dernier tour de boucle, on endort le programme le temps qu'il faut
    			{
     
    				SDL_Delay(FPS - (tempsActuel - tempsPrecedent));
    			}	
     
     
    	}
     
     
    }

    et voici ma fonction deleteWindow qui pose tant de problème, tout semble pourtant être dans les règles :

    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
     
    void Window::DeleteWindow()
    {
    	FSOUND_Sample_Free(valideSound);
    	FSOUND_Sample_Free(menuSound);
    	FSOUND_Sample_Free(bonusSound);
    	FSOUND_Sample_Free(degat);
    	 FSOUND_Stream_Close(musique);
    	 FSOUND_Close();
     
    	SDL_FreeSurface(Title[0]);
    	SDL_FreeSurface(Title[1]);
    	SDL_FreeSurface(GameOver[0]);
    	SDL_FreeSurface(GameOver[1]);
    	if(player != NULL)
    	player->Free();
    	if(lvl[lvl.size()-1] != NULL)
    	lvl[lvl.size()-1]->Free();
    	SDL_FreeSurface(ecran);
    	SDL_Quit();
     
    }
    Il arrive même que le debugger situe la fuite de mémoire... dans le constructeur !!!

    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
     
    Window::Window()
    {
     
    	stade = 2;
     
    	float w = 720;
    	float h = 480;
     
    	FSOUND_Init(44100, 32, 0);
     
    	SDL_Init(SDL_INIT_VIDEO | SDL_DOUBLEBUF);
    	SDL_WM_SetCaption("PATCHWORK Hero",NULL);
        ecran = SDL_SetVideoMode(w, h, 32, SDL_HWSURFACE);
     
    	Title[0] = IMG_Load("Title/ecran-titre-01.png");
    	Title[1] = IMG_Load("Title/ecran-titre-02.png");
    	Title[2] = IMG_Load("Title/ecran-titre-03.png");
    	GameOver[0] = IMG_Load("Title/game-over-01.png");
    	GameOver[1] = IMG_Load("Title/game-over-02.png");
    	Choice[0] = IMG_Load("Title/choix-01.png");
    	Choice[1] = IMG_Load("Title/choix-02.png");
    	degatImg = IMG_Load("Enemies/degat.png");
     
    	heroTitle = new PictureAnimated("Title/hero.imga", 0.35);
     
    	ready = IMG_Load("Title/ready.png");
     
    	posTitle.x = 0;
    	posTitle.y = 0;
     
    	menu = 0;
    	menuGameOver = 0;
     
    	posready.x = 0;
    	posready.y = 0;
     
    	/*if(musiquestop == false)
    	{
    	musique = FSOUND_Stream_Open("Music/Fond.mp3", FSOUND_LOOP_NORMAL, 0, 0);
    	FSOUND_Stream_Play(FSOUND_FREE, musique);
    	FSOUND_Stream_SetLoopCount(musique, -1);
    	}*/
     
    	bonusSound = FSOUND_Sample_Load(FSOUND_FREE, "Music/bonus.mp3", 0, 0, 0);
    	degat = FSOUND_Sample_Load(FSOUND_FREE, "Music/degat.mp3", 0, 0, 0);
    	menuSound = FSOUND_Sample_Load(FSOUND_FREE, "Music/menu.mp3", 0, 0, 0);
    	valideSound = FSOUND_Sample_Load(FSOUND_FREE, "Music/valide.mp3", 0, 0, 0);
     
     
    	SDL_ShowCursor(SDL_DISABLE);
     
    	lastlevel = 0;
     
     
    	OpenStory();
     
     
     
     
     
    }
    En mettant l'erreur sur un "FSOUND_Close()" à la dernière parenthèse...

    J'avoue que j'ai vraiment du mal à comprendre et j'aurai vraiment besoin de votre aide pour ce problème !!!
    Comment feriez vous pour afficher les menus ? Comment régler ce problème ?
    Merci d'avance !

  2. #2
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 084
    Par défaut
    Bonjour,

    Je pourrai pas te dire exactement ton problème, le C++ et moi, c'est pas encore ca. De plus, ton code est devenue assez conséquent.

    Par contre, j'ai remarqué que tu ne vérifier pas le retour de tes fonction. C'est peut être pour ca que ca plante a Fsound_Close, car je ne sais pas quelle est son comportement si tu lui envoie NULL.

    J'espère que tu trouvera ton bonheur et que tu vérifiera le retour des fonction dorénavant.

  3. #3
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 151
    Billets dans le blog
    150
    Par défaut
    Bonjour,

    La méthode la plus connue pour faire ce que vous voulez c'est d'utiliser les Machines d'états finis ( Final State Machine ). Cela marche comme un graphe avec des chemins qui dépendent des actions des joueurs.
    Pour chaque noeud, on aura un constructeur ( point d'entrée ) un render/update, pour mettre à jour l'affichage et les actions, et une destructeur ( point de sorties ). En fait, à chaque noeud, les fonctions render / update vont changer de façon à affiché un menu ou un niveau.
    Si j'ai bien compris le bug, ( je n'ai pas regarder le code :red: ) c'est que à chaque fois que vous passer un écran ( menu ou niveau ) vous appeler le prochain. Du coup, lorsque vous quitter votre boucle actuelle, vous ne faites que revenir en arrière.
    Ma solution ( enfin celle que j'explique ici ) n'a qu'une seule boucle, dans laquelle on change ce que l'on affiche. En espérant mettre fait comprendre.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    20
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2009
    Messages : 20
    Par défaut
    Salut, je pense que j'ai la réponse.
    LittleWhite a raison (comme toujours)
    Avec ta première méthode:
    Tu créais une fenetre et ensuite tu appellais une nouvelle fenetre. Normal que quand tu quites la deuxième il t'affiche la première (puisque SDL_Flip(ecran) est à la fin de ta boucle, après ta fonction qui crée la fenêtre 2).

    Moi j'ai eu le même problème et je m'en suis sorti en faisant une variable globale

  5. #5
    Expert confirmé
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 226
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 226
    Par défaut
    Citation Envoyé par Wiz02 Voir le message
    Moi j'ai eu le même problème et je m'en suis sorti en faisant une variable globale
    Il faut jamais faire de variable global (en tous cas a éviter le plus possible),pour ma part j'ai creer qql petit jeu , des lib et j'ai jamais du en utiliser une seule.

    J'ai lu ton code ça m'a l'air correct mais je vais te montrer comment je fais grosso modo mes menu.

    bon je fais du C ,Donc le principe faire une structure MENU

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    typedef struct
    {
        int menu;
        int game;
        int option;
        int quit;
     
    }MENU;
    et apres:
    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
     
        MENU menu;
     
        menu.menu = 1;
        menu.option = 0;
        menu.game = 0;
        menu.quit = 0;
     
        while(menu.quit == 0)
        {
            menu_principal(&menu);
            option(&menu);
            game(&menu);
        }
     
     
     
     
        //et dans des boucle tu enleve
        while(continuer)
       {
            /*----*/
       }
     
        //par
        while(menu->menu == 1) //si c'est le menu ects
       {
            /*----*/
       }


    En espérant que ça t'aide.

    Edit: quelque erreur de code.

Discussions similaires

  1. Intégration de Personnages Blender dans un jeu vidéo
    Par supierre dans le forum Développement 2D, 3D et Jeux
    Réponses: 4
    Dernier message: 01/03/2013, 09h29
  2. Réponses: 4
    Dernier message: 26/05/2011, 22h30
  3. Intégrer un chat dans un jeu vidéo
    Par topgun1223 dans le forum Développement 2D, 3D et Jeux
    Réponses: 4
    Dernier message: 22/06/2009, 19h24
  4. Salaire dans le jeu vidéo
    Par Bob.Killer dans le forum Salaires
    Réponses: 3
    Dernier message: 03/09/2008, 21h46

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