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 :

Question conception d'un jeu 2d en C++


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Mai 2010
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Mai 2010
    Messages : 69
    Par défaut Question conception d'un jeu 2d en C++
    Bonjour tout le monde,

    Je suis présentement en train de créer un petit jeu 2d de plateforme à la Mario Bros.
    Bien sûr avant de programmer, j’ai décidé de me lancer dans la conception de mon jeu. Je vous expose donc mes problèmes (interrogation) ou j’aimerai avoir un peu d’aide ou du moins une piste vers où je pourrai regarder pour pouvoir me débrouiller seul.

    1) Les collisions

    J’ai de la difficulté à voir comment je pourrai gérer les collisions. Je sais bien comment savoir si 2 choses ont une collision entre elles, cependant, je ne sais pas comment les faire interagir ensemble.
    Par exemple : le personnage touche un ennemi sur la tête. L’ennemi doit donc mourir, est- ce que je me crée une méthode ‘’Mort()’’ dans chaque classe ennemie que j’appelle lorsqu’il y a eu collision sur le dessus.
    De plus supposions, qu’un ennemi particulier à des piquants sur la tête. Donc quand notre personnage va sauter sur la tête de l’ennemi, il ne doit pas mourir, mais faire mal à notre personnage.

    J’aimerai avoir des pistes de solution sur comment gérer cela. J’ai donné mes exemples avec un personnage et un ennemi, mais cela s’applique pour tous les autres.
    (Perso/item, Ennemi/bloc, etc)

    2) Les items
    Chaque item fait quelque chose de particulier à notre personnage. (Par exemple : fleur permet de lancer des boules de feux, étoile rend invincible, etc)
    Comment gérer cela dans les classes ? Des boolean qui indiquent par exemple s’il est invisible, s’il peut lancer des boules de feux?

    3) J’aimerai faire mon jeu sur le modèle MVC pour pouvoir séparer l’affichage du reste.
    Cependant, j’ai quelque difficulté à voir comment l’implémenter. Pour l’instant dans mon modèle de personnage, j’ai un statut qui contient par exemple Walking, jumping, falling, etc. Qui signifie l’action que le personnage fait. Dans la vu que vais lire ce statut et afficher l’image en conséquence.
    Est-ce correct de s’y prendre ainsi? Avez-vous de meilleures solutions à proposer ?

    PS : si vous avez des liens parlant du modèle MVC et comment l’implémenter je suis preneur. J’ai trouvé quelque lien, mais il n’expliquer pas tous bien comment cela marche.


    Merci beaucoup à ceux qui vont bien vouloir m’aider et qui ont eu le courage lire ce long texte
    Pour l’instant j’aimerai principalement avoir des pistes sur les collisions puisque c’est ce qui me pose le plus de problème.

    Je poste sur le forum C++, car mon jeu sera fait en C++ avec SFML, si je ne suis pas dans le forum, merci de déplacer ce sujet

  2. #2
    Membre expérimenté Avatar de Dalini71
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2008
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2008
    Messages : 181
    Par défaut
    Bonjour,

    C'est une bonne chose de réfléchir à la conception avant de coder

    Je te conseil de te documenter sur les Design Pattern (State et Observer en particulier), ils répondront à pas mal de tes problèmes.

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


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 071
    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 071
    Billets dans le blog
    144
    Par défaut
    Bonjour,

    Pour l'instant vos réflexions semblent assez bonnes.
    La réponse de Dalini71 est une solution possible pour les collisions.
    Sinon, on peut faire une boucle dans la méthode update du monde, qui informe de la collision entre deux objets et qui en appelle des méthodes spécifiques des objets. Mais le observer peut aussi le faire, d'une manière surement plus belle.

    Sinon, juste pour information, car votre poste n'est pas spécialement mal placé, le forum possède une section 2D / 3D / Jeux vidéo et je vous invite à présenter votre jeu là bas .
    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 Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Pour le coup, et contrairement à mes saines et figées habitudes, je préconise le contraire : laisser émerger le design à partir des complexités du code initial.

    Donc, pour faire plus clair, coder le système sans designer, puis généraliser, puis re-généraliser, etc, de manière à aboutir au design final.

    Sinon, une solution est d'utiliser un modèle basé sur les composants (on a N composants qui s'envoient des messages: par exemple, le composant X boradcast le message CheckCollision, le composant Y lui réponds CollideWithMe, et X appelle Y.handle_collision(this) pour traiter la collision (X peut être le PJ, une balle, ... bref; un composant qui se déplace ; Y peut être n'importe quel composant, y compris un composant passif ou un autre composant actif).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Tiens, pourrais tu développer les raisons qui provoquent en toi cette envie ?

    A part ça, pour tout ce qui est collision, un besoin récurrent et non couvert par le langage est la notion de multi-méthode.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  6. #6
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Tiens, pourrais tu développer les raisons qui provoquent en toi cette envie ?
    1/ parce que l'OP est relativement débutant en design (sinon, il ne poserais pas la question )

    2/ parce que le design est émergent lorsqu'on crée des applications complexes, que c'est une application complexe, et que donc, il va voir ses erreurs émerger, la correction possible, bref : évoluer en même temps qu'il produit son jeu.

    3/ parce qu'il va voir de visu ce qu'on entends pas système ouvert à l'extension et fermé à la modification

    4/ parce que c'est un bon exercice de design, et de correction de design, qui intervient très tôt dans le cycle de développement, et qui est donc corrigeable rapidement.

    Il doit bien y avoir d'autres raisons, mais c'était hier, et entre temps, j'ai dormi et je n'ai plus la même perception des choses
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

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

    Informations professionnelles :
    Activité : aucun

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

    J'irais sans doute même plus loin qu'Emmanuel, mais en étant passé directement à la phase de généralisation (j'ai un peu réfléchi au problème )...

    De mon avis, le terme "collision" est suffisamment général pour s'appliquer à bien plus qu'entre toi et un "ennemi": il peut en survenir soit entre un élément "immobile" et un élément mobile, soit entre deux éléments mobiles, mais, quoi qu'il en soit, une collision sera... toujours une collision entre deux objets.

    Cela implique qu'il y aura "interaction" entre ces deux objets, et que le résultat dépendra essentiellement de la nature de chacun d'eux

    Il y a en effet énormément de chances pour qu'un "ennemi" réagisse différemment à une collision avec un boulet de canon ou avec un "bonus" que toi, et que tu réagiras toi même différemment à une collision avec un mur qu'un boulet de canon rentrant en collision avec le même mur.

    Et nous pourrions en dire de même pour le deuxième "objet" intervenant dans la collision, étant donné que j'ai fait remarquer qu'il s'agissait d'une inter action (chaque élément agissant d'une manière particulière sur l'autre )

    Nous pourrions donc partir d'une situation dans laquelle il existe trois grande hiérarchies de classes distinctes représentant les différents objets susceptibles de rentrer en collision :
    • les joueurs (toi, les PNJ éventuels (les personnages qui ne sont pas tes ennemis, mais qui font juste "partie du décors" ), et les ennemis)
    • Les objets mouvants non joueurs (les bonus qui s'écartent, les obus de canon, etc)
    • les objets immobiles (tout ce qui fait partie du décors et qui ne bouge pas)
    Comme j'ai dit que rien ne ressemble plus à une collision qu'une autre collision, il faudrait faire en sorte que la collision soit en mesure de fournir le "contexte" dans lequel elle s'est produite. Cela revient à faire en sorte que la collision soit en mesure d'indiquer à chacun des deux éléments qui se sont rencontrés le genre d'élément qu'il a rencontré

    Nous aurions donc une quatrième grande hiérarchie reprenant les cinq possibilités de collision à envisager:
    • joueur avec joueur
    • joueur avec objet mouvant
    • joueur avec objet immobile
    • objet mobile avec objet mobile
    • objet mouvant avec objet immobile
    pour chaque type de collision, tu peux prévoir un ordre de priorité dans les réactions : le joueur réagira avant un objet mobile qui réagira lui-même avant un objet immobile.

    Tu pourrais d'ailleurs décider d'approfondir cette notion de priorité en disant que le joueur (toi) a priorité sur les ennemis qui ont eux meme priorité sur les PNJ, voire (mais on sort du contexte "mario") de baser le calcul de priorité complexe (basé sur le niveau, la rapidité, la force ou... l'age du capitaine), lorsque deux éléments "similaires" (faisant partie de la même hiérarchie de classes) entrent en collision.

    Le système qui s'occupe de détecter les collision aurait alors la lourde responsabilité de créer la collision "ad hoc" et de l'envoyer à l'élément ayant la priorité de réaction la plus élevée.

    Chaque élément réagirait comme un visiteur à la collision (qui jouerait le role de "visité"), à ceci près que l'on n'a pas *vraiment* besoin de partir de l'objet visité.

    Au final, cela pourrait ressembler à quelque chose comme
    /* la hiérarchie "Collision" */
    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
    class Collision /* la classe de base */
    {
        public:
            virtual ~Collision() = 0; // seule fonction réellement indispensable
                                  // virtuelle pure pour qu'il n'y ait pas moyen de 
                                  // l'instancier
     
             void transmit(){doTransmit();}
         private : 
             virtual void doTransmit()
             {
             }
    };
    /* un petit coup de template pour se faciliter l'écriture :D */
    template <typename FirstType, SecondType = FirstType>
    class TCollision
    {
        public:
            TCollision(FirstType * f, SecondType * s):first_(f), second_(s){}
            virtual ~TCollision(){}
            /* l'accès à l'élément ayant la priorité de réaction la plus élevée */
            FirstType & first() {return first_;}
            /* l'accès à l'élément ayant la priorité de réaction la moins élevée */
            SecondType & first() {return second_;}
     
        private:
            FirstType * first_;
            SecondType * second_;
            virtual void doTransmit()
            {
               first_->collide(this);
               second_->collide(this);
            }
    };
    /* les typedef prenant les différentes possibilités en compte, pour
     * faciliter l'utilisation
     */
    typedef TCollision<Player> CollisionTwoPlayers;
    typedef TCollision<Player, MovingObject> CollisionPlayerMovingObject;
    typedef TCollision<Player, ImmobileObject> CollisionPlayerImmobileObject;
     
    typedef TCollision<MovingObject> CollisionTwoMovingObject;
    typedef TCollision<MovingObject, ImmobileObject> CollisionMobileObjectImmobileObject;
    /* une collision entre deux objets immobiles n'arrivera jamais :D
    La hiérarchie de classes Player prendrait donc la forme d'un visiteur de collisions utilisant le pattern NVI (un peu aménagé pour éviter de devoir implémenter chaque fois les cinq fonctions, même si un joueur ne fait rien dans certains cas ) et ressemblerait à
    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
    class Player
    {
        public:
            Player();
            virtual ~Player() = 0;
            /* la fonction a appeler par le système de détection de collisions */
            void collide(Collision * col)
            {
                doCollide( *col);
            }
        /* d'autres fonctions, sans doute :D */
        protected : 
            /* pour la classe de base, on ne fait rien par défaut 
             * il n'y a, a priori, pas à traiter le cas d'une collision
             * entre un objet mobile et un objet immobile, ni
             * entre deux objets mobiles ;)
             */
            virtual void doCollide(CollisionTwoPlayers &){}
            virtual void doCollide(CollisionPlayerMovingObject &){}
            virtual void doCollide(CollisionPlayerImmobileObject &){}
            virtual void doCollide(CollisionTwoMovingObject&){}
    };
    class Gamer : public Player
    {
        public:
            Gamer (/* ... */);
            virtual ~Player();
            void collide(Collision * col)
            {
                doCollide( *col);
            }
        /* d'autres fonctions, sans doute :D */
        protected : 
            /* il ne faut réimplémenter que les fonctions qui 
             * nécessite une réaction de notre part :D
             * l'idée générale étant de mettre en place
             * la logique qui devra etre suivie :D
             */
            virtual void doCollide(CollisionTwoPlayers &)
            {
                /*...*/
            }
            virtual void doCollide(CollisionPlayerMovingObject &)
            {
                /*...*/
            }
            virtual void doCollide(CollisionPlayerImmobileObject &)
            {
                /*...*/
            }
            virtual void doCollide(CollisionTwoMovingObject&)
            {
                /*...*/
            }
    };
    /* idem pour les ennemis et les pnj, s'il y en a */
    Les hiérarchies d'objets mobiles et d'objet immobiles suivraient le même principe en veillant à ne fournir le pattern nvi que pour les collisions qui sont susceptibles d'arriver parmis les cinq cas que l'on a définis plus haut

    Il nous manquerait, peut etre, enfin, une "fabrique de collision" qui permettrait au détecteur de collision de ne pas s'occuper lui-même de la création de celles-ci (le fameux principe ORP (One Responsability Principle), et il (le détecteur de collision) pourrait donc ressembler à quelque chose qui serait fort proche 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
    class CollisionDetector
    {
         public:
            /* j'aime les template pour éviter de devoir réécrire
             * vingt fois la même chose :D
             template <typename FirstType, SecondType>
             static void detect(FirstType * one, SecondType * second)
             {
                 /*logique de détection de collision */
                /* logique de sélection de priorité */
               sendCollision(mostPriorItem, secondPriorItem);
             }
        private:
              template <typename FirstType, SecondType>
             void sendCollision(FirstType * mostPriorItem, SecondType * secondPriorItem)
             {
                 Colllision * col = CollisionFactory::createCollection(mostPriorItem, secondPRior);
                 col->transmit();
             }
    };
    Ce n'est qu'une idée qui mériterait plus grande réflexion, mais je crois que tu as là une base qui devrait pouvoir évoluer assez rapidement...

    A ceci près qu'il pourrait même être intéressant de prévoir se supprimer la responsabilité de visiteur des hiérarchies de classes, car les élements qui entrent en collision ont très certainement déjà une responsabilité qui leur est propre, et cela devrait leur suffire
    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

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


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 071
    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 071
    Billets dans le blog
    144
    Par défaut
    Je vais me permettre une remarque

    Sur ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    virtual void doCollide(CollisionTwoPlayers &){}
    virtual void doCollide(CollisionPlayerMovingObject &){}
    virtual void doCollide(CollisionPlayerImmobileObject &){}
    virtual void doCollide(CollisionTwoMovingObject&){}
    Le jour ou vous allez vouloir gérer une nouvelle collision, entre 2 FlyingObject par exemple, vous allez devoir rajouter des fonctions partout dans votre code (ce qui peut être lourd, non?)
    Alors oui, vous aurez le compilateur comme aide pour vous dire que vous oublier une implémentation, donc y a cette avantage. Mais je trouve pour autant qu'après quelques types de collision, cela va vraiment alourdir le code.

    N'y a t-il pas une façon plus dynamique de faire. Notamment, il se peut qu'il y ai duplication de code si deux méthodes doivent implémenter le même comportement (sauf si le cast est possible entre CollisionPlayerImmobile et CollisionPlayerMoving, mais cela ne me semble pas castable).

    Pour le système de message, cela peut être bien (genre, on apprend qu'il y a eu collision entre un objet et un autre. Le premier objet recevant le message, connaitra l'objet qui collide avec le pointeur sur l'autre). Par contre, c'est souvent très dangereux au niveau de la mémoire et de la validité des pointeurs (donc, pointeurs intelligent à la rescousse, j'imagine)

    Voilà pour mon point de vue (moi je suis une des entités qui peut se tromper )
    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.

Discussions similaires

  1. Conception d'un jeu de tennis
    Par b Oo dans le forum Développement 2D, 3D et Jeux
    Réponses: 5
    Dernier message: 17/01/2007, 22h19
  2. Difference dates et questions conception
    Par lolo_bob2 dans le forum Modélisation
    Réponses: 2
    Dernier message: 23/11/2006, 13h23
  3. Conception d'un jeu de course
    Par zooffy dans le forum Développement 2D, 3D et Jeux
    Réponses: 5
    Dernier message: 03/11/2006, 19h29
  4. [Conception] Concevoir le jeu Pierre Feuille Ciseau
    Par websurfeur dans le forum Général Java
    Réponses: 14
    Dernier message: 17/03/2006, 19h26
  5. [VB] Aide pour la conception d'un jeu
    Par superbruno dans le forum VB 6 et antérieur
    Réponses: 12
    Dernier message: 17/01/2006, 18h01

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