Répliquer un effet de camouflage actif avec Flash

Le camouflage actif est un concept de science-fiction, généralement présenté sous la forme d'une combinaison qui permet au porteur de devenir presque invisible. On peut le voir dans des films tels que Predator et Die Another Day et dans des jeux comme Halo et Crysis.

Ce didacticiel explique comment obtenir un tel effet dans Flash en animant un filtre de déplacement à l'aide d'une séquence de bitmaps. Non seulement l'effet est cool, mais cette technique est rarement utilisée dans les tutoriels en ligne..


Aperçu du résultat final

Jetons un coup d'œil au résultat final sur lequel nous allons travailler:


Étape 1: Cartographie des déplacements dans Flash

La cartographie de déplacement est une texture permettant de moduler la force de déplacement. Le déplacement signifie déplacer littéralement les pixels d'une surface. Dans la plupart des applications 3D, les pixels sont déplacés le long de la normale à la surface. Dans Adobe Flash, le déplacement s'effectue dans un espace 2D, le long des coordonnées X et Y d'une image..

Les filtres de déplacement dans Flash s'animent généralement en modifiant dynamiquement leur intensité (paramètres scaleX et scaleY), en modifiant la position du bitmap de déplacement (paramètre mapPoint) ou en manipulant les canaux de couleur. Ce tutoriel expliquera plus en détail ces techniques, mais nous en étudierons également une autre, qui utilise une séquence bitmap pour dessiner une nouvelle carte de déplacement sur chaque image..

Exemple de déplacement le long de la normale à la surface.

Exemple de mappage de déplacement en flash, selon les axes X et Y.


Étape 2: Document Flash

Ouvrez un nouveau document dans Flash et définissez une taille de 550x368 pour qu'elle corresponde à notre image d'arrière-plan. Définissez la fréquence d'images sur 48fps. Le filtre de déplacement va en fait fonctionner à 12 images par seconde, mais si vous souhaitez une animation supplémentaire plus tard, il semblerait plus fluide à 48 images par seconde..

Cliquez sur Fichier> Paramètres de publication> Paramètres ActionScript 3.0 et désactivez la "déclaration automatique d'instances d'étape"..


Étape 3: Importer le fond

Importer rainforest.jpg sur la scène.

Appuyez sur Ctrl + K pour aligner et faire correspondre la taille de la toile. Cela va être notre image de fond.

Maintenant, avec l'image sélectionnée, appuyez sur F8 pour la convertir en un symbole. Sélectionnez "Clip" dans le menu Type.

Si la fenêtre de propriétés est fermée, appuyez sur Ctrl + F3 pour l'ouvrir. Nous allons nommer le clip qui vient d'être créé. Dans le champ du nom de l'instance, tapez "bkgd_mc".


Étape 4: Importer la séquence bitmap

Maintenant, appuyez sur Ctrl + F8 pour créer un nouveau clip. Nous ne nommons pas cela pour l'instant. Nous allons d’abord importer la séquence bitmap dans ce clip. Allez dans Fichier> Importer> Importer dans la scène. Sélectionnez la première image de la séquence, appelée "pred0001.jpg". Flash va vous demander si vous souhaitez importer toutes les images de cette séquence. Cliquez oui.


Étape 5: Convertir la séquence bitmap

Vous remarquerez que chaque image bitmap est placée sur une image clé le long de la ligne temporelle du clip. À partir de l'image 1, sélectionnez l'image et appuyez sur F8 pour la convertir en clip. Faites cela sur chaque image jusqu'à la fin de la séquence. Faites-le dans l'ordre, du premier au dernier et assurez-vous de ne pas sauter d'images, sinon cela gâcherait l'animation.

Une fois que vous avez terminé, chaque image clé doit avoir un clip contenant une image du visage du personnage. Sélectionnez à nouveau l'image un et appuyez sur Entrée pour voir l'animation.


Étape 6: Distribuer aux calques

Sélectionnez le clip sur l'image 1. Cliquez avec le bouton droit de la souris et répartissez-le sur les calques. Encore une fois, faites-le pour tous les clips sur toutes les images. Lorsque vous avez terminé, vous ne pourrez plus voir l'animation, mais uniquement l'image sur le calque supérieur..


Étape 7: faites glisser le clip sur la scène

Appuyez sur Ctrl + L pour ouvrir la bibliothèque et faites glisser "Symbole 2" sur la scène. Dans l'onglet Propriétés, nommez cette instance "depl_mc". Ce clip sera utilisé dans notre filtre de déplacement.


Étape 8: Créer la classe de document

Nous allons écrire le code de notre filtre de carte de déplacement dans un fichier de classe de document. Créez un nouveau fichier Actionscript et nommez-le "pred_as3". Maintenant, collez ce code:

 package import flash.display.MovieClip; import flash.display.BitmapData; import flash.display.IBitmapDrawable; import flash.display.BitmapDataChannel; import flash.filters.DisplacementMapFilter; import flash.filters.DisplacementMapFilterMode; import flash.geom.Point; import flash.events.Event; Classe publique pred_as3 étend MovieClip 

Retournez au document flash et nommez la classe pred_as3.

Comme vous pouvez le constater, nous avons déjà importé toutes les classes dont nous aurons besoin dans ce tutoriel. Continuons maintenant à écrire la classe de document. Ajoutez ce code à cela:

 private var clipcont = new Array (); // toutes les images animées seront stockées dans ce tableau private var count: Number; // partie de la boucle enterframe; indique quelle image de l'animation sera affichée. var var: uint = 0; // définit la vitesse de l'animation public var var move_mc: MovieClip; public var bkgd_mc: MovieClip;

Nous énonçons quelques variables qui seront utilisées plus tard. Ils doivent être déclarés avant le constructeur de la classe s'ils doivent être utilisés par plusieurs fonctions de la classe de document..


Étape 9: Créer le filtre de déplacement

Juste en dessous de la dernière ligne, nous commençons à écrire les paramètres et le constructeur du filtre de la carte de déplacement.

 force privée var1: int = 120; // la valeur de scaleX et scaleY - définit l'intensité du filtre de déplacement privé var mapBitmap: BitmapData = new BitmapData (320,240); // la taille de la carte de déplacement en pixels private var varPointPoint: Point = nouveau Point (0,0 ); // la position du bitmap de déplacement private var composantX = BitmapDataChannel.GREEN; // quel canal de couleur est utilisé; ça ne compte pas vraiment car c'est dans les nuances de gris; private var composantY = BitmapDataChannel.GREEN; private var spe: int = 1; // modifie la force du filtre de déplacement // toutes les variables sont ensuite appliquées à un nouveau filtre filtre privé var: DisplacementMapFilter = new DisplacementMapFilter (mapBitmap, mapPoint, composantX, composantY, scaleX, scaleY); private var filterList = new Array (); // un tableau de liste de filtres.

Nous avons donc défini des paramètres pour la force, la taille, la position et le canal RBG. Regardons de plus près chacun de ces paramètres…


Étape 10: Force de déplacement

Comme mentionné précédemment, le déplacement en flash n'est possible que sur les axes X et Y. Les paramètres qui définissent la force de déplacement pour X et Y sont scaleX et échelleY respectivement. Dans ce didacticiel, nous allons utiliser la même force sur les axes X et Y, nous utilisons donc la même variable force1 pour les deux paramètres. Vous trouverez ci-dessous un exemple de déplacement sur l'axe horizontal, avec scaleY défini sur zéro (image de gauche), et l'axe vertical, avec scaleX défini sur zéro (droite)..


Étape 11: Taille de la carte de déplacement

Notez que la taille est définie sur 320x240. Nous connaissons déjà la taille des bitmaps dans l'animation et le constructeur doit avoir la même taille qu'eux. Si la valeur dans le constructeur est supérieure à celle des bitmaps, il y aura déplacement dans les zones où cela ne devrait pas se produire. Le gris # 808080 autour de la tête du personnage est une couleur neutre. Par contre, toute zone vide ou une image bitmap transparente déplaceraient en réalité l'image d'arrière-plan..

Exemple de la valeur définie dans le constructeur étant plus grande que la carte de déplacement réelle: les zones vides déplacent l’arrière-plan.


Étape 12: canal RVB

Le filtre de déplacement utilise un seul des 3 canaux RVB d'une image bitmap pour chaque axe. Lors de l'utilisation d'une image bitmap colorée en tant que carte de déplacement, chaque canal donnera des résultats très différents, comme indiqué dans l'exemple ci-dessous. Dans ce tutoriel, nous utilisons une image en nuances de gris, le canal n'est donc pas pertinent. ComponentX et composantY sont définis en vert, mais le même effet serait obtenu à l'aide des canaux rouge ou bleu.

Les différents résultats obtenus avec le canal vert, le canal rouge ou le canal bleu.


Étape 13: MapPoint

Le paramètre mapPoint définit la position de la carte de déplacement. La position est relative à l'objet auquel elle est appliquée et non à la scène. En définissant la position sur (0,0), la carte de déplacement apparaît dans le coin supérieur gauche de notre image d'arrière-plan, ce qui ne coïncide pas toujours avec le coin supérieur gauche de la scène, comme indiqué ci-dessous..

Le paramètre mapPoint est relatif à l'objet, pas à la scène.


Étape 14: Appliquer le filtre

Appliquons maintenant le filtre de déplacement à notre image d’arrière-plan "depl_mc". Le filtre de déplacement est inséré dans un tableau de filtres et nous le faisons dans le constructeur de la classe. Nous ajoutons également nos deux principaux clips à la scène avec la méthode addchild. En AS3, le constructeur de classe est la première fonction à être exécutée dans une classe de document. Elle s'appelle automatiquement. Il est donc préférable que toutes les fonctions ou méthodes devant être exécutées lors du chargement soient appelées depuis un constructeur de classe..

 fonction publique pred_as3 () addChild (deploy_mc); addChild (bkgd_mc); // ajoute les deux occurrences de Clip à la scène filterList.push (filter); // ajoute le filtre de carte de déplacement au tableau. bkgd_mc.filters = filterList; // applique le tableau de filtres au clip cible. storeClips (); 

La dernière ligne de code appelle une fonction qui n'a pas encore été écrite. Comme son nom l'indique, cette fonction stockera tous les clips animés d'un tableau. Alors allons-y et écrivez cela maintenant.


Étape 15: Stockez l'animation dans un tableau

Nous avons donc créé un filtre de carte de déplacement et l'avons appliqué au clip, mais nous n'avons pas encore ajouté de bitmaps au filtre. Nous allons le faire en deux étapes: d'abord, nous allons stocker l'animation dans un tableau, puis plus tard, nous ajouterons cette animation au filtre..

 fonction privée storeClips (): void // stocke l'animation dans un tableau count = mov_mc.numChildren; // le nombre total de MovieClips à l'intérieur de mov_mc pour (var i: int = 0; i < displ_mc.numChildren; i++)//finds all movieclips inside displ_mc  clipcont.push(displ_mc.getChildAt(i));// frames are pushed inside the clipcont array  

Cette fonction utilise un pour boucle pour numériser tous les clips à l'intérieur de dépl_mc. Nous voulons les images d'animation qui ont été converties en clips plus tôt dans ce didacticiel. Rappelez-vous quand j'ai dit de les convertir image par image? Nous avons fait cela pour que les images puissent être triées correctement et plus tard, accessibles via la méthode getChildAt (). Comme nous n’avons nommé aucune de ces instances, Flash les trie en interne par ordre de création. Si les bitmaps étaient convertis de manière aléatoire en clips, l'animation ne serait pas lue correctement. Ainsi, les images peuvent maintenant être insérées une par une dans le tableau clipcont.

Le code jusqu'à présent devrait ressembler à ceci:

 package import flash.display.MovieClip; import flash.display.BitmapData; import flash.display.IBitmapDrawable; import flash.display.BitmapDataChannel; import flash.filters.DisplacementMapFilter; import flash.filters.DisplacementMapFilterMode; import flash.geom.Point; import flash.events.Event; public class pred_as3 extend MovieClip private var clipcont = new Array (); // toutes les images animées sont stockées dans ce tableau private var count: Number; // partie de la boucle enterframe; indique quelle image de l'animation est affichée var timer privé: uint = 0; public var depl_mc: MovieClip; public var bkgd_mc: MovieClip; force privée var1: int = 120; // définit l'intensité du filtre de déplacement private var mapBitmap: BitmapData = new BitmapData (320,240); // la taille de la mappe de déplacement en pixels private var mapPoint: Point = new Point (0,0); // la position de le bitmap de déplacement privé var composantX = BitmapDataChannel.GREEN; // quel canal de couleur est utilisé; ça ne compte pas vraiment car c'est dans les nuances de gris; private var composantY = BitmapDataChannel.GREEN; var var privé: int = 1; // toutes les variables sont ensuite appliquées à un nouveau filtre privé var filtre: DisplacementMapFilter = new DisplacementMapFilter (mapBitmap, mapPoint, composantX, composantY, scaleX, scaleY); private var filterList = new Array (); // un tableau de liste de filtres. // CLASS CONSTRUCTOR fonction publique pred_as3 () addChild (depl_mc); addChild (bkgd_mc); // ajoute les deux occurrences du clip à la scène storeClips (); filterList.push (filter); // ajoute le filtre de déplacement au tableau. bkgd_mc.filters = filterList; // applique l'ensemble de filtres au clip cible.  fonction privée storeClips (): void // stocke l'animation dans un tableau count = mov_mc.numChildren; // le nombre total de clips vidéo dans la commande mov_mc pour (var i: int = 0; i < displ_mc.numChildren; i++)//finds all movieclips inside displ_mc  clipcont.push(displ_mc.getChildAt(i));// frames are pushed inside the clipcont array    

Étape 16: Animation du filtre de déplacement

Maintenant que l'animation est prête à être utilisée, mettons-la dans le filtre de déplacement. Nous allons accéder au tableau clipcont avec une boucle "time release" en utilisant le Event.ENTER_FRAME classe. Toutes les 4 images, un nouveau bitmap du tableau est utilisé, puis appliqué au filtre à l'aide de la méthode draw (). Une fois que la dernière image de clipcont est dessinée, la boucle recommence et la première image de clipcont est dessinée. C'est une boucle sans fin.

 fonction privée animate (e: Event) filter.scaleX = force1; // définit la valeur de scaleY et scaleX filter.scaleY = force1; if (timer> 3) // une nouvelle image est dessinée toutes les 4 images if (count <= 0)  count = clipcont.length;// setting an infinite loop  count--; timer = 0;  if (clipcont[count])  filter.mapBitmap.draw(clipcont[count]);// a new frame of animation is drawn  bkgd_mc.filters = filterList;//updates the filter 

Copiez les lignes ci-dessus dans votre fichier actionscript. Faisons maintenant cette exécution en ajoutant un écouteur d'événement au constructeur de classe.

 fonction publique pred_as3 () addChild (deploy_mc); addChild (bkgd_mc); // ajoute les deux occurrences de Clip à la scène filterList.push (filter); // ajoute le filtre de carte de déplacement au tableau. bkgd_mc.filters = filterList; // applique l'ensemble de filtres au clip cible. storeClips (); addEventListener (Event.ENTER_FRAME, animate); // appelle la fonction animate dans le cadre entrant

Mettez à jour le constructeur de classe avec le addEventListener méthode. Maintenant, la fonction animate a été ajoutée à la scène et est appelée à chaque image. Testez l'effet en appuyant sur Ctrl + Entrée. Vous devriez voir le visage animé dans le coin supérieur gauche de votre film..


Étape 17: Faites-le suivre la souris

Nous avons une boucle d’animation dans le coin du film. Faisons en sorte que la carte de déplacement suive la souris pour que vous puissiez voir l’effet camouflage actif sur différentes parties de l’arrière-plan. Collez cette ligne dans la fonction animate:

 fonction privée animate (e: Event) filter.scaleY = force1; // définit la valeur de scaleY et scaleX filter.scaleX = force1; minuterie ++; if (timer> 3) // une nouvelle image est dessinée toutes les 4 images if (count <= 0)  count = clipcont.length;// setting an infinite loop  count--; timer = 0;  if (clipcont[count])  filter.mapBitmap.draw(clipcont[count]);// a new frame of animation is drawn  filter.mapPoint = new Point(mouseX-160, mouseY-240); // displacement map follows the mouse bkgd_mc.filters = filterList; 

De cette façon, nous mettons à jour la position de la carte de déplacement sur une base de cadre d’entrée en utilisant les propriétés mouseX et mouseY. Appuyez sur Ctrl + Entrée pour le tester. La tête devrait maintenant suivre la souris.


Étape 18: Modifier la force du filtre

Dans la dernière étape de ce didacticiel, nous allons jouer un peu avec la force de notre filtre, en augmentant la valeur des paramètres scaleX et scaleY sur une période donnée, puis en les ramenant à la valeur initiale. Ce que nous essayons de faire avec cela est de rendre l'effet plus dynamique et… visible. Bien que le but d'un camouflage dans la vie réelle devrait être de rendre les choses moins visibles, ce que nous essayons de faire ici, c'est de le rendre cool. Faisons geler l'animation pour que vous puissiez comprendre de quoi je parle. Dans la fonction animate, remplace la ligne

 filter.mapBitmap.draw (clipcont [count]);

avec cette ligne à la place:

 filter.mapBitmap.draw (clipcont [20]);

Au lieu de dessiner l'animation, nous demandons à Flash de dessiner la même image encore et encore. Appuyez sur Ctrl + Entrée pour le tester.

L'effet semble complètement statique et ennuyeux. Donnons-lui un peu de mouvement. Collez le code ci-dessous dans la fonction animate:

 fonction privée animate (e: Event) filter.scaleY = force1; // met à jour la valeur de scaleY et scaleX filter.scaleX = force1; minuterie ++; if (timer> 3) // une nouvelle image est dessinée toutes les 4 images if (count <= 0)  count = clipcont.length;// setting an infinite loop  count--; timer = 0;  if (clipcont[count])  filter.mapBitmap.draw(clipcont[20]);// a new frame of animation is drawn  filter.mapPoint = new Point(mouseX-160, mouseY-240); // displacement map follows the mouse if (filter.scaleX > 220 || filter.scaleX < 120) // filter keeps changing it's intensity, making the effect more dynamic  spe *= -1;  strength1 += spe; bkgd_mc.filters = filterList; 

Maintenant, testez-le avec Ctrl + Entrée.

Vous voyez à quel point ça a l'air mieux? Ok, donc vous pouvez maintenant restaurer l’animation, corrigez la ligne modifiée:

 filter.mapBitmap.draw (clipcont [count]);

Cet effet est également utile si vous souhaitez attacher ultérieurement un corps statique à l'animation faciale. Cela aurait l'air plus actif à côté de l'animation bitmap.


Conclusion

Le fichier peut être un peu lourd si vous utilisez la qualité jpeg 100, ce que je recommande. Dans une qualité inférieure, l'effet perd un peu de son charme. Si vous souhaitez un film plus petit, vous pouvez compresser davantage les images dans Photoshop, mais assurez-vous de conserver le bon agencement de couleurs. La couleur autour de la tête du personnage devrait toujours être # 808080 ou vous verrez une boîte autour.

Alors c'est ça. Le premier tutoriel que j'ai jamais écrit était amusant à faire et j'espère que vous vous êtes amusés à lire et à en faire bon usage. J'apprécierais beaucoup vos commentaires. Merci d'avoir lu!