Jeux Libres
       
           

» Les Tutoriels » Création d'un jeu vidéo » Création du menu avec OpenGL

Création du menu avec OpenGL


Dans ce chapitre nous verrons comment créer un menu avec OpenGL pour votre jeu vidéo. Nativement, OpenGL ne permet pas de créer de menu. Nous allons donc configurer OpenGL pour fonctionner en 2D puis nous dessinerons nos boutons dans la fenêtre 2D.

Le but de ce chapitre est de créer un menu au démarrage du programme permettant de choisir entre "Jouer" et "Quitter". Un clique sur le bouton "Jouer" a pour effet de lancer l'exécution de la scène tandis que le bouton "Quitter" quitte le jeu.


Aperçu du menu avec les 2 boutons





Chapitre précédent     Sommaire     Chapitre suivant


L'architecture du jeu


Avant de se lancer dans la création du menu, nous allons faire un point sur l'architecture du projet actuel. On se rendra compte qu'elle n'est pas parfaite et que certaines choses seront à revoir.

La scène dans le main()



Pour le moment, voici notre main().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main(int argc, char* argv[])
{
   // Initialisation de la SDL et d'OpenGL
   initSDL();
   initOpenGL();
 
   // Execution de la scene
   Scene scene;
   scene.executer();
 
   // Arrt de la SDL
   SDL_Quit();
 
   return 0;
}

On initialise SDL et OpenGL, avant d'exécuter la scène. La fonction initSDL() permet de créer la fenêtre tandis que la fonction initOpenGL() définit la façon dont sera exploitée la fenêtre ainsi que la zone visible en 3D. On s'aperçoit qu'initOpenGL() prépare notre scène à la 3D alors que nous voulons afficher un menu en 2D au démarrage du jeu. La scène est instanciée puis exécutée dans le contexte de la scène 3D précédemment créé.

Pour l'instant notre "jeu" n'est constitué que d'une scène, sans menu.

Un jeu, c'est quoi ?



Arrivé à ce stade, il est important de définir ce qu'est un jeu. D'un point de vue "architectural", c'est l'enveloppe contenant les scènes et les menus. Du point de vu du programme en lui même, le main() ne devrait avoir à exécuter que le jeu.

Voici ce que devrait contenir le main() :
1
2
    Jeu jeu;
   jeu.executer();

Une architecture adaptée



Nous venons de voir les problèmes liés à l'organisation de notre projet. Nous en déduisons qu'il faut faire une classe Jeu comportant une méthode executer(), tout comme celle de votre classe Scene. Vous créerez cette classe dans les fichiers jeu.cpp et .h.
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef JEU_H_INCLUDED
#define JEU_H_INCLUDED
 
class Jeu
{
   public:
       Jeu();
       ~Jeu();
 
       void executer(void);
};
 
#endif // JEU_H_INCLUDED

Vous aurez probablement besoin d'un constructeur et d'un destructeur. Pour le moment, décrivez les 3 méthodes de votre nouvelle classe en les laissant vide. Nous les décrirons plus tard.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "jeu.h"
 
Jeu::Jeu()
{
   
}
 
Jeu::~Jeu()
{
   
}
 
void Jeu::executer(void)
{
   
}

Dans le main(), instanciez simplement le Jeu puis faite appel à sa méthode executer(), comme ceci :
1
2
3
4
5
6
7
8
9
#include "jeu.h"
 
int main(int argc, char* argv[])
{
   Jeu jeu;
   jeu.executer();
 
   return 0;
}

Je précise qu'il ne s'agit pas d'un nouveau projet mais d'une refonte totale du main() actuel.


Votre projet doit compiler et s'exécuter sans erreur. Lors de son exécution, rien ne doit se passer. En effet, pour le moment seules les 3 méthodes vides sont appelées, on ne fait donc "rien".

Initialisation de SDL et OpenGL



Avant, les fonctions initSDL() et initOpenGL() étaient appelées dans le main() avant l'exécution de la scène.

La fonction initSDL() avait pour but de créer la fenêtre, indispensable pour afficher votre "jeu".
La fonction initOpenGL() avait pour but d'initialiser OpenGL pour la 3D, nécessaire au fonctionnement de votre scène.

Création de la fenêtre



Pour être sûr que notre fenêtre soit créée à l'exécution de notre jeu, nous allons déplacer la fonction initSDL() dans la classe Jeu et l'appeler dans la méthode executer(). Notre nouvelle méthode n'a pas besoin d'être publique.
1
2
3
4
5
6
7
8
class Jeu
{
   public:
       // . . .
 
   private:
       void initSDL(void);
};
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
void Jeu::executer(void)
{
   // Creation de la fenetre avec SDL
   this->initSDL();
   
   
   
   // Arrt de la SDL
   SDL_Quit();
}
 
void Jeu::initSDL(void)
{
   // Demarrage de la SDL avec le module video
   if(SDL_Init(SDL_INIT_VIDEO) < 0)
   {
       fprintf(stderr, "Erreur d'initialisation de la SDL : %s\n", SDL_GetError());
       exit(EXIT_FAILURE);
   }
 
   // Creation de la fenetre initialisee pour fonctionner avec OpenGL
   SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE, 32, SDL_OPENGL);
 
   // Titre de l'application
   SDL_WM_SetCaption(TITRE_APPLICATION, NULL);
}

La méthode initSDL() va de paire avec la fonction SDL_Quit(). A la fin de l'exécution de notre jeu, la SDL doit être arrêtée.


N'oubliez pas d'inclure les entêtes #include <SDL/SDL.h> et #include "configuration.h" à votre jeu.cpp ; la méthode Jeu::initSDL() en a besoin.

Paramétrage d'OpenGL pour la 3D



Pour fonctionner correctement, votre scène nécessite que OpenGL soit paramétré pour la 3D. Je vous invite a faire la même chose avec la fonction initOpenGL() au sein de la classe Scene. Ainsi, votre scène configurera elle même le contexte OpenGL dans lequel elle s'exécutera.
1
2
3
4
5
6
7
8
9
void Scene::executer()
{
   // Parametrage d'OpenGL
   this->initOpenGL();
 
 
   // . . .
 
}

Compilation et exécution



Si vous exécutez votre jeu, vous devriez voir la fenêtre s'afficher et se fermer immédiatement après.

Maintenant, ajoutez la scène à votre jeu.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "scene.h"
 
// . . .
 
 
void Jeu::executer(void)
{
   // Creation de la fenetre avec SDL
   this->initSDL();
 
   // Execution de la scne
   Scene scene;
   scene.executer();
 
   // Arrt de la SDL
   SDL_Quit();
}

Résultat



Votre scène s'exécute dans la fenêtre de votre jeu.

Assurez-vous bien que les révisions que nous venons d'apporter n'ont pas modifié le fonctionnement de votre jeu. Si tout est bon, passons à la suite.


Vous voici maintenant prêt à passer au menu.


La création du menu


Le menu est la première chose qui doit s'afficher à l'exécution du jeu, juste après la création de la fenêtre.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Jeu::executer(void)
{
   // Creation de la fenetre avec SDL
   this->initSDL();
 
 
   // Ici, la creation du menu
 
 
   // Execution de la scne
   Scene scene;
   scene.executer();
 
   // Arrt de la SDL
   SDL_Quit();
}

La classe Menu



Nous allons créer une classe Menu dans des fichiers menu.cpp et menu.h.

Les méthodes



Notre menu sera constitué d'une image de fond dont on passera le nom du fichier en paramètre au constructeur. Il s'agitera d'un fichier BMP qu'on chargera très facilement grâce à notre conteneur de texture créé dans un précédent chapitre. Le nom du fichier sera mémorisé dans un attribut afin de pouvoir supprimer la texture à la destruction du menu.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef MENU_H_INCLUDED
#define MENU_H_INCLUDED
 
#include <string>
#include "conteneurTextures.h"
 
class Menu
{
   public:
       Menu(std::string imageFond);
       ~Menu();
       void dessiner(void);
 
   private:
       std::string imageFond;
       ConteneurTextures conteneurTextures;
};
 
#endif // MENU_H_INCLUDED
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "menu.h"
#include "conteneurTextures.h"
 
Menu::Menu(std::string imageFond)
{
   this->imageFond = imageFond;
   this->conteneurTextures.ajouter(this->imageFond);
}
 
Menu::~Menu()
{
   this->conteneurTextures.supprimer(this->imageFond);
}
 
void Menu::dessiner(void)
{
 
}

Pour l'instant il n'y a rien de compliqué à expliquer. Voyons maintenant comment dessiner le menu.

La méthode Menu::dessiner()



Notre méthode Menu::dessiner() permettra de dessiner le fond du menu ainsi que nos futurs boutons. Nous aurons donc deux sous-méthodes : dessinerFond() et dessinerBoutons()
1
2
3
4
5
6
7
8
9
10
class Menu
{
   // . . .
 
   private:
       // . . .
       
       void dessinerFond(void);
       void dessinerBoutons(void);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void Menu::dessiner(void)
{
   // Dessin de fond du menu
   this->dessinerFond();
   
   // Dessin des boutons
   this->dessinerBoutons();
}
 
void Menu::dessinerFond(void)
{
   
}
 
void Menu::dessinerBoutons(void)
{
   
}

Initialisation d'OpenGL pour de la 2D



Pour dessiner le fond et les boutons, OpenGL a besoin d'être initialisé pour faire de la 2D. Pour cela, on charge la matrice de projection et on définit la fenêtre comme étant la zone visible. Étant donné que nous seront en 2D, nous n'auront pas besoin du teste de profondeur. Avant de commencer à dessiner, nous viderons l'écran. Lorsque le fond et les boutons seront dessinés, on affichera le dessin à l'écran.

Voici le code qui effectue cette suite d'instructions :
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
void Menu::dessiner(void)
{
   // En 2D
   glLoadIdentity();
   glMatrixMode(GL_PROJECTION);
 
   // Definition de la fenetre
   gluOrtho2D(0.0, (GLdouble)LARGEUR_FENETRE, 0.0, (GLdouble)HAUTEUR_FENETRE);
 
   // Desactivation du test de prophondeur
   glDisable(GL_DEPTH_TEST);
 
   // Vidage de l'image
   glClear(GL_COLOR_BUFFER_BIT);
 
   // Dessin de fond du menu
   this->dessinerFond();
 
   // Dessin des boutons
   this->dessinerBoutons();
 
   // Affichage du dessin
   glFlush();
   SDL_GL_SwapBuffers();
 
}

Vous aurez besoin des entêtes suivantes pour compiler :
1
2
3
4
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>
#include "configuration.h"

Dessin du fond du menu



Pour dessiner le fond, on sélectionne la texture de fond chargée dans le constructeur à l'aide de notre conteneur ; puis on applique la texture à l'écran en décrivant la position des 4 sommets.
1
2
3
4
5
6
7
8
9
10
11
12
13
void Menu::dessinerFond(void)
{
   // Selection de l'image de fond
   glBindTexture(GL_TEXTURE_2D, this->conteneurTextures.texture(this->imageFond).texture);
 
   // Application de l'image de fond
   glBegin(GL_QUADS);
       glTexCoord2d(0, 0); glVertex2f(0, HAUTEUR_FENETRE);
       glTexCoord2d(0, 1); glVertex2f(0, 0);
       glTexCoord2d(1, 1); glVertex2f(LARGEUR_FENETRE, 0);
       glTexCoord2d(1, 0); glVertex2f(LARGEUR_FENETRE, HAUTEUR_FENETRE);
   glEnd();
}

Rappel : L'origine des textures SDL est en haut à gauche tandis que celui d'OpenGL est en bas à gauche. J'ai donc fait un retournement de la texture, comme nous l'avions fait auparavant pour Objet3DStatique.


Test d'exécution



Pour tester, enregistrez l'image ci-dessous en BMP avec un logiciel comme Paint. Le fichier fond_menu.bmp doit être placé près de l'exécutable.


Image de fond du menu

Ensuite, nous allons devoir instancier un menu avec cette image de fond et appeler la méthode dessiner. Pour que le menu s'affiche et puisse être quitté proprement, nous allons devoir mettre en place une petite gestion d'évènements.
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
#include "menu.h"
 
// . . .
 
void Jeu::executer(void)
{
   // Creation de la fenetre avec SDL
   this->initSDL();
 
   // Cration du menu
   Menu menu("fond_menu.bmp");
 
   // Boucle d'execution du jeu
   bool8 continuer = TRUE;
   while(continuer)
   {
       // Affichage du menu
       menu.dessiner();
 
       // Gestion des evenements
       SDL_Event evenement;
       SDL_WaitEvent(&evenement);
       switch(evenement.type)
       {
           // Quitter
           case SDL_QUIT:
               continuer = FALSE;
               break;
       }
   }
 
   // Execution de la scene
   /*Scene scene;
   scene.executer();*/

 
   // Arret de la SDL
   SDL_Quit();
}

Remarquez que j'ai utilisé la fonction SDL_WaitEvent() afin d'attendre qu'un évènement se produise. Dans le cas d'un menu, il n'y a rien à faire si aucun évènement ne se produit, donc on attend. Lorsqu'un évènement se produit, on test s'il s'agit de l'évènement de type SDL_QUIT. Si c'est le cas on quitte, sinon on continue.


L'appel à la méthode menu.dessiner() aurait pu être placé juste avant la boucle d'exécution du jeu. Je l'ai mis dans la boucle d'exécution car plus tard notre menu devra être redessiné lorsque certains évènements se produiront. Par exemple, lorsque la souris passera au dessus d'un bouton, celui-ci sera redessiné en surbrillance.

Si tout s'est bien passé, vous devez obtenir ceci :


Le menu avec l'image de fond




Dans cette première partie nous avons réorganisé la partie haute de notre projet et commencé à créer un "menu". Dans le chapitre suivant nous apprendrons à créer des boutons et à les rendre cliquable.

État actuel du projet : Jeu_08.zip.



Chapitre précédent     Sommaire     Chapitre suivant



Rédigé par David
Consulté 22554 fois



Hébergeur du site : David
Version PHP : 5.4.45-0+deb7u2
Uptime : 16 jours 5 heures 53 minutes
Espace libre : 1599 Mo
Dernière sauvegarde : 09/12/2018
Taille de la sauvegarde : 1109 Mo


4957883 pages ont été consultées sur le site !
Dont 2258 pages pendant les 24 dernières heures.

Page générée en 0.501 secondes


Nos sites préférés
- Création d'un jeu de plateforme de A à Z avec SDL
- Zelda ROTH : Jeux amateurs sur le thème de Zelda
- Zeste de Savoir : la connaissance pour tous et sans pépins
- YunoHost : s'héberger soi-même en toute simplicité
- Site de Fvirtman : recueil de projets et de codes en C et C++
- Par ici la sortie : le site des idées de sorties


  © 2005-2018 linor.fr - Toute reproduction totale ou partielle du contenu de ce site est strictement interdite.