Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de conception pour un jeu

    28 juillet 2015 à 11:44:51

    Bonjour,

    Je suis en train de réaliser un jeu avec SFML et j'ai du mal à me décider sur comment organiser mes classes.

    Voici ce à quoi je pensais :

    - classe Game dans laquelle tourne la boucle du jeu (la base du jeu)

        - classe World qui va gérer la map, le joueur ..

             - classe Level qui va contenir un array de ROom et draw/update la Room actuelle

                   - classe Room qui correspond à une salle, qui va load et générer un tableau de vertices puis la draw / update (mobs)

                         (- classe Mobs)

             (- classe Player)

    J'aurais également une classe Player, qui va mouvoir le personnage en fonction de l'input, gérer les collisions et faire bouger le sprite. Et également uen classe Entity de laquelle hériteront les Mobs.

    Mon problème est que je ne sais pas comment gérer ces classes Player et Mob.

    A la base, je pensais stocker une liste de Mobs dans la classe Room, ainsi chaque Room pourrait générer ses propres mobs en connaissant les coordonnées et le type de chaque bloc etc, rendant la génération plus aisée.

    Mais où devrait alors se situer le Player ? Probablement dans World, mais le plus gros problème est alors que je n'ai aucune idée de comment je pourrais communiquer entre les Mobs et le Player, pour gérer les collisions. 

    Par exemple, si un Mob attaque en lançant une boule de feu puis une autre, comment puis-je savoir s'il y a collision entre le Player et une des boules de feu, les mobs étant stockés dans Room et le Player dans World ?

    Je pourrais certes faire une chaîne de get pour récupérer la liste de mobs dans le update du World, mais je ne sais pas si c'est le plus optimisé à faire. De plus, admettons que le Player attaque (avec une épée), j'appelerais donc une méthode attack dans Player et je récupérerais une bouding box de la zone où les dégats seront infligés, mais comment vérifier si elle match avec un Mob, à partir de l'architecture de mes classes ? Je ne peux pas accéder aux mobs depuis la classe Player ...

    De plus, dans le update de World, est-ce la bonne marche à suivre de d'abord déplacer le Player en fonction de l'input et des collisions ainsi que de déplacer les mobs en fonction de l'aléatoire et aussi des collisions, puis de vérifier toutes les collisions par ex entre les boules de feu et le joueur, ou alors l'inverse ?

    Merci beaucoup !

    -
    Edité par codageweb 28 juillet 2015 à 11:52:08

    • Partager sur Facebook
    • Partager sur Twitter
      28 juillet 2015 à 21:38:11

      Lu'!

      Les classes Player et Mob ont-elles une vraie raison d'être séparée ? Telle que tu l'annonces, la seule différence entre les deux, c'est leur pilotage, l'une par des IA, l'autre par les contrôles. Bref, on a plutôt envie d'avoir une classe IA et une classe EventHandler qui vont, elles, se charger piloter l'entité qu'on leur aura assignée.

      • Partager sur Facebook
      • Partager sur Twitter

      Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

        28 juillet 2015 à 22:02:26

        Salut,

        Le truc, c'est que lors de la génération de la map, je vais générer (exemple) 200 Rooms aléatoirement. Il faudra donc remplir chacune d'elles avec des mobs, de manière aléatoire. Je pensais donc que le plus optimisé serait de placer ces mobs dans les classes Rooms étant donné qu'elles contiennent tous les tiles. Alors que pour le player, je ne l'ai qu'une fois donc je ne vais en charger un par Room.

        Dans tous les cas, les classes hériteront d'une classe Entity (Player aussi du coup ?), là question que je me pose est sur l'interaction entre ces classes.

        J'ai du mal à concevoir comment le faire :euh:

        Pour l'instant, j'ai World > Level > Room, ma tilemap est chargée et j'ai une instance de Player dans World.

        Où devrais-je au final déclarer les instances des mobs ? Ca risque d'être dur au même endroit que le player.

        • Partager sur Facebook
        • Partager sur Twitter
          29 juillet 2015 à 0:37:23

          Salut,

          Mais, si tu y réfléchis bien, la seule différence entre un mob et le joueur, c'est que le mob est piloté par une intelligence artificielle.  Du coup, tu peux avoir une classe commune au joueur et au mob qui expose (peu ou prou) un seul comportement : moveTo(positionX, positionY) ou move(distanceX, distanceY) (selon ce que tu préfères ;)) et, la seule différence qu'il y aura entre les deux classes (joueur et mob), c'est "qui donne l'ordre de mouvement").

          Par facilité, tu crées une classe qui s'occupe de maintenir les mobs d'une piece (appelons-là "MobHolder", pour l'exemple), qui expose trois comportements :

          • addMob(mob*) qui sera utilisée lors du chargement
          • clear() pour supprimer l'ensemble des mobs (lorsqu'il s'agit de charger la piece suivante) et
          • move(id, postitionX, positionX) (ou move(id, distanceX,distanceY), selon ce que tu as prévu pour la classe de base ;) ) pour que l'IA puisse donner les ordre de mouvement aux différents mobs

          Tu place ton joueur et cette classe (je parle de MobHolder) au niveau de ta partie (dans la classe game) et tu transmet ces deux données (par référence -- éventuellement constante) à toute fonction / classe qui en a besoin pour fonctionner ;)

          NOTA: à long terme l'approche purement orientée objets n'est vraiment pas la meilleure des solutions pour tout ce qui est jeu.  Une approche orientée ECS s'avère très souvent plus flexible, dés qu'il est question d'envisager de rajouter régulièrement de nouveaux types d'éléments (nouveaux bonus, nouveaux ennemis, nouvelles armes, nouveaux... va savoir quoi ;) )

          • Partager sur Facebook
          • Partager sur Twitter
          Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
            29 juillet 2015 à 11:04:01

            Merci pour ta réponse !

            Donc d'après ce que tu me dis, j'aurais une classe Entity, dont héritent par exemple une classe Character et une classe [UnMob]. Par-dessus, j'aurais une classe Player qui gère input/collisions et déplace le Character, et une autre classe qui va gérer les mobs. Mais si les mobs ont chacun des comportements différents, dois-je différencier ces comportements dans les classes qui héritent de Entity ou dans celles qui vont gérer les Entity ?

            Par ailleurs, les mobs sont générés aléatoirement mais une fois générés, ils restent, donc je dois garder les mobs lorsque je change de pièce. Je dois dons les stocker dans ma classe Room, je ne peux pas ne sauvegarder que des mobs pour une salle à la fois.

            De plus, c'est surtout les classes joueur et MobHolder qui ont besoin entre elles d'avoir leurs informations, afin que le player puisse détecter s'il touche/est touché et pareil pour chaque mob. 

            Dois-je donc gérer tout ce qui est collisions etc dans la classe qui gère le player, ou directement dans ma boucle update principale, dans ma classe Game ?

            • Partager sur Facebook
            • Partager sur Twitter
              29 juillet 2015 à 11:17:48

              codageweb a écrit:

              Donc d'après ce que tu me dis, j'aurais une classe Entity, dont héritent par exemple une classe Character et une classe [UnMob].

              Pas nécessairement, il n'y a pas de différence entre le Personnage joueur et les Personnage non-joueur mis à part leur centre de décision.

              class Entity{
              public:
                void move(position);
                void attack(Entity);
              };
              
              //...
              
              Entity mob;
              Entity hero;
              
              IA ia(mob);
              Controller c(hero);

              A chaque "tour" de jeu :

              for(IA ia : all_ias){
                ia.update_knowledge(infos);
                ia.do_something();
              }
              
              control.check_action();

              Si tu as plusieurs IA différentes :

              class IA{
              public:
                virtual void update_knowledge(knowledge);
                virtual void do_something();
              };
              
              class Aggressive : public IA{};
              class Pacific : public IA{};
              
              //etc ...

              Pour ce qui est de la gestion des pièces. Le plus simple est d'avoir une scène "en cours" et des les éléments sauvés. Un truc du genre :

              Scene load_room(Room::id_t id){
                return Scene { load_room(id), hero };
              }

              Et c'est dans la scène que les entités se baladent et apprennent des choses.

              • Partager sur Facebook
              • Partager sur Twitter

              Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                29 juillet 2015 à 12:23:58

                Je commence à visualiser, merci !

                Donc j'instancie un Controller dans ma classe World (la boucle principale) que je link à une entité player également instanciée dans World, et je crée des Entity pour plusieurs mobs dans chacune de mes rooms, que je link chacune à une IA et stocke dans un tableau. Dans ma boucle update, je m'occupe d'abord du personnage, puis je récupère à chaque tour de boucle un tableau contenant des pointeurs vers toutes les IA de la Room actuelle, j'envoie à chacune en reférence les infos utiles sur le joueur (en gros, sa hitbox) et j'agis en conséquence. Quoi que, si je dois faire perdre de la vie au joueur à partir d'une IA car un mob l'a touché, ou pour savoir s'il est en train d'attaquer, je devrais envoyer à chaque IA une const ref vers le Controller et non seulement la hitbox.

                Est-ce bien cela ?

                Pour la scène, c'est ce que j'ai pour l'instant. Je stocke les infos sur toutes les Rooms (tiles, mobs), et les fonctions draw/update n'ont d'impact que sur la Room où est actuellement situé le character. Ainsi, en sortant d'une room, on la retrouvera exactement dans le même état en y entrant à nouveau.

                Merci encore !

                • Partager sur Facebook
                • Partager sur Twitter

                Problème de conception pour un jeu

                × 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