EDIT: Pour clarifier quelle est exactement ma question: est-ce un bon moyen de gérer les animations / l'état d'animation dans un moteur de jeu avec un œil sur la création / gestion de contenu? Quels sont les défauts de le faire de cette façon et quelle serait une autre façon de le faire? - Bien que ma réponse ait été partiellement répondue dans les commentaires, car cela semble être la voie à suivre.
J'essaie de gérer des animations dans un projet de passe-temps de moteur de jeu 2D , sans les coder en dur. Les états d'animation codés en dur me semblent être un phénomène courant mais très étrange.
Un peu d'histoire: je travaille avec un système d'entités où les composants sont des sacs de données et les sous-systèmes agissent sur eux. J'ai choisi d'utiliser un système d'interrogation pour mettre à jour les états d'animation.
Avec les états d'animation, je veux dire: "walking_left", "running_left", "walking_right", "shooting", ...
Mon idée pour gérer les animations était de le concevoir comme un modèle piloté par les données . Les données pourraient être stockées dans un fichier xml, un rdbms, ... Et pourraient être chargées au début d'un jeu / niveau / ... De cette façon, vous pouvez facilement éditer des animations et des transitions sans avoir à aller changer le code partout dans votre Jeu.
À titre d'exemple, j'ai fait un brouillon xml des définitions de données que j'avais en tête.
Une donnée très importante serait simplement la description d'une animation . Une animation aurait un identifiant unique (un nom descriptif). Il contiendrait un identifiant de référence à une image (la feuille de sprites qu'il utilise, car différentes animations peuvent utiliser différentes feuilles de sprites). Les images par seconde pour exécuter l'animation. Le "replay" définit ici si une animation doit être exécutée une fois ou à l'infini. Ensuite, j'ai défini une liste de rectangles comme cadres.
<animation id='WIZARD_WALK_LEFT'>
<image id='WIZARD_WALKING' />
<fps>50</fps>
<replay>true</replay>
<frames>
<rectangle>
<x>0</x>
<y>0</y>
<width>45</width>
<height>45</height>
</rectangle>
<rectangle>
<x>45</x>
<y>0</y>
<width>45</width>
<height>45</height>
</rectangle>
</frames>
</animation>
Les données d'animation seraient chargées et conservées dans un pool de ressources d'animation et référencées par les entités de jeu qui les utilisent. Il serait traité comme une ressource comme une image, un son, une texture, ...
La deuxième donnée à définir serait une machine à états pour gérer les états d'animation et les transitions. Cela définit chaque état dans lequel une entité de jeu peut se trouver, ce qui indique qu'elle peut effectuer une transition et ce qui déclenche ce changement d'état.
Cette machine d'état diffère d'une entité à l'autre. Parce qu'un oiseau pourrait avoir des états "marcher" et "voler" alors qu'un humain n'aurait que l'état "marcher". Cependant, il pourrait être partagé par différentes entités car plusieurs humains auront probablement les mêmes états (surtout lorsque vous définissez des PNJ communs comme des monstres, etc.). De plus, un orc peut avoir les mêmes états qu'un humain. Juste pour démontrer que cette définition d'état peut être partagée mais uniquement par un groupe sélectionné d'entités de jeu .
<state id='IDLE'>
<event trigger='LEFT_DOWN' goto='MOVING_LEFT' />
<event trigger='RIGHT_DOWN' goto='MOVING_RIGHT' />
</state>
<state id='MOVING_LEFT'>
<event trigger='LEFT_UP' goto='IDLE' />
<event trigger='RIGHT_DOWN' goto='MOVING_RIGHT' />
</state>
<state id='MOVING_RIGHT'>
<event trigger='RIGHT_UP' goto='IDLE' />
<event trigger='LEFT_DOWN' goto='MOVING_LEFT' />
</state>
Ces états peuvent être gérés par un système de sondage . À chaque partie, il capture l'état actuel d'une entité de jeu et vérifie tous les déclencheurs. Si une condition est remplie, elle change l'état de l'entité en l'état "goto".
La dernière partie avec laquelle je me débattais était de savoir comment lier des données d'animation et des états d'animation à une entité . L'approche la plus logique m'a semblé ajouter un pointeur sur les données de la machine d'état qu'une entité utilise et définir pour chaque état de cette machine quelle animation elle utilise.
Voici un exemple xml de la façon dont je définirais le comportement d'animation et la représentation graphique de certaines entités communes dans un jeu, en abordant l'état d'animation et l'identifiant des données d'animation. Notez que "wizard" et "orc" ont les mêmes états d'animation mais une animation différente. En outre, une animation différente peut signifier une feuille de sprite différente, ou même une séquence d'animations différente (une animation peut être plus ou moins longue).
<entity name="wizard">
<state id="IDLE" animation="WIZARD_IDLE" />
<state id="MOVING_LEFT" animation="WIZARD_WALK_LEFT" />
</entity>
<entity name="orc">
<state id="IDLE" animation="ORC_IDLE" />
<state id="MOVING_LEFT" animation="ORC_WALK_LEFT" />
</entity>
Lorsque l'entité est en cours de création, elle ajouterait une liste d'états avec des données de machine d'état et une référence de données d'animation.
À l'avenir, j'utiliserais le système d'entités pour créer des entités entières en définissant des composants dans un format xml similaire.
-
C'est ce que j'ai trouvé après quelques recherches. Cependant, j'ai eu du mal à m'en sortir, alors j'espérais avoir des retours. Y a-t-il quelque chose ici qui n'a pas de sens, ou existe-t-il une meilleure façon de gérer ces choses? J'ai saisi l'idée d'itérer à travers des cadres mais j'ai du mal à aller plus loin et c'est ma tentative de le faire.
Réponses:
Les clips d'animation sont mieux décrits dans les données anciennes, comme vous l'avez fait dans votre premier extrait de code XML. Vous pouvez le faire à la main ou l'exporter à partir d'un package artistique. Quoi qu'il en soit, vous souhaiterez probablement créer un pipeline qui le prendra à partir d'un format intermédiaire lisible par l'homme comme XML et le placera dans quelque chose de agréable et rapide à charger.
La prochaine étape consiste à rendre la chose. Si vous utilisez une sorte de graphique de scène, cela signifiera probablement la création d'un nœud d'animation pour cela. Vous devriez être en mesure de dire au nœud d'animation quelle animation il joue actuellement et où il se trouve actuellement dans la chronologie. Assurez-vous de conserver les informations de la zone de délimitation accessibles à ce niveau afin de pouvoir les insérer facilement dans votre système de tri.
Maintenant, vous allez vouloir associer une animation à une entité de jeu. J'ai tendance à utiliser un modèle basé sur les composants, donc pour moi, cela signifie et le composant AnimState. Il s'agit de votre couche intermédiaire entre le gameplay et le rendu. Il garde la trace de l'animation en cours de lecture d'une entité, des modes de lecture (boucle, une fois, ping-pong, etc.), du timing, etc. . AnimStates pour les entités actives sera mis à jour une fois par tick de simulation si elles jouent une animation.
Un composant animstate est probablement suffisant pour les éléments de jeu simples (accessoires d'arrière-plan de base et similaires), mais pour les entités plus complexes, vous allez vouloir utiliser une machine d'état pour le gérer. Cela s'exprime mieux dans un langage de script comme Lua ou Python. Un état peut avoir plusieurs blocs fonctionnels (onEnter, onExit, onUpdate, onEvent), ainsi qu'une chronologie qui spécifie certaines actions et déclencheurs qui devraient se produire à certains moments. Vous aurez probablement une sorte de classe de gestionnaire qui est responsable de la mise à jour de ces machines d'état, le cas échéant, ainsi que du déclenchement des rappels de la chronologie lorsqu'ils se produisent. Vous devriez essayer de garder ces choses aussi basées que possible sur les événements, car chaque OnUpdate que vous écrivez sera un coût linéaire avec le nombre d'entités. Vous voudrez également pouvoir spécifier des balises ("attaque", "inactif", 'ignoreinput', etc.) qui sont associés à la fois à des états entiers et à certaines régions temporelles d'états. Vous voudrez probablement aussi des gestionnaires d'événements de haut niveau qui s'appliquent à l'ensemble du graphique d'état, et pas seulement à un état particulier.
Les personnages «sensibles» auront probablement aussi une sorte d'IA. J'ai tendance à créer un composant «locomoteur» spécifique qui gère les déplacements. Il s'interface avec le stratège à l'aide d'un système de signaux et d'événements et interroge les étiquettes d'état, et peut être invité à «marcher jusqu'au point», ou «courir dans une certaine direction à une certaine vitesse». Les composants d'IA de niveau supérieur (comme un arbre de comportement ou autre) peuvent ensuite utiliser cette interface sans se soucier des détails.
la source
Le meilleur système d'animation basé sur les données que j'ai vu jusqu'à présent est l' arbre de fusion . Vraiment, c'est sacrément bon et il peut faire tout ce que vous demandez ici. Selon AIGameDev.com, c'est désormais la norme de facto dans l'industrie, et je pense qu'ils ont raison.
Malheureusement, je n'ai trouvé aucune bonne ressource avec une recherche rapide sur Google, mais vous pouvez essayer ceci ou cela pour obtenir un aperçu. Il y a aussi un article payant sur AIGameDev.com, je ne sais pas si cela vaut la peine d'obtenir un compte premium.
la source