Bonjour ! Je m'adresse ici notamment à @rewind , mais évidement tout le monde est invité à m'éclairer =) .
Je m'intéresse en ce moment aux systèmes à entités, et je me heurte à plusieurs problèmes que je ne me souviens pas avoir vu évoqués dans ces articles de ce journal de bord sur Akagoria.
Il est probable que j'ai mal compris certains aspects d'un système à entités =P
Je rajoute que je conçois le système à entités moi-même, pour pouvoir mieux en comprendre les mécanismes.
En premier lieu, comment gérer la surcouche "matérielle" entre les composants de son propre système à entités et une bibliothèque externe ?
Dans mon cas, j'utilise Ogre3D, moteur de rendu 3D.
Voici un exemple :
Un SceneNode (un nœud dans l'espace) et une Entity (comportant notamment texture et mesh) sont produits à partir d'un SceneManager, d'une part.
D'autre part, on aura besoin d'effectuer une opération du type "sceneNode.attach(entity)" pour reproduire correctement les mouvements du nœud sur l'entité graphique.
On doit pouvoir également attacher des nœuds entre eux.
La relation de dépendance entre la composante spatiale et la composante graphique est nette, tout comme la dépendance entre ces deux-là est le SceneManager, et enfin celle possible entre deux nœuds.
Cependant, ça parait un peu étrange de fusionner ainsi deux composantes assez différentes dans le principe. Par exemple on aura à modifier l'animation actuelle d'une entité graphique, sans avoir à s'occuper de son nœud spatial.
On peut aussi imaginer le cas d'un objet intangible mais situé dans l'espace (une zone, par exemple) qui n'a aucune utilité d'informations graphiques ou physiques.
Est-ce que je prends le problème de travers et devrais fusionner ces deux objets ?
J'ai l'impression que rapidement je finirais par obtenir un énorme composant "OgreComponent" avec tout dedans. Après tout pourquoi pas...
Mais même ainsi je n'échappe pas au problème de l'antériorité, ou dépendance logique en d'autres mots. Comme suit :
Une boite de collision produite par la bibliothèque Bullet (moteur physique) n'a a priori pas de sens si elle est un composant d'une entité qui ne comporte pas de composant avec des coordonnées spatiales, donc qui n'existe pas de façon tangible. Ce serait comme essayer d'appliquer la gravitation à une quête.
Peut-on ignorer ce cas de figure, ou est-il raisonnable de penser qu'un composant doit être accompagner d'informations d'antériorité qui doivent être satisfaits pour permettre son existence ? Est-ce hors-sujet pour un système à entités ?
On a pourtant bien ce genre d'informations dans les systèmes, dans le prototype : la liste des composants qu'une entité doit avoir pour être traitable par ce système. Et donc également dans les composants et les entités, puisque ceux-ci sont donc typés (dans mon cas c'est un typage à l’exécution, manuel à base de std::string).
Enfin, dernier thème, toujours au sujet des composants :
J'illustrerai ce chapitre avec ma preuve de fonctionnement que voici :
J'ai 400 petits cubes sur un même plan horizontal, en un quadrillage carré. Sont appliqués deux traitements : le rendu graphique, et une oscillation verticale décrivant une onde sinusoïdale.
(Pratique pour tester la solidité du programme en augmentant fortement la quantité de cubes, par exemple.)
On sait que le traitement pour le sinus est dans un système des dizaines de fois par seconde.
Mais qui doit s'occuper de la "préparation" de ces cubes, c'est-à-dire notamment créer les objets Ogre à l'intérieur, puis placer correctement tous les cubes selon une scène pré-déterminée d'un fichier de sauvegarde ?
Qui doit s'occuper du nettoyage lorsque les composants seront déconstruits (fuite mémoire, notamment) ?
Si un composant n'est qu'une structure de donnée sans logique (dans la limite du C++), qui doit s'occuper de ce genre de traitements préparatoires et terminaux ?
Un système ? Mais qui l'appellera et quand ? A priori on ne peut pas insérer pareil système préparatoire dans le circuit de la boucle infinie de l'application.
Par extension, c'est tout le thème du "traitement ponctuel" qui est en jeu.
Mettons que deux objets qui réagissent l'un avec l'autre se rencontrent (de l'eau + du feu = de la vapeur).
Comment implémenter ce genre de traitement de façon efficace ?
Un système qui parcourt l'intégralité des objets du jeu pour effectuer un calcul de proximité, ça serait a priori très lent.
J'ai sans doute dû omettre un point important dans le thème de la communication entre éléments d'un système à entités, je suppose.
J'ai du mal à voir comment implémenter le concept de "chose à faire ponctuellement".
Comment dire à un système de modifier un composant *précis *de telle manière *une seule fois ?
Je sais que cela fait beaucoup pour un seul message, mais ces questions me tournent dans la tête depuis un moment déjà, cela devient quelque peu fatiguant =P
# Système à entités et interface avec des librairies existantes
Posté par Pazns . En réponse à la dépêche Je crée mon jeu vidéo E13 : un an, premier bilan. Évalué à 1.
Bonjour ! Je m'adresse ici notamment à @rewind , mais évidement tout le monde est invité à m'éclairer =) .
Je m'intéresse en ce moment aux systèmes à entités, et je me heurte à plusieurs problèmes que je ne me souviens pas avoir vu évoqués dans ces articles de ce journal de bord sur Akagoria.
Il est probable que j'ai mal compris certains aspects d'un système à entités =P
Je rajoute que je conçois le système à entités moi-même, pour pouvoir mieux en comprendre les mécanismes.
En premier lieu, comment gérer la surcouche "matérielle" entre les composants de son propre système à entités et une bibliothèque externe ?
Dans mon cas, j'utilise Ogre3D, moteur de rendu 3D.
Voici un exemple :
Un SceneNode (un nœud dans l'espace) et une Entity (comportant notamment texture et mesh) sont produits à partir d'un SceneManager, d'une part.
D'autre part, on aura besoin d'effectuer une opération du type "sceneNode.attach(entity)" pour reproduire correctement les mouvements du nœud sur l'entité graphique.
On doit pouvoir également attacher des nœuds entre eux.
La relation de dépendance entre la composante spatiale et la composante graphique est nette, tout comme la dépendance entre ces deux-là est le SceneManager, et enfin celle possible entre deux nœuds.
Cependant, ça parait un peu étrange de fusionner ainsi deux composantes assez différentes dans le principe. Par exemple on aura à modifier l'animation actuelle d'une entité graphique, sans avoir à s'occuper de son nœud spatial.
On peut aussi imaginer le cas d'un objet intangible mais situé dans l'espace (une zone, par exemple) qui n'a aucune utilité d'informations graphiques ou physiques.
Est-ce que je prends le problème de travers et devrais fusionner ces deux objets ?
J'ai l'impression que rapidement je finirais par obtenir un énorme composant "OgreComponent" avec tout dedans. Après tout pourquoi pas...
Mais même ainsi je n'échappe pas au problème de l'antériorité, ou dépendance logique en d'autres mots. Comme suit :
Une boite de collision produite par la bibliothèque Bullet (moteur physique) n'a a priori pas de sens si elle est un composant d'une entité qui ne comporte pas de composant avec des coordonnées spatiales, donc qui n'existe pas de façon tangible. Ce serait comme essayer d'appliquer la gravitation à une quête.
Peut-on ignorer ce cas de figure, ou est-il raisonnable de penser qu'un composant doit être accompagner d'informations d'antériorité qui doivent être satisfaits pour permettre son existence ? Est-ce hors-sujet pour un système à entités ?
On a pourtant bien ce genre d'informations dans les systèmes, dans le prototype : la liste des composants qu'une entité doit avoir pour être traitable par ce système. Et donc également dans les composants et les entités, puisque ceux-ci sont donc typés (dans mon cas c'est un typage à l’exécution, manuel à base de std::string).
Enfin, dernier thème, toujours au sujet des composants :
J'illustrerai ce chapitre avec ma preuve de fonctionnement que voici :
J'ai 400 petits cubes sur un même plan horizontal, en un quadrillage carré. Sont appliqués deux traitements : le rendu graphique, et une oscillation verticale décrivant une onde sinusoïdale.
(Pratique pour tester la solidité du programme en augmentant fortement la quantité de cubes, par exemple.)
On sait que le traitement pour le sinus est dans un système des dizaines de fois par seconde.
Mais qui doit s'occuper de la "préparation" de ces cubes, c'est-à-dire notamment créer les objets Ogre à l'intérieur, puis placer correctement tous les cubes selon une scène pré-déterminée d'un fichier de sauvegarde ?
Qui doit s'occuper du nettoyage lorsque les composants seront déconstruits (fuite mémoire, notamment) ?
Si un composant n'est qu'une structure de donnée sans logique (dans la limite du C++), qui doit s'occuper de ce genre de traitements préparatoires et terminaux ?
Un système ? Mais qui l'appellera et quand ? A priori on ne peut pas insérer pareil système préparatoire dans le circuit de la boucle infinie de l'application.
Par extension, c'est tout le thème du "traitement ponctuel" qui est en jeu.
Mettons que deux objets qui réagissent l'un avec l'autre se rencontrent (de l'eau + du feu = de la vapeur).
Comment implémenter ce genre de traitement de façon efficace ?
Un système qui parcourt l'intégralité des objets du jeu pour effectuer un calcul de proximité, ça serait a priori très lent.
J'ai sans doute dû omettre un point important dans le thème de la communication entre éléments d'un système à entités, je suppose.
J'ai du mal à voir comment implémenter le concept de "chose à faire ponctuellement".
Comment dire à un système de modifier un composant *précis *de telle manière *une seule fois ?
Je sais que cela fait beaucoup pour un seul message, mais ces questions me tournent dans la tête depuis un moment déjà, cela devient quelque peu fatiguant =P
Cordialement.