Je crée mon jeu vidéo E15 : J'arrête...

Posté par  (Mastodon) . Édité par Benoît Sibaud et palm123. Modéré par Pierre Jarillon. Licence CC By‑SA.
Étiquettes :
46
30
août
2015
Jeu

«Je crée mon jeu vidéo» est une série d'articles sur la création d'un jeu vidéo, depuis la feuille blanche jusqu'au résultat final. On y parlera de tout : de la technique, du contenu, de la joie de voir bouger des sprites, de la lassitude du développement solitaire, etc. Vous pourrez suivre cette série grâce au tag gamedev.

Dans l'épisode 14 (il y a trop longtemps), on a discuté des formats de données et de compilation croisée. Pour cet épisode, je vais expliquer pourquoi j'arrête. Il y a tout un tas de raison que je vais tâcher d'expliquer.

Bon, allez, j'avoue : je n'arrête pas Akagoria ni cette série d'épisodes. Faut pas déconner non plus. C'était juste pour l'aguiche. Mais j'arrête une expérience qui était à l'origine d'Akagoria : les systèmes à entités. Souvenez-vous, c'était le premier épisode de la série.

Les systèmes à entités

Les limites

Conceptuellement, les systèmes à entités, c'est vraiment satisfaisant. Dans la pratique, c'est très compliqué. Parce que dès qu'on sort des exemples tarte à la crème, c'est très difficile de bien délimiter les composants et les systèmes. Et c'est encore plus compliqué quand on interagit avec des bibliothèques externes qui ne sont souvent pas prévues pour ça. Par conséquent, on passe beaucoup de temps à tâtonner à faire des gros composants, puis des petits composants, puis des gros systèmes, puis des petits systèmes. Et au final, on n'a rien fait à part des réusinages qui n'ont pas fait avancer le jeu.

Je pense qu'on n'a pas assez de recul sur ce paradigme pour pouvoir l'utiliser sur de gros projets. Quand je dis «pas assez de recul», je veux dire qu'il manque beaucoup de choses, notamment une méthodologie globale pour bien choisir ses composants, mais également des exemples un peu plus complexes qui permettent de voir qu'un système à entités seul, ça ne sert pas à grand chose. Certes, ça peut constituer une ossature pour un projet, mais il est nécessaire d'avoir d'autres paradigmes qui interviennent. Et l'articulation entre les systèmes à entités et ces autres paradigmes n'est expliquée nulle part et peut se révéler très compliquée.

Quoi d'autre ?

Si j'abandonne les systèmes à entités, par quoi les remplacer ? He bien, par une approche plus traditionnelle, une approche à objets. Parce qu'au final, c'est une approche suffisamment simple pour être flexible. Bien sûr, ça ne veut pas dire faire de grosses hiérarchie de classes. L'expérience m'a montré que trois étages de hiérarchie permettent de gérer toutes les situations, et souvent deux suffisent. Sans oublier que ce qui compte aussi, c'est un bon agencement des données. C'est peut-être une des leçons que j'ai retenues avec les systèmes à entités.

Depuis le début d'Akagoria, j'ai produit plusieurs jeux (souvent pour des gamejams), et chaque fois, utiliser une approche objet a permis de faire tout ce qu'on voulait. Dans le cadre du club de développement de jeux vidéo que j'anime, j'encourage les étudiants à partir dans cette voie. Pas uniquement parce que c'est ce qu'ils connaissent, mais aussi parce que c'est ce qui me semble le plus naturel à expliquer et à utiliser. Les systèmes à entités ne me semblent pas aussi naturels, ils forcent à avoir une vision globale et complète avant de commencer un jeu, là où il est plus facile de procéder de manière incrémentale dans un paradigme objet.

Talk is cheap, show me the code

Je ne vais pas vous montrer le code tout de suite. Je n'ai pas encore pushé la nouvelle version d'Akagoria. Elle mijote tranquillement sur mon ordinateur.

Votre branche est en avance sur 'origin/master' de 97 commits

Cependant, elle va arriver. J'aimerais profiter du push qui vient pour parler de tout ce que j'ai pu développer depuis ces derniers mois (ou qui est en cours de développement) dans les prochains épisodes : dialogues, quêtes, interfaces, sauvegardes, etc. Et il y a des challenges qui arrivent. Donc il faudra patienter un peu.

Dialogue dans Akagoria

Autres nouvelles

Il s'est passé beaucoup de temps depuis le dernier épisode. Mais voici quelques nouvelles en marge d'Akagoria.

Migration sur GitLab

Suite à la fermeture programmée de Gitorious, j'ai migré les deux dépôts qui s'y trouvaient sur GitLab : celui du jeu et celui du site web. J'hésite à tout migrer sur GitHub puisque c'est là que sont tous mes autres dépôts. Au départ, j'avais envie d'utiliser Gitorious parce que c'était libre, et même copyleft. Mais il faut bien avouer que Gitorious n'était pas aussi simple à utiliser que GitHub, sans compter les lenteurs trop fréquentes. Je connais un peu GitLab (il y a une instance qui tourne dans mon labo) mais pas assez pour juger de son efficacité.

Au final, je pense que c'est plus simple de tout centraliser (oui c'est mal) sur GitHub parce que ça me simplifiera les choses plutôt que de devoir gérer deux forges. Je laisserai l'ancienne implémentation d'Akagoria (avec les systèmes à entités) sur GitLab.

Une interface graphique pour MapMaker

Vous vous souvenez sans doute de MapMaker, l'outil qui avait permis d'illustrer l'article sur la génération procédurale de carte. Et bien je suis très content de vous apprendre qu'un début d'interface graphique a été développé : mmgui. Je le dis d'autant plus facilement que ce n'est pas moi qui l'ai fait ! C'est en Qt5, ça marche plutôt pas mal pour l'instant. Mon rêve, c'est que ça puisse ressembler un jour à World Machine.

Aller plus loin

  • # Systèmes-Entités-Composants

    Posté par  . Évalué à 10. Dernière modification le 31 août 2015 à 03:53.

    Est-ce qu'il serait possible d'avoir une description plus détaillée des difficultés avec le modèle systèmes-entités-composants ? Ou du moins quelques exemples, même si tu ne reprends pas tous tes problèmes :) .

    Je voyais les systèmes un peu comme des modules, un truc assez simple : un système de combat, un système de mouvement, … Avec quelque chose pour enchaîner tout ça. Est-ce l'enchaînement qui est difficile par exemple, parce qu'on a des actions de différentes natures mêlées et que du coup on sort vite de l'exemple "je lance le système de mouvement qui fait bouger tout le monde, puis le système de combat qui fait tous les combats, puis le système de rendu…" ?

    Ou avec des systèmes plus fins (juste des fonctions permettant de traiter différents aspects des objets animés, en mouvement, …) est-ce qu'il est trop compliqué de construire des fonctions pour traiter les entités ayant tel ou tel composant plutôt que les considérer globalement ? Par exemple pour savoir comment déplacer un personnage j'ai besoin de ses infos de mouvements mais aussi assez souvent d'autres données qui sont dans un autre composant, ça ne se résumé pas à "telle fonction qui s'applique à n'importe quelle entité possédant ce composant" ?

    • [^] # Re: Systèmes-Entités-Composants

      Posté par  (site web personnel) . Évalué à 4.

      J'ai les mêmes demandes à l'auteur du poste :)

      Dés le début, je trouvais que le système de gestion d’événements était traité trop rapidement, alors qu'il est central.

      "La première sécurité est la liberté"

    • [^] # Re: Systèmes-Entités-Composants

      Posté par  (Mastodon) . Évalué à 6.

      Je voyais les systèmes un peu comme des modules, un truc assez simple : un système de combat, un système de mouvement, … Avec quelque chose pour enchaîner tout ça. Est-ce l'enchaînement qui est difficile par exemple, parce qu'on a des actions de différentes natures mêlées et que du coup on sort vite de l'exemple "je lance le système de mouvement qui fait bouger tout le monde, puis le système de combat qui fait tous les combats, puis le système de rendu…" ?
      Ou avec des systèmes plus fins (juste des fonctions permettant de traiter différents aspects des objets animés, en mouvement, …) est-ce qu'il est trop compliqué de construire des fonctions pour traiter les entités ayant tel ou tel composant plutôt que les considérer globalement ? Par exemple pour savoir comment déplacer un personnage j'ai besoin de ses infos de mouvements mais aussi assez souvent d'autres données qui sont dans un autre composant, ça ne se résumé pas à "telle fonction qui s'applique à n'importe quelle entité possédant ce composant" ?

      Je vais donner quelques exemples.

      Quand on a une boucle de jeu traditionnelle, on voit bien comment on récupère les entrées (clavier/souris/manettes). Mais dans un système à entités, c'est plus compliqué. Parce qu'il y a plusieurs entités qui peuvent être manipulées par les entrées : le héros, l'interface graphique, une carte, etc. Et du coup, on ne sait pas très bien où récupérer les entrées, et comment les dispatcher vers la bonne entité. Au début, j'avais mis ça dans un système qui mettait à jour un composant du joueur. Mais après, j'ai vu la limite. Donc j'ai mis la récupération des entrées dans un système Player qui mettait à jour le joueur directement, sans passer par un composant. Mais même là, ce n'était pas très satisfaisant pour les raisons précédentes. Et j'étais vraiment bloqué (et je le suis toujours) pour ce mécanisme d'entrée qui peut piloter plusieurs éléments.

      Autre exemple, l'affichage. Au début, c'est simple, tu as un système Render qui affiche toutes les entités qui doivent être affichées. Sauf que pour certains trucs, c'est un peu plus complexe. Genre une grande carte d'un monde ouvert, tu veux optimiser l'affichage et n'afficher que les tuiles qui sont à proximité du héros. Une solution, c'est de considérer que chaque tuile est une entité et de faire un système spécial qui va optimiser l'affichage. Sauf que tout n'est pas une tuile. Et puis après, il y a les éléments d'interface (la barre de vie, toussa) qui s'affichent toujours. La vraie solution, c'est d'utiliser plusieurs systèmes de Render qui vont avoir chacun leur caractéristique et qui vont afficher chacun une partie de la scène. Mais du coup, ça complexifie énormément, parce qu'on va avoir des composants différents pour chaque système. Et ces composants sont loin d'être simples. Par exemple, afficher un texte ou afficher une minimap, est-ce le même composant ? Ou deux ? Est-ce le même système qui gère les deux ou deux systèmes différents ?

      En vrai, je pense qu'un RPG contient beaucoup trop de diversité et de logique de jeu pour que ce soit faisable dès le premier coup avec un système à entités. Si on part d'un truc existant à transformer, c'est peut-être faisable mais ça demande d'avoir une vision globale de tous les mécanismes et de leurs interactions. Et même après ça, ce ne doit pas être si évident.

      Pour répondre à Nicolas Boulay sur le rôle d'un système de gestion d'événements, j'en avais dit quelques mots dans un épisode précédent. Je continue à croire que la gestion des événements est le grand impensé des systèmes à entités. Un système de gestion d'événements est indispensable mais son interaction avec le système à entités n'est jamais explicité et c'est un grand oubli.

      • [^] # Re: Systèmes-Entités-Composants

        Posté par  (site web personnel) . Évalué à 3.

        "Un système de gestion d'événements est indispensable mais son interaction avec le système à entités n'est jamais explicité et c'est un grand oubli."

        Peut être qu'il faut expliciter les liens de communication entre entité, comme les connecteurs de blocks en sysml ?

        "La première sécurité est la liberté"

        • [^] # Re: Systèmes-Entités-Composants

          Posté par  (Mastodon) . Évalué à 3.

          Oui mais après, comment l'entité reçoit-elle l'événement ? Peut-elle y répondre ? Les entités sont-elles les seules sources d'événements ? Où mettre le bout de code qui gère l'événement pour une entité (une entité n'est qu'un entier, un composant n'est qu'une donnée) ?

          Bref, pas facile.

      • [^] # Re: Systèmes-Entités-Composants

        Posté par  . Évalué à 3.

        D'accord, je pense que je comprends un peu mieux les difficultés.

        Ça rejoint aussi des discussions dans les commentaires d'autres articles que tu as écrits, sur le fait que ce modèle Systèmes-Entités-Composants était plutôt un modèle de conception ou plutôt un paradigme… Quand j'ai lu des articles dessus j'ai vu ça comme un modèle de conception qui consistait à avoir des objets standards (les entités) qui accueillent des composants. Donc on assemble les objets à partir de composants. Comme alternative à la construction d'objets basés sur des classes elles-mêmes assemblées par héritage. Donc quelque chose de plutôt adapté à la représentation du modèle de données du jeu.

        Si je comprends bien tu as tenté d'aller beaucoup plus loin et de tout faire entrer dans ce modèle (ou paradigme, du coup), donc par exemple de représenter l'interface graphique sous forme d'entités et de composants aussi. D'où tes remarques sur le fait que le système d'événements n'était pas trop traité dans tes lectures. À mon avis pour que le modèle SEC soit intéressant il faut qu'il y ait pas mal de petits morceaux d'infos (des composants) assemblés de différentes manières (dans des entités). Ce qui ne correspond pas forcément à tout dans le programmation. Donc je voyais plutôt ce modèle pour les données du jeu, avec des objets plus classiques pour l'interface graphique (et sans système d'événements basé sur le modèle SEC du coup).

        Si l'idée est de gérer l'interface grâce au modèle SEC, est-ce que les entités affichées ne pourraient pas avoir un composant "affiché", qui contient leurs coordonnées sur la vue ? Comme ça savoir sur quoi on a cliqué consiste à piocher dans les entités ayant un composant "affiché" celle(s) dont la position inclut la position du clic (la position de l'entité peut inclure une notion de profondeur, pour sélectionner la bonne en cas de superposition). Du coup le système recevant les événements recherche l'entité concernée, décide de ce qui se passe et lance le traitement approprié (dans un autre système sans doute). On a ici un système qui a un rôle classique de contrôleur. Et c'est ce système de contrôle qui dit "bon, on a un clic gauche sur un ennemi, il faut sans doute l'attaquer" et qui lance le traitement approprié (qui met à jour les entités, …).

        Pour l'affichage je comprends moins bien. Pour l'optimisation, est-ce que tu as un index qui te permet de retrouver les entités affichables qui ont une coordonnée sur la carte avec x entre tant et tant et y entre tant et tant ? Pour l'histoire des composants "texte" et "mini-carte", ça pourrait être une gestion hors des entités-composants, avec des objets classiques plutôt. Ou bien des fonctions permettant d'afficher l'un ou l'autre (le composant "affiché" sert à récupérer toutes les entités à afficher, dont le texte et la mini-carte, puis ensuite on appelle une fonction d'affichage basée sur la classe exacte du composant décrivant la nature de l'élément (donc une hiérarchie de classes pour le composant décrivant la nature de l'entité à afficher)). Là c'est un peu compliqué, mais c'est parce que la représentation par des objets classiques est peut-être plus évidente qu'une représentation par des entités composées de blocs assemblables différemment. En gros je comprends qu'avoir des personnages avec des propriétés réagençables c'est intéressant, y compris pour les marquer comme affichable, affiché, … ; par contre pour des composants graphiques bof : ils ont sans doute un comportement unique et un affichage qui dépend de leur classe, et c'est tout. Donc les représenter par des composants et entités revient un peu à simuler ce système de classes par des entités-composants (par exemple le composant décrivant leur nature, avec choix la méthode de tracer en fonction de ce composant), ce qui est plus compliqué qu'autre chose (a priori, mais il y a peut-être des avantages que je ne vois pas).

        Je n'ai pas non plus bien saisi où tu plaçais tes traitements. Dans ce que j'avais compris, les entités et composants servaient surtout à représenter les données et les systèmes les traitements. Donc on a une séparation très nette données/traitements (ce qu'on ne fait pas forcément dans les jeux avec des objets habituellement). Il n'y a pas trop de problèmes de propagation entre entités parce que ce sont les systèmes qui s'occupent de ça. Et eux-mêmes manipulent des entités sans se soucier de leur classe mais plutôt de leurs composants, c'est-à-dire qu'ils traitent les entités ayant une propriété commune (mobile, ennemi, position, affichable, …), représentée par un composant de la même classe. Ce qui permet de recombiner facilement ces propriétés en les ajoutant/retirant aux entités. Du coup côté interactions ce ne serait pas plus difficile dans ce modèle que dans un jeu classique, puisque c'est fait pareil (sauf la recherche des entités concernées).

        Pour ce qui est de la difficulté à prévoir l'évolution, je pensais qu'au contraire le modèle SEC permettait d'ajouter après coup des propriétés sans avoir à rebricoler des hiérarchies de classes, et que ça simplifiait. Tant qu'on ne s'en sert que pour le modèle de données du jeu en tout cas. Et que les systèmes étaient plutôt gros. Des fonctions normales de moteur de jeu (gestion de combats, d'affichage, …) mais simplement au lieu de se baser sur des classes et des listes pour trouver les données (la liste des bâtiments du jeu par exemple), ils se basaient sur un tas d'entités indexées par composant et que ça permettait par exemple d'implémenter la phase de production du tour en cherchant toutes les entités ayant un composant de production (plutôt que parcourir la liste des bâtiments et regarder pour chacun s'il a des capacités de production), le traitement de production se faisant comme dans un jeu classique. Ce qui permet par exemple à des troupes d'avoir une capacité de production si on le décide plus tard. On pourrait refaire cet exemple avec une capacité de régénération par exemple, si c'est plus proche de ton jeu.

      • [^] # Re: Systèmes-Entités-Composants

        Posté par  . Évalué à 3.

        Je continue à croire que la gestion des événements est le grand impensé des systèmes à entités.

        Je n'ai pas approfondi et je n'ai jamais utilisé ce système, mais j'avais cru comprendre qu'au contraire s'était la base et que c'est un événement qui déclenchait l’exécution de l'ensemble des systèmes.

        En y réfléchissant aujourd'hui, pourquoi tes événements ne sont pas tout simplement des entités ? Tu reçois un événement, tu crée l'entité qui contient l'information utile.

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: Systèmes-Entités-Composants

        Posté par  (site web personnel) . Évalué à 5.

        on ne sait pas très bien où récupérer les entrées, et comment les dispatcher vers la bonne entité

        Il faut séparer les deux avec un pattern command: le joueur n'appuie pas sur des touches pour se déplacer, il donne des ordres de déplacement à une entité de la simulation.

        Par contre je déconseille vivement, sauf pour des jeux très simples, de permettre à une entité de gérer elle même quoique ce soit (et donc le "dispatch vers"), SURTOUT pas la mise à jour d'autres entités: imagine deux tanks qui se tirent dessus dans un RTS. C'est au moteur du jeu d'appliquer les règles de dommages dans le bon ordre, car si tu mets le code aux niveaux des tanks, tu vas te retrouver avec une entité morte qui continue à tirer :-)

        Autre exemple, l'affichage. Au début, c'est simple, tu as un système Render qui affiche toutes les entités qui doivent être affichées. Sauf que pour certains trucs, c'est un peu plus complexe

        Il te faut un scenegraph: tes entités auront des composants faisant référence à des noeuds du scenegraph.

        Un système de gestion d'événements est indispensable mais son interaction avec le système à entités n'est jamais explicité et c'est un grand oubli.

        Il suffit de plugger n'importe quel système d'évènements avec un composant Publisher et un composant Subscriber.

        Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

        • [^] # Re: Systèmes-Entités-Composants

          Posté par  (site web personnel) . Évalué à 2.

          Comment tu fais pour gérer l'ordre des mises à jour dans un tel système ? (genre collision/dessin)

          La gestion d’événements ne rend pas très compliqué la gestion de l'ordre d’exécution des systèmes ?

          "La première sécurité est la liberté"

  • # Hors limites

    Posté par  (site web personnel) . Évalué à 5.

    Je pense que ce qu'il faut retenir de tout cela est que la gestion par entité doit se limiter au modèles et surtout ne pas s'appliquer aux vues et contrôleurs (pour une architecture MVC j'entend).

    Merci pour ce nouvel épisode.

  • # Si tu recules, les autres avancent

    Posté par  (site web personnel) . Évalué à 8. Dernière modification le 31 août 2015 à 14:11.

    Je pense qu'on n'a pas assez de recul sur ce paradigme pour pouvoir l'utiliser sur de gros projets.

    Ce paradigme est mis en œuvre depuis plus de dix ans dans les jeux et les simulations: ça fonctionne très bien. Le problème c'est qu'il perturbe beaucoup les gens qui pensent que ça remplace l'objet, qu'il se suffit à lui même et qu'il faut tout faire avec.

    Un ES permets de lier entre eux (mais ne remplace jamais) les composants essentiels pour un jeu:

    • un système d'évènements.
    • un scenegraph.
    • un moteur d'animation.
    • un moteur physique.
    • un moteur d'IA.

    Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

  • # Les systèmes à entités

    Posté par  . Évalué à 2.

    Conceptuellement, les systèmes à entités, c'est vraiment satisfaisant. Dans la pratique, c'est très compliqué.

    Tu serais surpris de savoir les jeux AAA qui sont fait avec un système à entités. Je ne peux rien dire, mais en tout cas je ne découragerais pas les devs de pousser un peu plus loin le test ;)

    • [^] # Re: Les systèmes à entités

      Posté par  . Évalué à 4. Dernière modification le 31 août 2015 à 15:30.

      Un truc que j'ai remarqué en game dev (mais je pense que ça s'applique au dev de manière général), c'est qu'on a toujours tendance à penser que l'herbe est plus verte ailleurs. Mais il faut se rendre à l'évidence, il n'y a pas de système parfait et il faut faire au mieux avec ce qu'on a. Bien évidemment, il faut optimiser les systèmes aussi, mais ça, ça arrive plus tard, quand tu peux commencer à profiler ton code et donc à détecter les bottlenecks.

      Tout ça pour dire que je pense que tu peux aller loin avec un système à entités. Je dirais qu'un gros avantage de ce système, c'est qu'on peut facilement le rendre data driven. Et ça c'est très très important quand on fait un jeu avec une équipe de plusieurs centaines de personnes incluant des non-dev.

      • [^] # Re: Les systèmes à entités

        Posté par  (site web personnel) . Évalué à 3.

        Quand l'assemblage des composants pour créer des entités est géré par Lua, est-ce encore des données ? D'un point de vue du code C++ oui, mais d'un point de vue conceptuel cela commence à devenir très flou.

        "La première sécurité est la liberté"

        • [^] # Re: Les systèmes à entités

          Posté par  . Évalué à 4.

          Quand l'assemblage des composants pour créer des entités est géré par Lua, est-ce encore des données ?

          OSEF ? On s'en fout de savoir si sous tel angle c'est ou pas géré par les données. Ce qui t'intéresse c'est que là où ça peut t'apporter tu soit data driven et c'est dans ton code natif que ça t'intéresse parce que c'est là que c'est coûteux de faire évoluer ton modèle. Dans le DSL en plus si c'est un langage dynamique, c'est beaucoup moins important voir pas intéressant du tout (notamment pour la fiabilité/simplicité d'utilisation).

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

          • [^] # Re: Les systèmes à entités

            Posté par  (Mastodon) . Évalué à 2.

            Je plussoie. Dans ma nouvelle mouture, j'essaie au maximum de mettre des choses dans des std::vector (et pas des pointeurs, mais des données complètes), qui à utiliser des unions plutôt que de l'héritage, pour justement faciliter le data-driven. C'est une sorte de compromis entre l'ECS pur et l'OO pur.

            • [^] # Re: Les systèmes à entités

              Posté par  . Évalué à 3.

              et pas des pointeurs, mais des données complètes

              Que ce soit des pointeurs, des références ou des structures complètes qu'est-ce que ça change conceptuellement ?

              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

              • [^] # Re: Les systèmes à entités

                Posté par  (Mastodon) . Évalué à 2.

                L'agencement en mémoire et donc l'utilisation des caches. Par exemple, admettons que tu as une structure Vec avec deux float ou deux double ou même trois. Tu peux ranger tes données de deux manières :

                Vec positions1[N]; // tableau de données
                Vec *positions2[N]; // tableau de pointeurs

                Dans le second cas, tes données vont être éparpillées en mémoire et donc tu vas te taper plein de défaut de cache. Dans le premier cas, le processeur va reconnaître un pattern d'accès à la mémoire et va précharger les positions futures, ce qui va considérablement améliorer ton temps de traitement.

                • [^] # Re: Les systèmes à entités

                  Posté par  . Évalué à 2.

                  Loin de moi l'idée de te contredire : c'est évident. Mais par curiosité, est-ce vérifié à l'exécution ?

                  "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                  • [^] # Re: Les systèmes à entités

                    Posté par  (site web personnel) . Évalué à 3.

                    Tout à fait. Voici une présentation sur ce sujet.

                    Il y a d'autres vidéos de la CppCon 14 qui ont le même discours. En gros ils nous disent « on voulait que ça aille vite alors on a fait des tableaux de POD et du traitement en lot ».

                    • [^] # Re: Les systèmes à entités

                      Posté par  . Évalué à 6. Dernière modification le 31 août 2015 à 19:45.

                      Je ne parlais pas de data-driven dans le sens de programmation orientée donnée, mais de data driven dans le sens où c'est la data (des informations hors code) qui dirige le jeu. Par exemple les règles de game design (points de vie des ennemies, type d'IA à utiliser, …) sont dans des fichiers JSON accessible par les game designers. L'un des avantages de la modélisation Entitées-Composants c'est que tu peux facilement lier une telle donnée à un composant.

                      Ceci dit, la programmation orientée donnée n'est pas exclusif et il est très important de penser au coût mémoire qu'aura tel ou tel algorithme. Cependant une autre règle intéressante à garder en tête est de ne pas commencer à optimiser tant qu'on n'a pas fait de profiling. Il faut toujours optimiser ce que l'on voit dans un profiling. Sinon on peut passer une semaine à optimiser un bout de code qui n'est finalement appelé qu'une seule fois par trame alors que de l'autre coté on a une fonction qui est appelée 100 fois par trame et qui mériterait bien plus d'amour.

                      • [^] # Re: Les systèmes à entités

                        Posté par  . Évalué à 8.

                        Cependant une autre règle intéressante à garder en tête est de ne pas commencer à optimiser tant qu'on n'a pas fait de profiling

                        Ce principe et la citation initiale (premature optimization is the root of evil) ont été sortis à toutes les sauces et beaucoup détourné de leur contexte initial. Il s'applique en fait très bien à ce qu'on appelle la micro-optimisation, celle qui consiste à gagner les cycles cpu cycle par cycle à grand coup de profileur.

                        En revanche, il s'applique beaucoup moins voire pas du tout à des choses qui relèvent beaucoup plus de la conception, comme le choix des conteneurs et des algorithmes adaptés, pour la simple raison que le code n'est en général pas plus compliqué à lire et à écrire avec le conteneur adapté qu'avec celui qui ne l'est pas. On pourrait résumer ça en "ne pas optimiser, mais ne pas pessimiser non plus".

                        Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0

                        • [^] # Re: Les systèmes à entités

                          Posté par  (Mastodon) . Évalué à 3.

                          C'est un peu ce que je fais : choisir le bon container, le bon algorithme et puis après, on regarde. Ne pas refaire les calculs plusieurs fois aussi. Là par exemple, j'avais mis un appel de fonction dans la boucle de jeu mais c'était le même tous les tours. Du coup, je l'ai sorti, j'ai conservé le résultat et ça fait un calcul en moins.

                          • [^] # Re: Les systèmes à entités

                            Posté par  . Évalué à 2.

                            Ne pas refaire les calculs plusieurs fois aussi. Là par exemple, j'avais mis un appel de fonction dans la boucle de jeu mais c'était le même tous les tours. Du coup, je l'ai sorti, j'ai conservé le résultat et ça fait un calcul en moins.

                            Je pense que dans ce cas particulier, c'est une optimisation, mais il y a de nombreux cas où il vaut mieux refaire les calculs que d'utiliser la mémoire, à cause des temps d'accès. Donc une fois de plus, il faut faire du profilage avant d'optimiser :)

                            bépo powered

                        • [^] # Re: Les systèmes à entités

                          Posté par  . Évalué à 3.

                          Pour moi les conteneurs c'est déjà un niveau d'implémentation. Le design c'est ce qui te permet de dire que ce conteneur est adapté (pas qu'en performance).

                          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                  • [^] # Re: Les systèmes à entités

                    Posté par  . Évalué à 1.

                    Je ne suis pas un expert, mais avec les caches et tout le bordel qu'appliquent les processeurs pour optimiser l'exécution de code, un accès à la mémoire "séquentiel" (càd p, p+1, p+2, etc.) prend dans le pire des cas 10 cycles processeurs par accès mémoire. Si tes données sont totalement éparpillées, tu peux te retrouver à avoir du 2000 cycles par accès.

                    Après, les machines sur lesquelles je bossait étaient relativement ancienne (un Pentium et un Xeon de 2007-2008), je ne sais pas quels trucs absurdes ils ont rajouté pour améliorer les perfs entre temps.

                    • [^] # Re: Les systèmes à entités

                      Posté par  . Évalué à 1.

                      Après, les machines sur lesquelles je bossait étaient relativement ancienne (un Pentium et un Xeon de 2007-2008), je ne sais pas quels trucs absurdes ils ont rajoutés pour améliorer les perfs entre temps.

                      Il me semble qu'il y a des recherches de faites pour faire des détections de boucles du type

                      for (int i=0; i<n; i++) { do_something(array[k*i]); }
                      et de faire les prefetch qui vont bien. Ça permettrait de faire des parcours de tableaux 2D par colonnes de manière efficace (en plus du parcourt par lignes).

                      bépo powered

                      • [^] # Re: Les systèmes à entités

                        Posté par  . Évalué à 1. Dernière modification le 01 septembre 2015 à 16:54.

                        Il y a pire. Certains CPUs aujourd'hui sont capables de détecter des dépendance entre instructions. Si une instruction devrait bloquer le CPU, celui-ci à déjà au préalable détecté que d'autres instructions sont indépendantes et va les exécuter pendant ce temps.

                    • [^] # Re: Les systèmes à entités

                      Posté par  . Évalué à 5.

                      C'est toujours le cas, voire même pire encore.

                      La vitesse CPUs s’améliore plus vite que la bande passante (et la latence) d’accès la mémoire.
                      De plus, la taille des caches de niveau L1 et L2 na pas augmentée depuis quelques années. Donc le prefetching ne s’améliore pas vraiment ou bien il ne peut pas s’améliorer assez par manque de place dans les caches L1 et L2.
                      Référence: la présentation de Gil Tene (CTO d'Azul systems, créateur d'une JVM ou le GC ne provoque pas des "stop the world") a DevoxxFR 2015 sur les optimisations de la JVM.

                      Donc stocker une collection de POD de manière contiguë en mémoire a un impact très positif sur les perfs. Et plus le temps passe, plus cella devient vrai, et plus les cache miss sont pénalisant. Cela explique pourquoi Java se dirige doucement vers les "value types" pour Java 10.
                      Référence: la présentation de Brian Goetz (un des architectes de Java) a DevoxxFR 2015 sur le futur de Java.

                      • [^] # Re: Les systèmes à entités

                        Posté par  . Évalué à 6.

                        Donc stocker une collection de POD de manière contiguë en mémoire a un impact très positif sur les perfs.

                        Comme je le disais dans un autre commentaire ça dépend de ton utilisation de ces POD. Si tu as besoin de les trier, si tu passe du temps à en créer/détruire, si tu ne les traites pas de manière groupée alors non, ça n'est pas une bonne idée de les stocker de manière contiguë.

                        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                • [^] # Re: Les systèmes à entités

                  Posté par  . Évalué à 1. Dernière modification le 31 août 2015 à 20:00.

                  Tu peux aussi utiliser des Pool pour ce genre de cas, comme ça tu continues d'utiliser des pointeurs dans tes vecteurs, mais le Pool permet de s'assurer que les objets sont dans la même zone mémoire.

                  Par contre, tu as toujours un risque plus élevé de cache miss (par rapport à un vecteur de non-pointeurs) car même si le pool rassemble tes objets dans la même zone mémoire, ils sont proches, mais pas contigus.

                • [^] # Re: Les systèmes à entités

                  Posté par  . Évalué à 5.

                  Je me suis mal fait comprendre. « qu'est-ce que ça change pour le data driven ? » et du coup rien c'est juste un détail d'implémentation et non un design de conception. AMHA il est important de distinguer le concept que tu met en place (le data driven, le message oriented, l'ES, etc) et la manière dont tu l'implémente (ici des tableaux/vecteurs d'objets). Suivant tes contraintes, contexte ou objectifs la manière d'implémenter devront changer.

                  Mais si tu veux parler d'optimisation ça n'est pas un cas général. Pour que ce que tu dis ai un intérêt il faut t'assurer d'éviter les recopies notamment :

                  • pas trop passer de temps à créer/détruire/créer tes objets
                  • faire attention à la manière dont tu les utilise (en passage de paramètre notamment)

                  Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                • [^] # Re: Les systèmes à entités

                  Posté par  . Évalué à 5.

                  Dans le second cas, tes données vont être éparpillées en mémoire et donc tu vas te taper plein de défaut de cache. Dans le premier cas, le processeur va reconnaître un pattern d'accès à la mémoire et va précharger les positions futures, ce qui va considérablement améliorer ton temps de traitement.

                  Ça me semble péremptoire. Ce sera vrai dans certain cas, mais dans d’autre, tu risques les recopies d’objets, tu dois faire attention à ne pas modifier ton tableau (cas 1) dans un fil d’exécution léger pendant qu’un autre fil dispose d’une référence sur l’objet N. Car l’implémentation peut déplacer les objets en mémoire (std::vector)…

                  En fonction de comment on utilise les données, l’un ou l’autre sera plus adapté. Àmha.

                • [^] # Re: Les systèmes à entités

                  Posté par  . Évalué à 2.

                  Il existe des gestionnaires de mémoires qui permettent d'éviter ces bidouilles :
                  http://www.boost.org/doc/libs/1_59_0/libs/pool/doc/html/index.html

    • [^] # Re: Les systèmes à entités

      Posté par  (Mastodon) . Évalué à 2.

      Tu serais surpris de savoir les jeux AAA qui sont fait avec un système à entités.

      Non, je sais que c'est très répandu ;) Mais je sais aussi qu'il y a beaucoup de variantes et que beaucoup croient faire des systèmes à entités alors qu'ils ne font que du data-driven (ce qui n'est pas un mal hein).

      • [^] # Re: Les systèmes à entités

        Posté par  . Évalué à 1.

        Hm, rappelez-moi la différence entre "data-driven" et "système à entité" ?

        • [^] # Re: Les systèmes à entités

          Posté par  . Évalué à 3.

          Je suis pas sûr qu'on ait les même définitions, mais pour moi, un système à entité est le fait de déterminer un objet de base (l'entité) et d'y plugger des fonctionnalités (composants). Et le fait d'être data-driven est le fait que les règles ne soient pas hardcodées; elles sont exposées dans des data éditables par des non-développeurs qui permet de contrôler le jeu.

          Par exemple, l'entité est juste un objet-identifiant. On y ajoute quelques composants: une position et une jauge de vie, et on obtient un objet-joueur. Tu rajoutes à ça une IA et tu obtiens un objet-NPC (c'est volontairement simple, évidemment dans un vrai jeu il y aurait bien plus de composants par entité).

          D'un autre côté, tu as des data qui sont liés à ses composants, permettant de déterminer différentes spécificités comme les points de vie par exemple. L'avantage c'est que la gestion de la vie c'est le composant qui s'en charge, mais la quantité de vie, c'est les data qui déterminent ça. On peut ainsi mettre différentes data sur le même pattern "entité-composants" et tu obtiens différents NPCs.

          Au final, ça permet de bien séparer les systèmes et les data, le contenant et le contenu.

        • [^] # Re: Les systèmes à entités

          Posté par  . Évalué à 4.

          Je dirais que les systèmes à entités sont une façon de faire du data-driven. Dans un contexte totalement différent tu peux faire du data-driven pour générer des vues : au lieu d'avoir des templates dans les quels tu injecte tes données, ton code va récupérer les données et générer la vue dynamiquement. C'est du data-driven et ça n'a pas le moindre rapport avec l'ES.

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

        • [^] # Re: Les systèmes à entités

          Posté par  (Mastodon) . Évalué à 3.

          Je crois qu'il y a eu une incompréhension de ma part. Quand ça parlait de «data-driven», j'ai cru que ça parlait de data-oriented design. Les systèmes à entités sont data-oriented mais ça n'a rien à voir avec data-driven si ça veut dire qu'on part de données dans des fichiers.

  • # Interessant le problème du réusinage/refactoring

    Posté par  . Évalué à 3.

    Jonathan Blow un créateur de jeux vidéos est en train d'écrire un nouveau langage qui, entre autre, essaye de simplifier le réusinage.
    Un exemple si tu veux passer d'un 'array of struct' (AoS) classique à un struct of array (SoA) et bien il suffit d'ajouter une annotation sur UNE déclaration et il n'y a pas besoin de modifier le reste du code.

    Malheursement il communique sur le sujet principalement par vidéos https://www.youtube.com/channel/UCCuoqzrsHlwv1YyPKLuMDUQ

  • # sfml moi aussi

    Posté par  . Évalué à 3. Dernière modification le 06 septembre 2015 à 15:53.

    moi aussi je développe mon jeu avec sfml c++11. Merci de partager sur la question des systèmes à entités. Personnellement j'ai fais à mon idée sans trop regarder les méthodes existante. J'ai lu quelque tutos sur les systèmes à entités. Mais je suis quand même partis sur de l'objet.
    Donc, je suis content d'avoir un avis un peu approfondis sur la question.
    J'ai séparé les données/propriétés du traitement des données. J'ai donc des objets comme healSkill (compétences de soin avec ses propriétés) et interaction pour utiliser la compétence pour soigner.
    Si ça t’intéresse j'ai un peu détaillé comment j'ai organisé mon code, notamment les événements. Et aussi comment j'ai évité de passer par l'évaluation dynamique du type d'objet (un peu barbare comme méthode mais ça marche).
    http://en.sfml-dev.org/forums/index.php?topic=17721.0 (voir le dernier post)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.