Mon premier dessin animé

Publié le 7 octobre 2015 par Gee dans Dépêches Melba

Si vous suivez un peu l’actualité du libre et de Framasoft en particulier, vous avez sans doute entendu parlé des services lancés à l’occasion de l’an 2 de Dégooglisons Internet. Et outre la fameuse carte qui a été mise à jour (et animée par les soins de pyg avec les 2-3 petits sprites que je lui ai fournis), vous avez peut-être vu ce petit dessin animé de ma création :

À la base, cette vidéo était un simple GIF, mais j’en étais tellement content que j’ai poussé le concept en ajoutant une bande son et dans un format HD 🙂

Voici le GIF réalisé à la base :

Animation sur Framadrive (même chose que la vidéo ci-dessus, mais avec le texte à la place de la voix)

C’est court, l’animation n’est pas hyper-détaillée, mais j’en suis très fier ! Mine de rien, ça m’a quand même demandé 10 heures de boulot tout ça… Et je vous propose aujourd’hui de découvrir une sorte de making-of de ce GIF, parce que c’est loin d’être si simple que ça à faire.

Les outils

Bon. Quand Pouhiou m’a envoyé un mail pour me demander s’il y avait moyen de faire un petit GIF avec le scénario qu’il avait écrit (avec une date limite assez serrée), je me suis penché sur les logiciels d’animation libre. J’ai tout d’abord essayé Synfig qui semblait être le plus plébiscité. J’ai importé un personnage bricolé dans Inkscape, j’ai essayé de l’animer en fouillant un peu les menus et en regardant des tutos sur Internet. Sans succès (je dois pas être doué). J’ai laissé tombé quand le logiciel m’a planté entre les mains après avoir cliqué sur un bouton au hasard. J’ai vaguement jeté un œil du côté de Pencil2d, mais ça ne m’avait pas l’air beaucoup plus simple.

Qu’à cela ne tienne. Quand on est un peu pressé, mieux vaut s’en tenir à des logiciels qu’on connaît, même s’ils ne sont pas exactement faits pour la tâche qu’on a à accomplir. En l’occurrence, je me suis contenté d’utiliser :

  • Mon chouchou Inkscape pour faire les dessins, on ne change pas une équipe qui gagne (et il est aussi utilisable en ligne de commande, un très gros atout !)

  • ImageMagick pour générer le GIF

  • Un peu de Ruby pour automatiser un peu le processus

Je préviens d’avance que j’ai procédé volontairement de manière quick’n’dirty. Il est évident que tout ce que j’ai fait peut-être réalisé plus efficacement et proprement si on maîtrise un parser XML, les expressions régulières, etc. etc.

Animons… à l’ancienne !

Puisque je n’utilise aucun outil qui facilite l’animation (pour calculer automatiquement des images entre deux positions-clefs, par exemple) je fais au plus simple : décomposer le mouvement image par image et dessiner chaque image séparément. J’assume du coup le côté « saccadé » car je n’avais franchement pas le courage de faire du 25 images par seconde 🙂

Pour la marche du manchot, une boucle de 8 images :

Les huits images de marche du manchot

La marche de l’empereur… enfin, j’me comprends.

Pour animer l’uppercut, je me suis inspiré des sprites d’un certain jeu de baston assez connu…

Les 8 images de l'animation de l'uppercut

Shoooooryuken !

Et pour la partie jardinage, j’ai fait à l’instinct avec une boucle de deux images quand le manchot grattouille la terre.

Les images de l'animation de grattouillage

Il grattouille et il est content.

Reste le soldat qui est beaucoup moins animé mais possède son petit nombre d’images quand même. Je dessine le bouclier vide, sachant que le logo sur le bouclier va varier selon les projets.

Le soldat qui parle et se prend un pain

Engagez-vous… rengagez-vous qu’ils disaient !

Voilà ! Les autres éléments sont fixes (ou pratiquement) :

Nuage, éclairs et arbre

Je vous épargne l’animation du nuage de fumée à la fin…

Et enfin, un fond qui est raccordable à gauche et à droite pour pouvoir boucler facilement.

Le fond de la banquise

On assemble…

C’est là où ça devient carrément artisanal (et où, encore une fois, il y a moyen de faire plus simple – et moins gourmand en espace ! – si on sait scripter du SVG comme un chef). Je fais un calque (toujours sur Inkscape) par image, en dupliquant les éléments qui doivent l’être à chaque fois. Du coup le fichier source devient vite très gros…

On commence par 2 cycles de marche (soit 16 images). C’est le fond qui bouge. J’ai calculé qu’à la fin des deux cycles, mon personnage devait avoir parcouru à peu près les 2 tiers du décors qui fait 860 pixels de large. On doit donc parcourir (2/3)860=537,33 pixels en 16 frames. À chaque calque, je duplique le précédent et je sélectionne mon fond : Objet/Transformer/Déplacement horizontal* de -35,84 pixels.

Arrivé à la dernière des 16 frames, le nuage doit être dans sa position finale. Je le mets, puis je fais l’opération inverse (copie du nuage sur les calques précédents et mouvement de 35,84 pixels jusqu’à ce qu’il sorte du cadre). Avec toutes ces copies, le fichier fait déjà 11Mio ! Je décide de diviser l’animation en plusieurs fichiers pour ne pas exploser la mémoire de ce pauvre Inkscape…

Le deuxième fichier SVG commence aux éclairs et termine quand le soldat est éjecté de l’écran. Pas grand chose à dire, pas de formule mathématique ici, j’ai animé en essayant/regardant/corrigeant jusqu’à arriver à un enchaînement qui me semblait bien. Mine de rien, le deuxième fichier fait déjà 20Mio… On passe au troisième fichier !

On commence par recentrer la « caméra » sur notre personnage : rien de bien compliqué, toute l’image bouge en même temps. On en profite pour lancer l’animation du manchot qui grattouille la terre. Rien de bien compliqué pour faire apparaître l’arbre dans une explosion de lumière 🙂

Mais c’est là que les choses se corsent : il faut que je termine en bouclant sur le début, il faut donc que la dernière image se raccorde avec la première. J’ai déjà prévu un fond raccordable, par contre mon personnage a un peu bougé à l’arrache avec le combat et le plantage d’arbre. Et en plus, horreur et damnation, je me rends compte que mon bel arbre dépasse sur la partie de l’image qui apparaît sur la première image !

Un schéma montre le problème : sur la première image, l'arbre devrait apparaître

L’homme qui avait pensé à tout… sauf à ça.

Aaaargh ! Trois solutions :

  • Tout refaire pour placer l’éclair, l’arbre et cie. plus à gauche (non mais ça va pas la tête ?!)

  • Recoller le morceau d’arbre sur les premières images pour rester cohérent (mais du coup ce serait bizarre de le voir dès le début)

  • Utiliser un habile trucage 🙂

Et c’est la dernière solution (la plus feignasse, j’assume) que j’ai choisie. Et je suis assez content parce que cette petite « triche » ne se voit pratiquement pas (sauf si on le sait). Vous l’avez vue ? Eh bien c’est simple : l’arbre bouge plus vite que le fond sur les dernières images ! De telle sorte qu’il semble naturel qu’il soit sorti de l’image quand on revient sur la première image…

Bon, n’empêche que c’est quand même un peu le bazar, puisque tout doit un peu bouger pour retourner à la position initiale :

  • Par rapport au fond, le manchot doit avancer de 327 pixels

  • Pour retrouver sa position initiale (sur le bord gauche de l’image), le manchot doit reculer de 80 pixel

  • Le fond doit reculer de 400 pixels

  • L’arbre doit reculer de 585 pixels

Puisque par rapport au fond, le manchot doit avancer de 327 pixels, on peut calculer le nombre de « pas » qu’il doit faire (= le nombre d’images dans la boucle de marche). On se rappelle que manchot faisait 35,84 pixels par pas au début. Pour parcourir 327 pixels, il lui faut donc 9,12 pas (arrondis à 9). Maintenant qu’on connaît le nombre d’images nécessaires et les déplacements à faire, il n’y a plus qu’à enchaîner ! Pendant 9 images :

  • Le manchot bouge de 8,89 pixels

  • Le fond bouge de 44,44 pixels

  • L’arbre bouge de 65 pixels (sans le problème décrit plus haut, il aurait dû bouger à la même vitesse que le fond, ici il est 46% plus rapide !)

Et voilà ! Nous avons maintenant toutes nos images, y’a plus qu’à assembler !

L'ensemble des images de l'animation

81 images pour l’animation complète ! (Je passe sur l’ajout du logo et les changements de nom sur l’arbre.)

Scriptons

On est quand même à 3 fichiers SVG qui totalisent 50Mio et 81 calques. Hors de question de se taper les exportations à la main (surtout que je veux pouvoir facilement tester et changer des choses). Du coup, c’est l’heure de scripter. J’ai choisi le Ruby pour plusieurs raisons :

  • Déjà, parce que c’est ce que j’utilise en général quand je dois scripter (du coup je maîtrise mieux – mais pas tant que ça vu que je ne scripte pas si souvent)

  • C’est un langage relativement dégueulasse (on peut écrire à peu près n’importe quoi) mais qui du coup est simple à faire fonctionner

  • C’est rigolo comme langage 🙂

Tout d’abord, comme je l’ai dit en introduction, il faut savoir qu’Inkscape a un mode ligne de commande, et c’est super ! On peut choisir d’exporter un fichier en PNG avec la taille que l’on veut et en sélectionner un objet de la scène. Et ça tombe bien, puisque mes calques sont des objets et qu’en sélectionnant chaque calque un par un dans l’ordre des numéros, on obtient toutes les images de l’animation dans le bon ordre.

Et là, il y a un hic : pour choisir un objet, Inkscape veut qu’on lui donne son ID. Sauf que son ID n’a rien à voir avec le Nom qu’on lui a donné dans Inkscape. Nom que j’avais pris soin d’écrire imgXXX (avec XXX le numéro de l’image). Groumpf. Qu’à cela ne tienne, en faisant un petit grep, on se rend vite compte que les attributs id et name d’un calque sont juste à côté. On commence donc par récupérer l’ID correspondant à chaque calque avec un petit hack un peu crade mais qui marche :

get_layer = Hash.new 81.times do |t| # (Je ne detaille pas comment sont definies les variables 'img' et # 'filename' qui contiennent respectivement le nom du calque et le # nom du fichier SVG) cmd = "grep -C 2 " + img + " " + filename + " | grep id" text = #{cmd} get_layer[img] = text.split('"')[1] end

Ensuite, une fois qu’on a récupéré les bons ID associés aux bons noms, on peut lancer l’exportation des calques vers des PNG avec une bête boucle et un appel à Inkscape :

get_layer.each do |i,l| frame_name = "frames/" + i + ".png" cmd = "inkscape -C -j -i " + l + " -e " + frame_name + " " + filename system cmd end

Il ne reste plus qu’à compiler le GIF à l’aide d’ImageMagick. La façon la plus simple de faire est celle-ci :

system "convert -loop 0 -delay 10 frames/*.png animation.gif"

Mais dans mon cas, je souhaite que certaines frames soient plus longues que d’autres (par exemple, celles où le soldat parle). Dans ce cas-là, j’écris la commande ImageMagick frame par frame en précisant la durée à chaque fois (notez qu’on pourrait ne préciser la durée par défaut qu’après chaque frame qui ne l’utilise pas, mais bon, c’est le script qui s’en charge alors peu importe). J’ai oublié de le copier/coller, mais la variable delay est égale à 10 bien sûr.

cmd = "convert -loop 0 " current = 1 get_layer.each do |i,l| if current == 30 cmd = cmd + "-delay 100 " elsif current == 31 cmd = cmd + "-delay 350 " elsif current == 32 || current == 73 cmd = cmd + "-delay 200 " else cmd = cmd + "-delay " + delay + " " end cmd = cmd + "frames/" + i + ".png " current = current + 1 end cmd = cmd + "animation.gif" system cmd

ET VOILÀ !

Notre GIF est tout prêt, tout beau. Ensuite, il y a encore moyen de réduire le poids du GIF en réduisant la qualité etc. J’ai aussi généré pas mal de variantes avec des changements de couleur (via des scripts aussi), mais je vous passe les détails. J’arrête là pour le making-of, car si je commence à vous parler de la vidéo (et du son), on n’est pas rendus 🙂

Publié le 7 octobre 2015 par Gee dans Dépêches Melba

Soutenir

Ce blog est publié sous licence libre, il est librement copiable, partageable, modifiable et réutilisable. Il est gratuit car financé principalement par vos dons. Sans inscription, vous pouvez très simplement me soutenir :

Pour la saison 2024-2025, 3 842 € ont pour l'instant été collectés sur un objectif annuel de 21 200 € (SMIC brut), soit 18 % de l'objectif :

Sources de revenu

La saison étant entamée à 26 %, il y a actuellement un retard de 1 618 € sur l'objectif.

Avancement de la saison

Vous pouvez également, si vous le souhaitez, passer par une plateforme de financement participatif :