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

 C++ Discussion :

[Conception]PollEvent et code découpé


Sujet :

C++

  1. #1
    Nouveau candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2012
    Messages : 2
    Par défaut [Conception]PollEvent et code découpé
    Bonjour à tous et à toutes,

    Je viens vous exposer un petit soucis survenu pendant la programmation d'un jeu 2D en SDL dans le cadre d'un projet scolaire.
    C'est un DuckHunt, le principe du jeu est de tuer des canards.
    Dans un premier temps, j'affiche un menu permettant de jouer ou de quitter puis le jeu se lance (si le joueur remplit la condition "play").

    Mon codé est divisé en plusieurs fichiers .cc et .h.

    Voici mon soucis : dans mon Main.cc,je fais appel à un PollEvent afin qu'il gère la fermeture de mon programme tout au long de celui-ci.
    Cependant, je suis obligé de relancer une boucle "while PollEvent" pour fermer le programme pendant le jeu.
    Ceci a pour conséquence une imbriquation de deux PollEvents et pour inconvénients d'obtenir un code non optimisé et un evenement assez surprenant : un SDL_Rect sensé bouger continuellement n'est en déplacement que lorsque je bouge ma souris.

    Ma question est donc la suivante :

    Comment faire pour n'avoir à déclarer qu'une seule boucle while (PollEvent) gérant la fermeture du programme sur tout le long du jeu ?

    Mon "Main.cc"
    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
     
    #include <iostream>
    #include <cstdlib>
    #include <string>
    #include <SDL.h>
    #include <SDL_image.h>
    #include <sstream>
    #include <SDL/SDL_ttf.h>
    #include <SDL_ttf.h>
    #include "menu.h" 
    #include "jouer.h"
    #include "image.h"
     
    using namespace std;
     
    SDL_Surface *ecran;//Initialisation de l'écran
    SDL_Event evennement;//Initialisation des évènements à venir sur la fenêtre SD
     
    int main ()
    {
    	bool quit=false;
    	bool play;
     
    	SDL_Init(SDL_INIT_EVERYTHING);
    	ecran=SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_SWSURFACE);
     
    	play = menu();//J'appelle ici mon menu qui demande à l'utilisateur de jouer ou de //quitter, c'est un booléen retournant play
     
    	while(!quit)
    	{
    		while(SDL_PollEvent(&evennement))//1er appel de mon PollEvent
    		{
    			if( evennement.type == SDL_QUIT )
    			{
    				quit = true;
    			}
    				if (play)
    					jouer();//On lance le jeu contenu dans un autre fichier
     
    				else
    					quit = true;
    		}
     
    	}
    	return 0;
    }
    Et voici mon "jouer.cc" :

    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 <iostream>
    #include <cstdlib>
    #include <string>
    #include <SDL.h>
    #include <SDL_image.h>
    #include <sstream>
    #include <SDL/SDL_ttf.h>
    #include <SDL_ttf.h>
    #include "jouer.h"
    using namespace std;	
     
    SDL_Surface *surfaceJeu;
    extern SDL_Event evennement;//J'appelle le SDL-Event déclaré dans le main
    extern SDL_Surface *canard;
     
    void jouer()
    {
    	int cptPhaseVol =0;
    	Canard c;
    	bool quit=false;
    	applySurface( 0, 0, surfaceJeu, screen, NULL );
    	surfaceJeu = load_image( "backGame.png");
    	c.canard = loadImageWithColorKey ("duck.png",228,255,0);
    	initImageCanard (c);
    	initCanard(c);
     
    		while(SDL_PollEvent(&evennement))//Deuxieme boucle PollEvent
    		{
    			if( evennement.type == SDL_QUIT )
    			{
    				quit = true;
    			}
     
    			if (!quit)
    			{
    				if (cptPhaseVol == 0)
    					c.canLect = c.NDos1;
    				else if (cptPhaseVol==50)
    					c.canLect = c.NDos2;
    				else if(cptPhaseVol == 100)
    					c.canLect = c.NDos3;
    				else if (cptPhaseVol >150)
    					cptPhaseVol =0;
    				applySurface( 0, 0, surfaceJeu, screen, NULL );
    				applySurface( c.x, c.y, c.canard, screen,&c.canLect );
    				SDL_Flip(screen);
    				moveCanard(c);
    				showCanard(c, screen);
    				SDL_FreeSurface(screen);
    				cptPhaseVol++;
    			}
    		}
    }
    A noter que nous sommes obligés de fragmenter ainsi notre code cela fait partie des eigeances de nos professeurs.
    Par ailleurs, le code est très loin d'être terminé, ce soucis me blogue légèrement pour continuer la suite.
    Enfin, dans mon menu.cc (non affiché ici), j'ai également appelé une autre boucle while (PollEvent).
    Cette dernière n'affecte cependant pas le bon déroulement du programme,hors-mis peut-être une perte d'optimisation de l'execution.
    Je ne sais pas si c'est vraiment très clair, n'hésitez pas à me demander de clarifier certains points si necéssaire.
    Merci par avance !
    Cordialement.

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Il y a sur le net un tuto pour un tetris en sdl que j'avais suivi il y a un an.

    Je te le recommande, mais je ne le retrouve pas, gràce au proxy de mon poste au boulot.

    Je l'avais trouvé rapidement, demande donc à notre ami à tous.

  3. #3
    Nouveau candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2012
    Messages : 2
    Par défaut
    J'ai trouvé des tetris en un seul fichier code entier ou n'utilisant qu'un simple .h. Ils ne traitent donc pas de mon probleme.

    Un seul d'entre eux était intérressant cependant hors-mi un code illisible le programme n'a pas "besoin" d'imbriquer les PollEvent comme ici.
    Dans mon code, j'aimerai ne pouvoir avoir à déclarer qu'une seule boucle qui s'applique à tous les autres fichiers.cc de mon executable, me permettant ainsi de pouvoir quitter la fênetre par SDL_Quit à tout moment, que ce soit dans le menu ou en plein jeu.

    Enfin les tutos ne traitent pas ce problème, ils ne parlent même pas de PollEvent.

    Cela-dit, merci de ta réponse

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Finalement, les conditions de sorties de la boucle et le poolEvent sont identiques dans la fonction principale et dans la fonction joue...

    Dés lors, pourquoi ne pas passer à la fonction joue des références sur les données qui nous permettent de sortir de la boucle, au moment de l'appeler depuis la boucle principale

    Ta fonction joue pourrait très bien avoir un prototype proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void joue(PollEvent & poll , bool & quit)
    et ressembler dés lors à quelque chose comme
    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
     
    void jouer(PollEvent & poll , bool & quit)
    {
    	int cptPhaseVol =0;
    	Canard c;
            /* plus besoin de cette variable, on l'a en paramètre ;)
    	bool quit=false;
            */
    	applySurface( 0, 0, surfaceJeu, screen, NULL );
    	surfaceJeu = load_image( "backGame.png");
    	c.canard = loadImageWithColorKey ("duck.png",228,255,0);
    	initImageCanard (c);
    	initCanard(c);
     
    		while(poll) // je ne connais pas assez SDL pour savoir comment 
                                // rajouter un événement à ce pollEvent :P
                                // mais est-ce encore nécessaire ???
    		{
    			if( evennement.type == SDL_QUIT )
    			{
    				quit = true;
    			}
     
    			if (!quit)
    			{
    				if (cptPhaseVol == 0)
    					c.canLect = c.NDos1;
    				else if (cptPhaseVol==50)
    					c.canLect = c.NDos2;
    				else if(cptPhaseVol == 100)
    					c.canLect = c.NDos3;
    				else if (cptPhaseVol >150)
    					cptPhaseVol =0;
    				applySurface( 0, 0, surfaceJeu, screen, NULL );
    				applySurface( c.x, c.y, c.canard, screen,&c.canLect );
    				SDL_Flip(screen);
    				moveCanard(c);
    				showCanard(c, screen);
    				SDL_FreeSurface(screen);
    				cptPhaseVol++;
    			}
    		}
    }
    et ta fonction main se simplifierait sous la forme de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    int main ()
    {
    	bool quit=false;
    	bool play;
     
    	SDL_Init(SDL_INIT_EVERYTHING);
    	ecran=SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_SWSURFACE);
     
    	play = menu();//J'appelle ici mon menu qui demande à l'utilisateur de jouer ou de //quitter, c'est un booléen retournant play
            /* prenons quand meme en compte le fait que le joueur veut jouer
             * autrement, on passe directement à la fin ;)
             */
        if(play)
        {
    	while(!quit)
    	{
                SDL_PollEvent poll(&evennement);
                joue(poll, quit);
            }
        }
    	return 0;
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    en général on laisse le poll event dans la boucle principal et on effectue des actions sur le jeu en fonction des évènements qu'on y trouve.

    Dans ton cas, il est inutile de réaliser cette boucle dans le main amha, il faut voir les évènements comme une liste ordonnée dans l'ordre où ils ont été émis.
    Donc s'il y a un évènement de fermeture de fenêtre, tu le retrouveras dans jouer().

    btw, avec ce code, il est impossible de quitter par le menu sans fermer la fenêtre manuellement. Est-ce voulu ?

    enfin, pourquoi déclarer ecran en globale ? pourquoi evenements en globale ?
    N'oublie pas non plus de libérer les ressources, en particulier les SDL_Surface.
    T'as déjà réussi à le compiler et le lancer ?
    Avec un beau free surface sur l'écran dans jouer, j'ai des doutes quant à l'absence de crash.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 290
    Billets dans le blog
    2
    Par défaut
    Callehabana, je te conseille de jeter un coup d'oeil au modèle MVC. Ce sera peut-être un peu ardu (je ne connais pas ton niveau), mais c'est exactement ce qu'il te faut pour ce type de programme.

  7. #7
    Membre habitué
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2011
    Messages : 8
    Par défaut
    Même question que l'OP pour ma part. On m'a aussi renvoyé vers le MVC mais je n'ai pas réussi à franchir mentalement le pas entre la théorie et la pratique...

    En gros, comment appliquer le modèle MVC à ce genre de petits programmes SDL et SFML, où, pour l'instant, je gère TOUS les événements de TOUS les objets dans la boucle du main (beurk).

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    En fait, l'idée du MVC est de créer trois modules aux responsabilités clairement distinctes, pour reprendre les termes du lien fourni par r0d :
    1. un modèle (modèle de données),
    2. une vue (présentation, interface utilisateur)
    3. un contrôleur (logique de contrôle, gestion des événements, synchronisation)
    Pour simplifier, nous pourrions dire que
    Le modèle, c'est un "module" (comprend : un ensemble de classes qui travaillent de concert ) composé de ta partie "métier" : toutes ces classes qui permettent de représenter une abstraction des données que tu veux manipuler, des classes qui te permettent de manipuler ces données et celles qui s'assurent que les données sont manipulées de manière cohérentes, que les règles sont suivies.

    Dans un jeu, ce seraient, par exemple, toutes les classes de "personnage" (joueur et non joueur), d'objet, d'armes, de sorts, ...

    Ces classes non aucun besoin d'être en mesure de se tracer d'elles-même, ce qui te permettrait parfaitement d'utiliser les même classes pour un jeu utilisant SDL, SFML, DirectX ou même la console, pourquoi pas

    La vue, c'est un "module" composé de toutes les classes qui permettent à l'utilisateur d'avoir une représentation des données qu'il manipule ainsi qu'un moyen d'inter-agir avec ces données.

    C'est dans ce module que l'on retrouvera, entre autres, les routines d'affichage (ou du moins l'interface des routines d'affichage ) et la possibilité de générer des événements.

    C'est aussi dans ce module que se trouveront toutes les ressources nécessaires à une représentation correcte de ton modèle (images, sprites, textures, "squelette" des objets, ...

    Le contrôleur est enfin ce qui va permettre de gérer les événements générés par la vue.

    Certains impliqueront un changement au niveau du modèle (comme par exemple, le fait que tu décide d'avancer qui fera en sorte de modifier la position du personnage), d'autres impliqueront un changement au niveau de la vue, sans passer par le modèle (par exemple, le fait que l'événement provoque l'affichage de l'inventaire).

    Il existe deux type de relations entre ces différents modules :
    1. Les relations de dépendances : c'est le fait qu'un module doit pouvoir accéder à un autre afin de pouvoir obtenir des informations de celui-ci (ou lui donner des ordres)
    2. la transmission d'événements et de signaux : c'est le fait qu'un module peut signaler à un autre "qu'il s'est passé quelque chose" et qu'il doit donc réagir à ce qui s'est passé.
    Au niveau des dépendances, la vue dépend du modèle, pour pouvoir accéder à son contenu en lecture seule: la vue doit pouvoir, en permanence, interroger n'importe quel objet du modèle pour lui demander les informations qui permettront à la vue de l'afficher correctement, ou pourquoi pas, si c'est un personnage et qu'il tient quelque chose dans la main droite, ce qu'il tient dans la main droite (ce qui signifie de pouvoir accéder à ce que le personnage tient dans la main droite afin de lui demander les informations qui permettront à la vue de l'afficher)

    De son coté, le controleur dépend à la fois de la vue et du modèle car certains événements (comme le fait de demander l'affichage de la fenêtre d'inventaire) feront que le controleur renverra directement un ordre à la vue (sans passer par le modèle) et d'autres (comme le fait de vouloir faire se déplacer ton personnage) impliqueront que le contrôleur devra envoyer "l'ordre qui convient" au modèle pour que ton objet "personnage" modifie son information de position.

    Au niveau de la transmission d'événements et de signaux, c'est un peu plus simple, car la vue ne transmet ses événements que dans un sens : en direction du controleur (qui, comme je l'ai dit plus haut, les analysera et transmettra des ordres en fonction soit à la vue soit au modèle).

    De son coté le modèle ne peut transmettre des signaux que dans un sens : en direction de la vue (essentiellement pour lui indiquer qu'il est temps de se mettre à jour )

    Note ici qu'il est tout à fait possible que le modèle envoie des signaux qui n'ont strictement rien à voir avec les SDL_event

    Tu serais, par exemple, bien inspiré de faire en sorte que ton modèle émette des signaux issus de boost::signals2 afin de garder ton modèle aussi indépendant de toute bibliothèque graphique que possible

    A ta charge d'avoir une classe qui recevrait ce signal et qui en ferait l'usage adéquat

    Ceci dit, le seul signal que ta vue risque de recevoir de la part du modèle est un signal lui indiquant qu'elle doit se mettre à jour ou similaire (ou peu s'en faut )

    Si l'on reprend, de manière un peu plus concrète, pour un jeu de chasse au canard, nous aurions:
    • les données qui représentent l'abstraction du "monde" dans lequel évolue les canards, les canards eux-même et tout ce qui permet de gérer leur position et leurs déplacements dans le monde (pour éviter qu'un cana se retrouve à traverser un arbre, par exemple) dans le modèle
    • La gestion de SDL_PollEvent et toutes les classes qui permettent de prendre des décisions grâces aux événements que pollEvent contient dans le controleur
    • La SDL_Surface et tout ce qui permet d'afficher le menu, le monde et les canards dans la vue
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. TDD Conception -> Test unit ->Code
    Par taroudant dans le forum Test
    Réponses: 4
    Dernier message: 09/02/2008, 23h52
  2. Concepts à intégrer pour code un client en PERL
    Par fafarun dans le forum REST
    Réponses: 3
    Dernier message: 08/01/2008, 10h33
  3. [Conception] Pourquoi ce code plante ?
    Par bilou95 dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 09/10/2007, 10h52
  4. Trouvez une erreur de conception dans un code
    Par ultimate_manx dans le forum C
    Réponses: 11
    Dernier message: 02/05/2007, 22h37
  5. Conception d'interface : Code ou VCL
    Par Alfred12 dans le forum Langage
    Réponses: 19
    Dernier message: 10/03/2006, 18h58

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