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 ylsul . En réponse à la dépêche Je crée mon jeu vidéo E15 : J'arrête.... É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.