Donc, vous avez votre jeu génial dans les travaux, il a toutes sortes de physique complexe, une IA épique ennemie ou ce que vous avez. Mais il se sent sans vie. Vous voulez du OOMPH, vous voulez de l'animation!
Si vous recherchez comment animer, la première réponse que vous rencontrerez sera probablement une méthode utilisant des feuilles de sprites et le blitting. En fait, presque tous les tutoriels sur le Web ne parlent de rien mais blitting, comme s'il n'y avait pas d'autre moyen d'animer. Mais selon mon expérience, il existe un meilleur moyen d'animer vos orcs et gobelins!
Cette méthode pourrait s'appeler animer avec des assets - ou plus techniquement, interpolation avec des fiches d’actifs - par opposition à l’utilisation de lutin-feuilles. Avant de préciser ce que cela signifie, considérons une question importante:
Voici quelques raisons pour Pourquoi vous ne voudriez pas utiliser le blitting dans certains cas.
Qu'il s'agisse de RAM ou d'espace disque, les images-objets peuvent facilement encrasser des objets. Surtout si vous essayez de créer des graphiques HD. D'énormes feuilles de sprites devront peut-être être divisées en plusieurs PNG, occupant une précieuse RAM et augmentant la taille de votre jeu si vous ne faites pas attention..
Que se passe-t-il lorsque vous souhaitez accélérer une animation? Vous pouvez sauter des images, mais qu'en est-il ralentir? L'animation aurait l'air agitée et laide. Même si vous ne voulez supporter que 60 ips, que se passera-t-il si un ordinateur peut exécuter le jeu plus rapidement? Vous pourriez avoir des animations incroyablement lisses à des taux de trame plus élevés sans aucun travail supplémentaire, et il serait également intéressant si vous choisissez de modifier le taux de trame du jeu à tout moment..
Et si vous vouliez que quelque chose se passe lorsque les bras du joueur atteignent un endroit? Ou de lui demander quelque chose? Vous devez marquer manuellement son bras tout au long de l'animation, ce qui peut prendre beaucoup de temps, car vous ne pouvez pas obtenir de données sur l'endroit où ses membres se trouvent sur une feuille de sprite..
Que se passe-t-il lorsque le joueur court et saute soudainement? Il coupe immédiatement l’animation de saut. Cela semble instable, et cela se produirait chaque fois que l'animation passera dans un nouvel état. Vous devrez effectuer une transition pour chaque paire d'animations que vous avez, ce qui non seulement prend énormément de temps, mais a également pour effet d'augmenter votre utilisation de la RAM, comme indiqué précédemment..
L'utilisation de feuilles de contenu permet non seulement aux animations d'être dynamiques et de s'adapter à tout FPS, ainsi que de passer en douceur entre deux états, également prend une infime quantité d'espace disque et de RAM par rapport au blitting!
Ce n'est même pas très nouveau. Certains jeux populaires l'utilisent, comme le très populaire Closure. Sa seule limite est qu'il ne peut pas faire d'animation image par image (FBF), car il repose sur l'interpolation. Si vous avez des explosions complexes, vous devrez utiliser des feuilles de sprite..
Mais dans de nombreux cas, vous constaterez que vous n'en aurez pas besoin, et cela vaut amplement la peine d’avoir un système comme celui-ci pour votre jeu, car certains jeux pourraient s’en remettre totalement à cela, ce qui réduirait considérablement les frais généraux. . C'est aussi vraiment cool parce que c'est similaire à la façon dont vous pourriez animer un jeu en 3D!
Donc, pour résumer:
Ceci est un personnage et sa fiche.
Comme son nom l'indique, une fiche d'actif est une PNG avec tous les membres / atouts du personnage ou de l'objet séparés.
Et voici les données d'animation en JSON (bien sûr, vous pouvez utiliser le format avec lequel vous préférez travailler):
// cet extrait montre les trois premières images de l'animation "Body" "-name": "Body", "Frame": ["-x": "0.65", "-y": "- 64.45", " -rotation ":" 0.000 ", " -x ":" 2.45 "," -y ":" - 64.45 "," -rotation ":" 0.279 "," -x ":" 3.30 "," - y ":" - 64.05 "," -rotation ":" 0.707 "
Maintenant, en combinant ces deux dans un moteur génial, vous obtenez:
Et contrairement à une animation blitted, cela pourrait accélérer ou accélérer la transition, ou se faire très facilement. Voilà ce que nous allons faire.
La première étape consiste à préparer votre fiche de patrimoine. Vous pouvez le faire de différentes manières. Le but est de se retrouver avec une feuille contenant les actifs et un fichier de données contenant les positions des actifs dans la feuille. C'est exactement la même méthode que pour créer un spritesheet, sauf que vous ajoutez des actifs séparés à la place des sprites.
Exportez les membres et les morceaux de votre lecteur sous forme de fichiers PNG individuels, puis utilisez un programme tel que Texture Packer pour les regrouper dans une feuille. Il existe d'autres programmes, mais je préfère personnellement Texture Packer en raison de sa polyvalence et de ses nombreuses fonctionnalités..
Pointe: Quel que soit le logiciel que vous utilisez pour créer vos feuilles, assurez-vous qu'il y a au moins 2 pixels de remplissage entre chaque actif et 1 extrusion. Cela empêchera certains problèmes désagréables à l'avenir.C’est sans doute l’étape la plus importante, car ce sont les données que vous utiliserez pour créer toutes les animations au moment de l’exécution. C'est aussi important parce que c'est indépendant de la plateforme. Vous pouvez utiliser les mêmes données d'animation sur une PS3 que sur un iPhone.
Les données dont vous avez besoin sont la position x, la position y, la valeur de rotation et d'autres propriétés similaires de chaque actif pour chaque image de votre animation..
Si vous utilisez Adobe Flash pour animer, vous pouvez facilement exporter vos données d'animation. En théorie, tout ce que vous avez à faire est de parcourir les enfants du MovieClip et de parcourir les images tout en récupérant les données..
Cependant, cela peut être une nuisance. Heureusement, certains outils le font déjà. Par exemple, Grapefrukt est un outil génial doté de nombreuses fonctionnalités, notamment l'exportation de feuilles de sprites ainsi que de données d'animation au format XML..
Remarque: Vous devez vous assurer que les noms de vos actifs dans les données correspondent à ceux de la fiche d'actif afin qu'ils puissent être facilement liés.Si vous essayez de le modifier ou si vous souhaitez simplement utiliser la simple fonctionnalité d'exportation d'animation, vous pouvez choisir d'utiliser ma propre classe d'exportateur d'animation, qui exporte automatiquement les données d'animation dans un fichier JSON situé dans le même répertoire. Vous pouvez le télécharger ici, avec un exemple de fiche d'inventaire et un exemple d'animation.
Si vous utilisez un autre logiciel d'animation (ou le vôtre), il ne devrait pas être trop difficile de trouver ou d'écrire un plug-in qui exporte les coordonnées et les données des ressources à chaque image..
Voici une liste de tous les attributs générés par les exportateurs Flash pour chaque actif:
X
et y
rotation
(en degrés ou en radians)scaleX
et échelleY
(combien d'actif est mis à l'échelle sur chaque axe)alpha
(transparence)colorMatrix
(vous permet d'exporter des données telles que la luminosité, la teinte et le contraste)Il n'y a pas de limite à la quantité de données que vous pouvez sortir. Par exemple, j'ai ajouté un extra profondeur
domaine de mon exportateur qui me dit la profondeur de chaque actif. Ainsi, si l'animateur organise les éléments dans un certain ordre ou modifie les calques, ils sont automatiquement mis à jour dans le moteur..
Comme vous pouvez le constater, vous pouvez créer de nombreux types d’animation et de fonctionnalités avec les bonnes données..
Alors maintenant, vous avez préparé votre fiche, son fichier de données et votre animation JSON. Vient ensuite la partie difficile: écrire le système d’animation qui comprend nos données et convertit les ressources distinctes et les données brutes en une belle animation..
La première étape consiste à charger les données d'animation. Cela devrait être facile car la plupart des langues ont un analyseur JSON ou XML.
Ensuite, vous séparez chaque élément de la feuille (ou vous ne rendez le rectangle qu’avec votre élément) et vous les stockez dans un tableau..
Alors maintenant, nos objets de jeu ont deux tableaux: un assetArray
qui a les actifs réels, et un animationArray
qui a les données d'animation.
animationArray
et donnez les noms des actifs. C’est pour que vous puissiez facilement accéder aux données correctes du tableau d’animation - donc si j’imprime la valeur de object.assetArray [5] .name
, Je voudrais obtenir "jambe", par exemple. Alors si je vais et accède object.animationArray ["leg"]
, Je devrais obtenir les données d'animation pour la jambe du personnage. Voyons maintenant du code!
/// Dans la fonction de mise à jour de l'objet var animationArray: Array = object.animationArray; var assetArray: Array = object.assetArray; // on parcourt tous les actifs pour (var i: int = 0; i < assetArray.length; i++) assetArray[i].x = object.x; assetArray[i].y = object.y; assetArray[i].angle = object.angle;
Jusqu'à présent, nous parcourons tous les actifs pour définir leur X
, y
et rotation
à celle de l'objet mère. Ceci est important pour que vos objets puissent bouger sans ruiner l'animation, de sorte que les coordonnées de l'animation soient relatives à ce point..
/// Dans la fonction de mise à jour de l'objet var animationArray: Array = object.animationArray; var assetArray: Array = object.assetArray; // on parcourt tous les actifs pour (var i: int = 0; iIci nous avons ajouté la ligne
+ animationArray [assetArray [i] .name] [currentFrame] .x
, oùcadre actuel
est un entier représentant le cadre actuel dans lequel vous vous trouvez.Maintenant, tous les actifs seraient à leurs positions de première trame, donc une fois que vous incrémentez
cadre actuel
, ils seraient aux positions de l'image 2, et ainsi de suite.Félicitations, vous avez créé l'animation! Cela semble identique à ce que vous aviez fait avec une feuille de correspondance, sauf que cela ne vous coûte que quelques kilo-octets au lieu de mégaoctets..
Ceci est juste un exemple très simple. Normalement, vous voudriez avoir des animations séparées, telles qu'une animation "en cours" avec 30 images et une animation "avec sauts" avec 12 images. Pour ce faire, il vous suffirait d'ajouter un autre calque à votre hiérarchie de tableaux d'animation afin qu'il ressemble à ceci:
Étape 4: Interpolation
Nous ne devons pas nous arrêter là. Nous voulons essayer de rendre nos animations aussi fluides et dynamiques que promis.
Normalement, ce serait quelque chose d'assez difficile - nous devrions stocker l'état complet de la trame précédente afin d'interpoler au courant. Mais heureusement, notre système stocke déjà ces informations!
Vous toujours savoir où se trouvait l'image précédente et où sera l'image suivante. L'interpolation entre les images est aussi simple que cela:
var data: Array = animationArray [assetArray [i] .name] var X: Nombre = data [currentFrame] .x + (data [currentFrame + 1] .x - data [currentFrame] .x) * _timeFactor; assetArray [i] .x = object.x + XIci, nous obtenons la différence entre l'image suivante et l'image actuelle, multipliée par un
timeFactor
qui est le temps entre les deux cadres.Cela signifie qu'au lieu que votre animation ressemble à ceci au ralenti:
… Cela ressemblerait à ceci:
Prendre cette, blitting!
Étape de bonus: matrice de couleurs
Si vous utilisez Flash pour animer, votre matrice de couleurs peut ressembler à ceci:
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0
Ce n'est pas très lisible maintenant?
Flash y stocke toutes les données de luminosité, de contraste et de saturation. Heureusement, ils ont posté leur formule afin que nous n'ayons pas à essayer de faire de l'ingénierie inverse,.
La formule ci-dessous vous explique comment calculer les valeurs RGBA finales du pixel en fonction de la couleur source et de la matrice de couleur (
une
est le tableau matriciel couleur):redResult = (a [0] * srcR) + (a [1] * srcG) + (a [2] * srcB) + (a [3] * srcA) + a [4] greenResult = (a [5] * srcR) + (a [6] * srcG) + (a [7] * srcB) + (a [8] * srcA) + a [9] blueResult = (a [10] * srcR) + (a [11] * srcG) + (a [12] * srcB) + (a [13] * srcA) + a [14] alphaResult = (a [15] * srcR) + (a [16] * srcG) + (a [17 ] * srcB) + (a [18] * srcA) + a [19]Plus d'informations sur Flash
ColorMatrix
classe peut être trouvé ici.
Conclusion et étude de cas
Bien que cela puisse sembler un peu effrayant au début, cette méthode est vraiment facile à utiliser lorsque tout est configuré, et la mise en place d'une base appropriée vaut du temps et des efforts.
Cela ne veut pas dire que cette méthode est idéale pour chaque situation. Comme mentionné précédemment, si votre jeu repose sur une animation image par image ou sur des choses impossibles à effectuer avec une interpolation, cela ne fonctionnera pas vraiment. (Bien que vous puissiez toujours mélanger et assortir les méthodes.)
Cela dit, examinons un dernier exemple concret d'utilisation de cette méthode..
C'est une porte:
Il s'ouvre et se ferme et vous voulez que le joueur ne puisse pas le traverser..
C'est simple, non? Vous voudriez simplement qu'une boîte de collision se déplace verticalement, en fonction du nombre d'images dans l'animation. Le problème, cependant, est que cette animation n'est pas linéaire: il y a un léger relâchement. En faisant correspondre la position verticale de la zone de collision à l'image actuelle de l'animation, la zone de collision ne serait pas synchronisée avec l'animation, ce qui donnerait l'impression que les objets passent soit à travers la porte, soit sur des nuages..
Heureusement, vous avez le
X
,y
,la taille
etlargeur
de la porte animée, vous permettant de synchroniser parfaitement votre collision!
Blitting vs feuilles d'actif