Partage
  • Partager sur Facebook
  • Partager sur Twitter

Comment structurer un jeu en c++

    14 juillet 2013 à 18:09:06

    Asphodelus a écrit:

    Oui je sais, je sais...une personne a dit ça donc il faut l'appliquer a la lettre :lol:

    Non tu es libre de passer outre, mais sache que tu n'es pas le premier à passer outre, et sache également que tout ceux qui l'ont fait avant toi se sont plantés...
    • Partager sur Facebook
    • Partager sur Twitter
    Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
      14 juillet 2013 à 20:48:38

      int21h a écrit:

      Asphodelus a écrit:

      Oui je sais, je sais...une personne a dit ça donc il faut l'appliquer a la lettre :lol:

      Non tu es libre de passer outre, mais sache que tu n'es pas le premier à passer outre, et sache également que tout ceux qui l'ont fait avant toi se sont plantés...

      Y'a optimiser et optimiser. Et y'a tôt et tôt. Et à côté, il y a réfléchir.

      Raffiner son algorithme en effectuant des modifications ultra-poussés, écrire ses tests dessus et voir à la fin qu'en fait, l'algorithme ne répond pas ou plus au problème, c'est mal. Et ça ne serait probablement pas arrivé si la partie fonctionnelle du projet avait avancée plus vite que le technique, c'est à dire si on avait pas chercher à optimiser tout de suite.

      Par contre, voir à l'avance que ça serait p'tête de bien de pas mettre des identifiants en chaîne de caractères là où énumération suffit, c'est bien. Déterminer si une solution que quelqu'un nous propose a un avenir dans le projet que l'on réalise, c'est juste indispensable.

      Asphodelus a écrit:

      Perso je suis en train de regarder à ça car il y a surement moyen de mêler fonctionnalité et performances

      Donc, ne te laisse pas faire Asphodelus ! C'est très bien d'y avoir pensé. Faut juste savoir t'arrêter quand tu as obtenu la réponse à "L'ECS convient-il vraiment à mes objectifs ?".

      -
      Edité par Xahell 15 juillet 2013 à 0:24:57

      • Partager sur Facebook
      • Partager sur Twitter
        14 juillet 2013 à 21:42:26

        Tout à fait d'accord avec toi Xahell

        @int21h: comment sais tu que beaucoup de gens qui ont optimisé leur code avant de son planté? Et puis...faut aussi pensé au contraire: combien de gens ont fait leur code à la va-vite sans penser à des petites optimisations simple et qui se retrouve avec un programme inutilisable car trop lent et qui, du coup, sont complètement paumé dans leur bordel et ne savent plus comment optimiser sans refaire 90% de leur code? ;)...bon ok, pareil, c'est pas vérifiable non plus, mais ça doit exister (autant que le contraire) donc je pense qu'il ne faut tout de même pas prendre cette célèbre phrase au pied de la lettre ^^

        • Partager sur Facebook
        • Partager sur Twitter
          14 juillet 2013 à 21:54:12

          Si changer le KeyType ou même la structure de données force à réécrire une bonne partie du code, alors il y a de quoi douter de la qualité de celui-ci. Le C++ offre suffisamment d'abstraction pour que l'impact de modifier une structure de données soit faible.

          • Partager sur Facebook
          • Partager sur Twitter
          FaQ : Fr | En 1 2 | C++11 | Template || Blog : Deloget | C++|Boost--Dev | C++Next | GotW || Installer Boost
            14 juillet 2013 à 22:15:02

            Oui enfin là c'était juste pour l exemple hein...enfin je ne dis plus rien j'ai perdu d'avance je crois ^^
            • Partager sur Facebook
            • Partager sur Twitter
              15 juillet 2013 à 10:13:24

              Changer un KeyType, en général, ça veut aussi dire modifier l'API.

              Dans un projet perso, je veux bien que ça soit sans conséquences, mais autant éviter que ça se produise malgré tout. C'est pas comme si c'était une perte de temps imbuvable de se demander "string, int ou enum ?" avant de coder.

              • Partager sur Facebook
              • Partager sur Twitter
                15 juillet 2013 à 10:35:40

                Comment on se rend compte des parties à optimiser ? Avec un profiler.

                Quand est-ce que le profiler nous donne des données pertinentes sur les parties à optimiser ? Quand on a plein de parties dans notre module/programme et qu'on est sûrs qu'on va optimiser au bon endroit.

                Je reprend int21h : en optimisant trop tôt tu t'exposes à des grosses failures, et surtout à des démarches inutiles qui n'optimisent pas vraiment ou à la limite ralentissent le programme. Seul ton profiler te permettra d'optimiser avec des données mesurées concrètes.

                Et quand tu dis "Un mec a dit ça alors il faut le faire". Déja si on te prêches la parole de cette personne la, c'est qu'elle a une certaine influence et une notoriété dans le développement en C++. Et tous les développeurs confirmés s'entendent la dessus imho, cf la phrase ci-dessus qu'on rencontre souvent sur le sujet :

                "Early optimization is the root of (all ?) evil"

                PS: normalement les optimisations ne devraient pas te donner des gains de temps énormes. Par exemple si tu passes d'un algo en O(n²) à du O(n), c'est que t'as pas réfléchi initialement, c'est pas une vraie optimisation.

                Donc oui comme tu dis trouver la structure de données qui te convient tu peux le faire avant. Mais la je dirais que c'est plus un soucis de convenience. Le choix string/enum c'est un probleme fonctionnel, tu veux que tes données se comportent comme une chaine de caractères ou comme un entier prédéfini à la compilation ? Toujours pas de l'optimisation ici.

                Pour les conteneurs, si tu te démerdes bien tu peux changer de conteneurs facilement, si ils ont les mêmes comportements.

                -
                Edité par Cytosol 15 juillet 2013 à 10:40:51

                • Partager sur Facebook
                • Partager sur Twitter
                  15 juillet 2013 à 10:48:22

                  Cytosol a écrit:

                  Donc oui comme tu dis trouver la structure de données qui te convient tu peux le faire avant. Mais la je dirais que c'est plus un soucis de convenience. Le choix string/enum c'est un probleme fonctionnel, tu veux que tes données se comportent comme une chaine de caractères ou comme un entier prédéfini à la compilation ? Toujours pas de l'optimisation ici.

                  Oui. Tu as totalement raison. Pour la partie de  ta réponse que je n'ai pas cité non plus d'ailleurs. ;)

                  C'est pour ça d'ailleurs que je suis de son côté. Il a eu une bonne initiative en se posant de bonnes questions, et on lui tatane une citation sans l'expliquer. C'est pour ça que je tiens à ce que la différence soit bien exposée pour qu'il ne s'embrouille pas.

                  Voir plus tard du code dans un projet professionnel fait "à l'arrache" parce que on passe de "ça sert à rien d'optimiser au début" à "ça sert à rien de réfléchir au début", c'est intolérable.

                  -
                  Edité par Xahell 15 juillet 2013 à 10:49:50

                  • Partager sur Facebook
                  • Partager sur Twitter
                    15 juillet 2013 à 14:45:08

                    Je suis d'accord sur le fait d'optimiser à la fin. Moi, ça me ferais mal de supprimer mon code tout optimisé où j'y ai passé pas mal de temps.  Après, ça ne veut pas dire : "Ouais, je m'en fous de faire du code dégueulasse, de toute façon je vais optimiser derrière".

                    Personnellement, je code proprement et lorsque que toutes les fonctionnalités et le core de mon jeu sont terminés, là je peux penser à optimiser.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      15 juillet 2013 à 15:43:06

                      J'ai dû toucher une corde sensible...y'a du monde tout à coup:-°

                      Je tiens à préciser que je ne cherche pas non plus a vouloir tout optimiser de suite mais c'est vrai que je bosse avec 3 projets: serveur, client + un programme fourre tout où je fais des tests lorsque j'ai un doute sur un truc

                      Je sais très bien que j'ai plein de truc pas opti du tout, par exemple, l'envoie de mes données, j'avais fait un truc à l'arrache en envoyant des strings, ça me convenait pas, j'ai changé de méthode tout en sachant qu'elle n'est pas parfaite et je l'ai mis dans ma liste ToDo (d'ailleurs pour le moment, j'ai plus de 40 lignes comme ça si ça peut vous rassurer), par contre, je sais que même si je fais des modifs dessus, je n'aurai pas à tout de retaper, juste ma méthode de "deserialization" (rien à voir avec boost ^^), et je n'aurais quasiment pas à toucher au reste. Donc quand je sais qu'il n'y aura pas de gros impacts derrière, je ne cherche pas non plus à faire un truc top dès le départ car je suis conscient que ça peut re-changer après lorsque j'aurai tenu compte du reste

                      Pour finir, je dois avouer que ma phrase : "un mec a dit ça alors il faut l'appliquer à la lettre" c'était un peu de la provoc car ça me faisait marrer qu'on me balance la fameuse phrase sans chercher plus loin :p

                      En tout cas, merci, je prend note de vos conseils (les constructifs)

                      • Partager sur Facebook
                      • Partager sur Twitter
                        15 juillet 2013 à 17:17:26

                        Mais ça c'est, comme je l'ai dit, pas vraiment de "l'optimisation". Envoyer des strings ou des données sérialisées ça relève plutôt d'un choix de conception, de contraintes techniques, etc...

                        -
                        Edité par Cytosol 15 juillet 2013 à 17:17:54

                        • Partager sur Facebook
                        • Partager sur Twitter
                          15 juillet 2013 à 17:33:12

                          Faut pas qu'on joue sur les mots...pour cet exemple: j'envoyais tout en string, ça faisait plus de 60 octets par paquets, sans compter que je devais les passer le float->string, et l'inverse à la réception...(sans compter les découpages avec tokenizer, "recollages"...) alors que là je n'ai aucune conversion à faire des 2 côtes et je n'envoie plus que 28 octets pour le même type de message...c'est un peu de l'optimisation je pense...mais bon je vois bien que vous êtes sur mon dos, c'est pas grave... :D
                          • Partager sur Facebook
                          • Partager sur Twitter
                            15 juillet 2013 à 19:12:20

                            @Xahell: Haskell, enum ca n'introduit pas exactement le même genre de point de variation que string/int, par contre string/int, si tu dois pouvoir switcher rapidement. Une interface ça se templatise, si un élément doit travailler sur un KeyType, alors :

                            template<class KeyType>
                            void fun(const KeyType& a)
                            { }

                            Et pas :

                            void fun(const std::string& s)
                            { }

                            Si le premier ne suffit pas, c'est que ce n'est pas uniquement le concept de KeyType qui est utilisé. Signe d'un problème de séparation des concepts peut-être.

                            • Partager sur Facebook
                            • Partager sur Twitter
                            FaQ : Fr | En 1 2 | C++11 | Template || Blog : Deloget | C++|Boost--Dev | C++Next | GotW || Installer Boost
                              15 juillet 2013 à 19:38:30

                              @Freedrom: je ne vois pas ce qu'un template change au problème ? Un template n'est pas magique, il génère juste du code, que ce soit à des fins de paramétrisation ou en méta-prog. Et dans ce code généré, il y a l'API que tu utilises.

                              Template ou pas, il devra quand même faire du refactoring sur son code pour modifier tous les appels à la méthode/fonction et changer toutes ses clefs string en clef int correspondantes. S'il y avait de la persistance dans son projet, il va devoir faire des mises à jour sur ses bases de données. Avec les IDE d'aujourd'hui et un peu de jugeote, c'est pas long. Mais c'est aussi inutile.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                15 juillet 2013 à 19:55:23

                                (je parle juste du code, pas des éléments extérieur au code comme les bases de donnée)

                                Ça change qu'il n'y a rien à changer si ce n'est un :

                                typedef int KeyType;

                                en

                                typedef std::string KeyType;

                                et quelques éléments en plus, et pas une grosse partie du code comme mentionné avant. (en vrac, la fonction de génération de clé, si elle existe, puisqu'elle n'est pas lié au concept de clé, et les clés introduites en dur, qui devraient être dans une section très localisé). On est loin de "tous les appels".

                                Après en effet il y a la base de données, sauf que ça n'a aucun importance, la base de données que tu utilises avant d'arrivé en rc (donc après optimisation) n'est pas vraiment sensé être la base de données réel mais juste représentatif du besoin (besoin qui évolue selon la phase de développement).

                                Et quand à l'inutilité, pouvoir voir directement ce que représente la clé pendant le debug (en voyant directement sa valeur) plutôt que réfléchir à quoi correspond la valeur "1", je trouve ça utile personnellement ...

                                -
                                Edité par Freedom 15 juillet 2013 à 19:58:37

                                • Partager sur Facebook
                                • Partager sur Twitter
                                FaQ : Fr | En 1 2 | C++11 | Template || Blog : Deloget | C++|Boost--Dev | C++Next | GotW || Installer Boost
                                  15 juillet 2013 à 20:13:25

                                  Tu m'as rendu curieux. L'argument du debug est intéressant.

                                  Il me manque quand même un élément. Comment tu passes d'une fonction de génération a des identifiants qui ont un sens en debug ?

                                  Ou alors tu ne faisais référence qu'aux clefs en dur ? Les clefs en dure, ça laisse quand même des valeurs comme 123456 ou 111111 qui sont également repérables.

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    15 juillet 2013 à 20:34:17

                                    Oui, je pensais aux clés en dur, pour celle générées, en générales elles ne sont pas faites pour avoir un sens autre que "les clés sont les même ou pas". Après il se peut qu'au final il n'y ai pas de clés en dur au final, mais avoir à un instant T la possibilité de tester / debuger des choses en introduisant des clés avec des noms, c'est toujours plus simple que des clés nommées avec des nombres (le mot peut avoir un sens par simple lecture, le nombre c'est par mémorisation).

                                    Au final, ce que je soulignais, c'est que oui, si tu y penses à un moment tu peux mettre des int (ou un autre type fondamental), comme utiliser une boost::flat_map à la place d'un map par exemple, mais qu'au final le "quand" tu le fais ne dois pas avoir d'importance (si ce n'est "avant la rc") et que switcher ne devrait pas être un frein au développement. Sans oublier que l'intuition de ce qui est le mieux c'est bien, mais que rien ne vaut un bench (pour départager ce qui est proche au niveau complexité asymptotique).

                                    -
                                    Edité par Freedom 15 juillet 2013 à 20:36:27

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    FaQ : Fr | En 1 2 | C++11 | Template || Blog : Deloget | C++|Boost--Dev | C++Next | GotW || Installer Boost
                                      15 juillet 2013 à 21:43:03

                                      Bonsoir,

                                      J'ai pas tout lu donc desole si ca a deja etait dit, mais pour ce qui est la gestion des Joeurs / NPC / Objets pour info, je te conseil de :

                                      Faire une classe GameObject avec des infos de base (guid, position, type) et plein de classes qui heriteront de celle ci (Unit > Npc, player ; Objects, ect ect) qui auront leur propres attributs (les unit auront de la vie, de lenergie, une faction, un niveau alors que les Objects auront plutot un type, une competence, une action ...)

                                      Tout ca dans une liste, le joueur sera bien evidement dans celle ci) ce qui permet de lros des actualisations avec le serveur, d'avoir qu une seule grande liste a actualisee.

                                      On appel ca generalement un ObjectManager, tu peut regarder un peut sur le net. TOUT les mmo fonctionnent de cette facon.

                                      Thomas

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        15 juillet 2013 à 21:47:23

                                        Bonsoir,

                                        Merci d'apporter ta lanterne mais tu devrais lire du début car en fait on cherche justement à éviter ce beau bordel d'héritage (enfin, y'en a quand même un peu obligatoirement mais très très peu) :p

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          16 juillet 2013 à 10:49:34

                                          @Freedom: Je vois.

                                          Je n'ai jamais eu ce besoin (d'avoir des identifiants en chaîne de caractères pour débugger), mais je comprends. Je manipule plutôt une batterie de tests unitaires et de scénarios qui rendent les besoins en debugger "à la main" assez rares.

                                          Ce qui joue peut-être, c'est que les tests complexes se basent sur des mocks, donc il est assez simple de simuler les entrées/sorties et une valeur repérable suffit amplement pour chaque cas (puisque c'est généralement la seule).

                                          Pour ce qui es de changer l'organisation interne d'une classe (map <-> flat_map), c'est un des principes de base de la POO, donc ça n'affecte en rien le développement, bien évidement.

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            16 juillet 2013 à 12:24:32

                                            Perso moi, je ne me casses pas la tête, je regroupe toutes les classes du même module dans un dossier et je fais mon propre moteur en fonction de ce que je maîtrise, je trouve que c'est le plus simple et en utilisant une ou plusieurs librairies comme la SFML, Qt, GMP, boost, etc... qui gèrent tout ce qui est bas niveau, c'est le top.

                                            Mon moteur de jeux est composé comme suit :

                                            Le moteur graphique (caméra, sprites, effets spéciaux, animations, etc...), le moteur réseau (cryptage, envoi/réception de paquets, etc..) mais toi c'est un rpg et pas un mmorpg donc je ne sais pas si tu as fais un moteur réseau, le moteur de collisions et de particules (les classes gérant les maths, la physique, les volumes englobants, etc...), le monde. (monstres, personnages, maps, etc...), l'intelligence artificielle (décisions des monstres (attaquer, s'enfuir, etc..)), le moteur de lumière (lumières, ombres, intersections lumières/entités, etc...), le moteur de chargement de textures et de map. (Chargement de map, de textures, sauvegarde de parties/personnages, etc...)

                                            Ca me fais une structure bien organisée et un code source dans lequel je peux me repérer facilement.

                                            Et tu fais bien sur une classe par élément important : une pour la caméra, une classe pour l'affichage, une pour les sprites, une pour les animations, une pour les personnages, une pour les monstres, une pour les lumières, une pour les ombres, une pour le chargement des textures, une classe pour le chargement de la map, etc...)

                                            Et tu peux aussi faire une classe Entité dont héritent toutes les classes Monstres et Personnage si elle ont des propriétés commune du genre la position, etc...

                                            Moi j'ai une classe Entité dont hérite chaque classe du moteur graphique qui affiche une entité (une animations, un sprite, etc...) et chaque classe qui est une entité du monde qui contient une ou plusieurs entités graphiques. (un personnage, un monstre, une lumière, une ombre, etc...)

                                            Je récupère facilement tout ces éléments ainsi pour récupérer les sprites de toutes mes entités (car tout ce qui hérite de entité est stocké de la grille de ma map.), je récupère ainsi tout ce qui est visible à la caméra et je les colle dans une tilemap ou une texture de rendu pour les afficher à l'écran.

                                            Je peux te dire que c'est simple et rapide.

                                            Si t'a plusieurs type d'ombre et de lumière tu peux aussi faire une classe héritée, ça, ça dépend de ce que tu veux faire.

                                            -
                                            Edité par StarShadow 16 juillet 2013 à 12:26:10

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              16 juillet 2013 à 13:06:38

                                              StarShadow a écrit:

                                              Et tu peux aussi faire une classe Entité dont héritent toutes les classes Monstres et Personnage si elle ont des propriétés commune du genre la position, etc...

                                              Moi j'ai une classe Entité dont hérite chaque classe du moteur graphique qui affiche une entité (une animations, un sprite, etc...) et chaque classe qui est une entité du monde qui contient une ou plusieurs entités graphiques. (un personnage, un monstre, une lumière, une ombre, etc...)

                                              Une petite lecture du fil complet (enfin, au moins fin page 1 + page 2) pourrait t'apporter des infos intéressantes ;) .

                                              -
                                              Edité par Ksass`Peuk 16 juillet 2013 à 13:07:52

                                              • Partager sur Facebook
                                              • Partager sur Twitter

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

                                                16 juillet 2013 à 15:03:50

                                                Oui je viens de tout lire mais il y'a des choses qui m'ont choqué :

                                                Quand vous parler du main ça vous faîtes comme vous voulez mais il faut absolument une classe qui se charge d'initialiser la configuration et plusieurs classes qui instancient les différents moteurs utilisé dans le jeux. (Moteur réseau, moteur graphique, moteurs de chargement de textures/map/sons, etc...)

                                                Sinon vous aller vous planter.

                                                Ces moteurs doivent être des classes statiques car ce sont des éléments unique qui gèrent des composants : Ils les suppriment, les remettent à jour, etc... (J'appelle ces classes là des manager ou encore, des systèmes.)

                                                Maintenant que vous faîtes une classe Base qui se charge d'instancier tout les systèmes, de charger toutes les ressources et qui est appelé dans le main ou que vous faîtes tout dans le main ça, ça dépend de vous mais éviter d'avoir un main trop gros sinon vous aller vous planter.

                                                Les sytèmes doivent pouvoir renvoyé que les composants qui les intéressent c'est à dire, pour l'affichage par exemple, ne récupérer que les entités qui sont visible à l'écran, ils doivent pouvoir aussi se débarrasser des composants ou les créer quand cela est nécessaire. (Donc ni avant, ni après.)

                                                C'est ça la partie la plus difficile qui pose souvent problème de mon côté.

                                                En ce qui concerne les composants maintenant : pas trop d'héritage, si certains composants peuvent faire des choses que d'autres ne peuvent pas faire, faîtes les hériter d'une classe qui contient des propriétés communes à tous ces composants et d'une interface. (je sais pas si il y en a ici qui ont déjà fait du java, le principe est le même.)

                                                Cette interface ne doit contenir que des méthode virtuelle pure et donc être 100% abstraite et tout les composants devant avoir un tel type de comportement devront hériter de cette interface, c'est beaucoup plus simple à comprendre surtout pour les non programmeurs de leur dire si votre composant ou bien votre objet permet de faire ça il doit implémenter tel interface.

                                                De plus ceci vous permettra d'adapter facilement les différents designs pattern à votre projet.

                                                N'hésiter pas non plus à commenter beaucoup votre code, rédiger des documents sur ce que vous faîtes et réfléchir, faire des diagrammes sur pc ou bien sur papier mais juste sur la structure globale, pas sur toutes les classes ni tout les attributs, il y en a bien de trop!

                                                Si un algorithme vous pose problème, poser le problème sur une feuille de papier, dessiner la situation et essayer de le résoudre. (Exemple : Trouvé la droite qui coupe un nuage de points en 2.)

                                                Cela fait depuis plusieurs années que je travaille sur un projet de mmorpg et je dois vous dire que si vous ne faîtes pas comme ça vous aller vous planter  car vous aller devoir modifier beaucoup trop votre code, vous aller avoir des bugs ou des crashs comme pas possible et vous aller pas savoir d'ou ça vient, etc...

                                                Je le sais j'ai travailler aussi sur plusieurs projets avant de commencé le mieux, fait par des gens qui n'ont jamais fait d'études sur la conception de programmes, juste des développeur amateurs donc qui ont tout appris sur ce site, je peux vous dire que j'ai du abandonner leur projet.

                                                Pour la structure, que vous stocker tout dans une grille ou bien un arbre peu importe, c'est pas trop compliqué de la changé après si vous avez bien tout conçu.

                                                Donc là, je ne parle pas d'optimisation de code mais juste de la conception, on est bien d'accord.

                                                Ne chercher pas à faire un code optimisé dès le départ ça ne sert à rien, et faîtes le au fur et à mesure, par exemple, afficher d'abord les sprites un par un puis essayer de vous poser la question est ce que je pourrai pas faire mieux en affichant plusieurs sprite en une seule fois ?

                                                Et si vodre code est trop lent et que ça tourne à 1 FPS au mons, n'hésiter pas à utiliser un profiler.

                                                Vous pouvez utiliser plusieurs thread qui gèrent chacun un système ou plusieurs, mais dans ce cas la, faîtes attention aux accès concurrents. (accès à la même variable en même temps par deux ou plusieurs thread.)

                                                Les accès concurrents sont difficile à déboguer donc moi j'ai tout fais dans un seul thread (sauf là ou je n'avais pas le choix car sinon ça freezerait le jeux.)

                                                Bref maintenant je veux forcer personne à faire comme ça mais à vos risque et périls si vous ne faîtes pas comme ça, vous risquez fort de vous planter et de devoir modifier beaucoup de code.

                                                Ca m'est déja arrive quand j'étais encore un novice.

                                                -
                                                Edité par StarShadow 16 juillet 2013 à 15:04:39

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  16 juillet 2013 à 15:21:29

                                                  C'est compris Ksass`, Xahell, int21h, lmghs ? faites attention avec vos solutions vous risquez de vous planter comme quand StarShadow était novice !
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    16 juillet 2013 à 18:44:03

                                                    La partie "Moteurs" graphiques & cie-multimedia, je décroche, car cela ne m’intéresse absolument pas -- d'où que je décroche là.

                                                    Je suis (étais) plus intéressé par le coeur des choses : mettre en place des systèmes de règles suffisamment adaptés à simuler des systèmes relativement touche à tout (oui, j'en suis resté à D&D3e, puis le système Dk ; maintenant, je préfère le sans règles), ou des IA. Bref.

                                                    Par contre, "classe statique", ça n'existe pas en C++. OK, je vois de quoi tu parles -> pattern monostate et autres singletons et god objets (des variables globales déguisées quoi). Bref, cela me rappelle un vieux message que j'avais lu sur gamasutra (je crois) au sujet que les singletons c'est mal et même et surtout dans des vrais jeux car il arrive vite le moment où le truc que l'on croyait unique ne l'est pas un seul instant.

                                                    BTW, on a mieux que les interfaces en C++ -> le pattern NVI.

                                                    Sinon, il y a plus d'une vérité dans le post de StarShadow, et il est toujours bon d'écouter l'expérience des autres. Même si après on peut pinailler sur tel ou tel autre point -- comme je ne sais pas m’empêcher de faire ^^'

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                    C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                                      16 juillet 2013 à 19:19:57

                                                      Par classe statique, je parlais bien évidement des singletons, il y a des classes ou je n'utilise que des méthodes et variables statiques.

                                                      Mais il faut bien sûr être sûr que l'objet soit bien unique.

                                                       Maintenant oui il y a toujours moyen de pinailler si tu utilises plusieurs moteur graphiques par exemple mais je te conseille de toujours avoir un objet unique qui vérifie si tout a été bien instancié avant d'utiliser les composants ça t'évitera de faire références à des composants qui n'ont pas été créer.

                                                      Et tu n'aura qu'à changé la référence ou le pointeurs si tu veux changer de moteur de rendu par exemple.

                                                      Personnellement les singletons on m'a toujours conseillé d'en utiliser lors de mes études pour éviter les crash quand tu oublies de créer un composant avant de l'utiliser., donc, non, les singletons ce n'est pas si mal que ça.

                                                      Moi je crée donc toujours un objet unique dans le main (Network, World,LightManager par exemple qui appelles des fonctions qui créent, détruisent et mettent à jour des composants ou des ressources de mon jeux.)

                                                      Je ne connais pas le pattern NVI, merci de l'avoir évoqué. (Il faut dire je n'ai pas encore vraiment commencé à coder le gameplay et à m'intérroger sur ce que les persos pourront faire avec les armes et ne pas faire.)

                                                      Et bon le système d'interface m'a toujours suffit jusqu'à présent mais je vais quand même regarder ton pattern NVI.

                                                      Mais bon pour moi ceci relève plus déjà vers du pinaillement et donc je vais m'arrêter là.

                                                      Mon but était de vous guider sur une structure de base en ce qui concerne la conception de grosses API en général qu'on doit respecter si on ne veut pas se planter et que j'utilise pour concevoir des grosses API, pas commencer à débattre indéfiniment pour savoir comment chacun fait en détail. (Car ça varie de trop en fonctions des développeurs et des différents langages de programmation ça.)

                                                      Donc ce sera mon unique et dernier post pour se sujet, en espérant avoir pu vous aider.

                                                      -
                                                      Edité par StarShadow 16 juillet 2013 à 19:20:44

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        16 juillet 2013 à 19:29:27

                                                        Le pattern NVI c'est très générique comme pattern, ce n'est pas spécifique à l'implémentation du Gameplay.

                                                        Pour le singleton, la question a déjà été abordé de multiple fois. Il vaut ce qu'il vaut : un objet global. Et il pose les problèmes d'implémentation qu'il pose (ou posait si tu es passé au C++11 ou que ton langage le gère "bien").

                                                        "Mon but était de vous guider sur une structure de base en ce qui concerne la conception de grosses API en général qu'on doit respecter si on ne veut pas se planter et que j'utilise pour concevoir des grosses API, pas commencer à débattre indéfiniment pour savoir comment chacun fait en détail. "

                                                        Donc tu proposes un avis (qu'on partage ou non), mais refuse d'en débattre ?

                                                        -
                                                        Edité par Freedom 16 juillet 2013 à 19:32:11

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                        FaQ : Fr | En 1 2 | C++11 | Template || Blog : Deloget | C++|Boost--Dev | C++Next | GotW || Installer Boost
                                                          16 juillet 2013 à 19:44:55

                                                          Le pattern NVI c'est très générique comme pattern, ce n'est pas spécifique à l'implémentation du Gameplay.

                                                          Ok alors je vais simplement utiliser des classes 100% abstraite, je préfère utiliser des patternes qui ne sont pas spécifiques à un langage de programmations car je développe dans pas mal de langages différents.

                                                          Pour le singleton, la question a déjà été abordé de multiple fois. Il vaut ce qu'il vaut : une variable statique. Et il pose les problèmes d'implémentation qu'il pose (ou posait si tu es passé au C++11 ou que ton langage le gère "bien").

                                                          Le singleton ne me pose pas de problème, il suffit de savoir bien les gérer. (Exemple : un singleton qui se charge de créer la texture si elle n'existe pas ou de la récupérer si elle existe, cela évite d'utiliser une texture qui n'a pas été chargée car le singleton se charge de la charger si elle n'a pas été chargée et renvoie une erreur si elle n'a pas pu être chargée.)

                                                          Et non je ne suis pas passé au c++11, le c++ standard me suffit.

                                                          Donc tu proposes un avis (qu'on partage ou non), mais refuse d'en débattre ?

                                                          Cette structure est simple et déjà standardisée dans beaucoup de moteur de jeux, si elle te pose problème, le mieux est d'utiliser un moteur de jeux, il n'y a pas vraiment lieu de débattre là dessus, c'est plus un choix que un débat, maintenant si vous voulez débattre sur des détails alors là..., il y a plus lieu de débattre, donc bon, je refuserai pas de débattre si vous voulez plus de détail sur le sujet, mais je vous préviens, je risque fort de m'y perdre.

                                                          PS : c'est comme débattre sur le fait de ce qui est mieux entre les pointeurs et les références, y'a pas vraiment de choix standard, certains pourront très bien gérer avec des pointeurs tandis que d'autres préfèrerons utiliser des références.)

                                                          Mais dans tout les cas y'a un mécanisme de base à respecter qu'il faut suivre pour ne pas se planter, et sur laquelle on ne peut pas débattre, donc ce n'est pas le fait que je refuse de débattre.

                                                          -
                                                          Edité par StarShadow 16 juillet 2013 à 20:02:12

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            16 juillet 2013 à 20:11:26

                                                            StarShadow a écrit:

                                                            Et non je ne suis pas passé au c++11, le c++ standard me suffit.

                                                            Le C++11 est le standard o_O . Heureusement qu'on utilise plus le C++ tel qu'il était en 83 sinon on n'aurait pas des masses évolué.

                                                            StarShadow a écrit:

                                                            Le singleton ne me pose pas de problème, il suffit de savoir bien les gérer. (Exemple : un singleton qui se charge de créer la texture si elle n'existe pas ou de la récupérer si elle existe, cela évite d'utiliser une texture qui n'a pas été chargée car le singleton se charge de la charger si elle n'a pas été chargée et renvoie une erreur si elle n'a pas pu être chargée.)

                                                            La plupart des implémentations de singletons ne sont pas thread-safe. Ce qui est un peu dommage, c'est que les utilisateurs y font rarement attention et ça peut entraîner des bugs difficiles à reproduire.

                                                            StarShadow a écrit:

                                                            PS : c'est comme débattre sur le fait de ce qui est mieux entre les pointeurs et les références, y'a pas vraiment de choix standard, certains pourront très bien gérer avec des pointeurs tandis que d'autres préfèrerons utiliser des références.)

                                                            Ils ont quand même une sémantique différente. Aussi la formalisation des programmes les utilisant ne sera clairement pas la même.

                                                            StarShadow a écrit:

                                                            Mais dans tout les cas y'a un mécanisme de base à respecter qu'il faut suivre pour ne pas se planter, et sur laquelle on ne peut pas débattre, donc ce n'est pas le fait que je refuse de débattre.

                                                            Heureusement qu'on peut débattre sur les mécanismes existant sinon on évoluerait pas ...

                                                            -
                                                            Edité par Ksass`Peuk 16 juillet 2013 à 20:16:40

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter

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

                                                              16 juillet 2013 à 21:14:17

                                                              Le C++11 est le standard  . Heureusement qu'on utilise plus le C++ tel qu'il était en 83 sinon on n'aurait pas des masses évolué.

                                                              Bah je n'utilise plus le c++ de 83 bien sûr, mais le c++11 m'a posé quelques problèmes du coup j'utilise le c++ 2000 et puis avec les librairies qui existent on peut facilement utiliser des fonctionnalités du c++11 compatible avec plusieurs os et qui incluaient déjà avant des nouvelles fonctionnalité du c++11.

                                                              La plupart des implémentations de singletons ne sont pas thread-safe. Ce qui est un peu dommage, c'est que les utilisateurs y font rarement attention et ça peut entraîner des bugs difficiles à reproduire.

                                                              Oui j'ai eu des problèmes d'accès concurrent avec différents moteurs de jeux que je n'arrivais pas à résoudre, c'est pour ça que j'ai décider de coder mon propre moteur de jeux, afin de rendre mes singletons thread safe. (Ce que les moteurs de jeux ne font pas.)

                                                              J'ai eu ce problème avec un thread qui réceptionnait les données (du singleton de mon moteur réseau.) et l'autre thread qui envoyaient les données, quand les 2 threads utilisaient le même socket en même temps (l'un pour recevoir, l'autre pour envoyer), j'avais des paquets vides et tout mon moteur de jeux qui se bloquait, parfois difficile de voir d'ou vient le problème, j'ai même mis longtemps avant de savoir d'ou venait le problème.

                                                              La seule solution si tu veux éviter ce problème, utiliser un seul thread, par contre, méfie toi des librairies qui utilisent des threads en interne, car singleton ou pas, tu risques quand même d'avoir des problèmes.

                                                              Donc bon même si tu n'utilise pas un singleton dans se cas là..., ça va pas trop te sauver.

                                                              Je vois pas trop se que le singleton viendrait engendré comme problème dans ce cas là, c'est plutôt un problème de savoir si tu veux utiliser plusieurs thread ou pas et de bien protéger tes données si tu utilises plusieurs thread.

                                                              Ils ont quand même une sémantique différente. Aussi la formalisation des programmes les utilisant ne sera clairement pas la même.

                                                              Personnellement j'utilise les 2, pointeurs et références, j'utilise les références plutôt pour passer des objets à une autre classe ou à une autre fonction. (C'est plus simple c'est vrai et la syntaxe est moins lourde.)

                                                              Et j'utilise des pointeurs pour libérer ou bien créer des ressources qui ne sont pas tout le temps utilisées dans l'application.

                                                              Il est clair que la sémantique ne sera pas la même si tu fais tout par pointeurs car par pointeurs il faut en plus un constructeur de copie si ta classe est copiable, bref, je suppose que je ne t'apprends rien en disant ça, donc oui c'est plus simple avec des références, mais pas impossible avec des pointeurs.

                                                              Mais tu ne peux pourra pas tout faire avec des références, n'oublie que pas les références doivent être initialisée dès leur déclaration.

                                                              Heureusement qu'on peut débattre sur les mécanismes existant sinon on évoluerait pas ...

                                                              Je voulais juste dire que le fait de ne pas les utiliser conduit à un code bordélique qui risque fort de planter.

                                                              C'est comme me dire par exemple qu'un singleton c'est mal d'en utilisé un, désolé mais moi je ne suis pas vraiment d'accord là dessus.

                                                              C'est l'utilisation qu'on en fait qui est mal, ci ceux-ci étaient thread-safe ça n'aurait jamais causé de problèmes mais bon tu vois on évolue et à mon avis avant les threads ça n'existait pas, tout tournais en mono-thread donc ils avaient pas prévu ça donc oui ça, les mécanismes doivent évolue, là je suis d'accord, c'est sur le fait de dire ne pas les utiliser parce qu'on en fait une utilisation mauvaise que là je suis pas trop d'accord.

                                                              PS : maintenant si tu as une solution pour avoir plus facile pour débuguer au cas ou l'on utiliserait plusieurs thread ça, je suis preneur mais je pense que il faudra attendre que les moteurs de jeux aient des singletons qui sont thread-safe pour ça.

                                                              -
                                                              Edité par StarShadow 16 juillet 2013 à 21:38:58

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Comment structurer un jeu en c++

                                                              × 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