• # C’est abstrait mais c’est intéressant

    Posté par . En réponse à la dépêche Je crée mon jeu vidéo E01 : les systèmes à entités. Évalué à 5.

    Ça tombe hyper bien, ça fait un moment que je me documente sur la chose, et en fait je trouve ça très bien sur le papier mais très abstrait (et quand je regarde le code ça m’aide pas tant que ça), surtout qu’il y a plusieurs façon de faire...

    Le plus simple c’est sans doute de prendre un exemple proche de moi. Je veux faire un jeu, grosso modo c’est le principe d’un Sokoban mais j’ai des caisses en bois que je peux pousser dans l’eau pour faire un pont, des interrupteurs qui ouvrent des portes quand on marche dessus. Du coup, j’ai la tuile (sol, eau ou mur en gros) qui est dessiné en premier, ensuite les mécanismes (interrupteurs, portes, pics qui sortent du sol à intervalle régulières...) et enfin les «objets» (je ne sais pas comment nommer cette catégorie: personnages, monstres, caisses...).

    Ces 3 catégories correspondraient à un attribut «level», et c’est très pratique parce que je ne peux pas avoir plusieurs éléments de même «level» qui se chevauchent, ni plusieurs éléments «bloquants» sur la même case (exemples: j’ai un mur donc je ne peux rien mettre d’autre, ou les pics sortent du sol avec la caisse dessus du coup conflit, les pics cassent l’objet dessus).

    Au début je me disais que seul les objets pouvaient bouger mais maintenant, je veux avoir des mécanismes qui peuvent bouger par exemple. Du coup je me dis qu’un ECS ça pourrait être pratique: un composant «mécanisme», un composant «mouvement», un composant «objet» pour savoir si c’est un objet qui flotte ou non et savoir et une autre propriété du style, etc. Et même avec des spécialisations, genre certains mécanismes ne sont pas à mettre à jour automatiquement ne sont pas à mettre à jour automatiquement (portes et interrupteurs sont déclenchés par l’action du joueur mais les pics qui sortent puis rentrent du sol sont automatiques).

    Le truc c’est que par exemple une IA (très basique) pour les monstres, c’est une méthode. Or j’avais compris que les composants ne stockaient que les données! Alors où se trouver la logique du jeu?

    Bref, en gros je pensais à un tableau en 3 dimensions pour stocker les tuiles, les mécanismes et les objets. Je mets à jour tout ce beau monde: automatiques + joueur + tout ce qui pourrait avoir été affecté par les précédents → ça évite que pour chaque case d’eau je vérifie si une caisse est au-dessus à chaque tour par exemple (je pense même à ne presque rien mettre en mise à jour auto et n’inscrire les caisses en automatiques que quand il y a déplacement par exemple).

    Ensuite je regarde s’il n’y a pas de conflits, sinon certains objets seront détruits (enfin marqués à destruction, on résout tous les conflits et on détruits tout ceux qui sont marqués à destruction), et enfin je déplace ceux qui ont changé de case (ceux qui ont le centre de gravité qui à changé de centaine quoi).

    Du coup grâce à cette technique je peux les dessiner dans le bon ordre, de sorte que les sprites qui dépassent sur la case du dessus ne soit pas dessinés en-dessous!


    • Un entité conteneur de composant vs pas de conteneur et id pour connaitre les entités, quels sont les avantages et les inconvénients? J’aime bien la deuxième méthode mais ça risque de compliquer mon tableau à 3 dimensions! De toute manière, il va falloir faire attention que si un composant «meurt», tous les autres composants de l’entité doivent suivre. C’est pas très compliqué sauf si on fait des listes par composants (est-ce que la vue aurait chaque composant «vue» de chaque entité? Du coup la logique et la partie graphique du jeu auraient une méthode où on passe l’id de l’entité et qui détruit ses composants).

    • Si je modifie un composant j’aimerais bien pouvoir accéder à l’entité pour lui dire de mourir proprement, avec des composants à id on peut faire ça proprement. Ou alors ma super grille ne contient que des int qui sont des id!

    • Pour les composants, j’ai l’impression qu’ils ont forcément une interface commune (au moins une méthode update), mais pas plus? N’est-il pas plus logique d’avoir un pointeur pour chaque type de composant qui est à null s’il n’en a pas? Notamment parce que je ne vois pas l’intérêt pour mon jeu de rajouter des composants à la volée. Du coup il va falloir que je fasse de l’héritage sur les composants, j’ai l’impression à lire çà et là des trucs sur les ECS que c’était «mal»! À moins que je fasse le composant directement à partir de l’interface/classe virtuelle/classe abstraite sans utiliser d’autre forme d’héritage?

    • Est-ce que je pourrait avoir un exemple très basique d’implantation de mon concept (en pseudo-code ou C++/Java/Python/...)? Parce quand c’est les concepts des autres j’ai du mal à suivre... Là je pense (j’espère) que ça m’aiderait carrément.

    Écrit en Bépo selon l’orthographe de 1990