Camuflajul activ este un concept SF, văzut de obicei sub forma unui costum care permite purtătorului să devină aproape invizibil. Poate fi văzută în filme precum Predator și Die Another Day și jocuri ca Halo și Crysis.
Acest tutorial vă arată cum să obțineți un astfel de efect în Flash animând un filtru de deplasare folosind o secvență de fișiere bitmaps. Nu numai că efectul este rece, dar această tehnică este rareori văzută în tutorialele online.
Să aruncăm o privire asupra rezultatului final pe care îl vom strădui:
Cartografia de deplasare este o hartă a texturii care este utilizată pentru a modula puterea de deplasare. Deplasarea înseamnă a muta în mod literal pixelii unei suprafețe în afara locului. În majoritatea aplicațiilor 3D, pixelii sunt deplasați de-a lungul suprafeței normale. În Adobe Flash, deplasarea are loc în spațiul 2D, de-a lungul coordonatelor X și Y ale unei imagini.
Filtrele de deplasare în Flash sunt, de obicei, animate prin modificarea dinamică a intensității lor (parametrii scaleX și scaleY), modificarea poziției bitmapului de deplasare (parametrul mapPoint) sau manipularea canalelor de culoare. Acest tutorial va explica în continuare aceste tehnici, dar vom studia și altul, care utilizează o secvență bitmap pentru a desena o nouă hartă de deplasare pe fiecare cadru.
Exemplu de deplasare de-a lungul suprafeței normale.
Exemplu de mapare a deplasării în bliț, de-a lungul axelor X și Y.
Deschideți un nou document în Flash și configurați dimensiunea la 550x368 pentru a se potrivi imaginii de fundal. Setați rata cadrelor la 48fps. Filtrul de deplasare va funcționa de fapt la 12fps, dar în cazul în care doriți animație suplimentară mai târziu, ar fi mai ușor la 48fps.
Faceți clic pe Fișier> Setări publicare> Setări ActionScript 3.0 și dezactivați "instanțele stadiilor de auto-declarare".
Import rainforest.jpg pe scenă.
Apăsați Ctrl + K pentru alinierea și potrivirea dimensiunii panzei. Aceasta va fi imaginea noastră de fundal.
Acum, cu imaginea selectată, apăsați F8 pentru ao converti la un simbol. Selectați "Movie Clip" din meniul de tip.
Dacă fereastra cu proprietăți este închisă, apăsați Ctrl + F3 pentru ao deschide. Vom numi filmul video care a fost creat. În câmpul nume de instanță, tastați "bkgd_mc".
Acum, apăsați pe Ctrl + F8 pentru a crea un nou clip video. Nu numim acest lucru încă. Mai întâi vom importa secvența bitmap din interiorul acestui clip video. Accesați Fișier> Import> Importare în scenă. Selectați prima imagine a secvenței, care se numește "pred0001.jpg". Flash vă va întreba dacă doriți să importați toate imaginile în această secvență. Faceți clic pe da.
Veți observa că fiecare bitmap este plasat pe un cadru cheie de-a lungul liniei de timp a filmului. Începând cu cadrul 1, selectați imaginea și apăsați F8 pentru ao ascunde în clipul video. Faceți acest lucru pe fiecare cadru până la sfârșitul secvenței. Fă-o în ordine, de la primul la ultimul și asigurați-vă că nu săriți peste cadre, altfel va afecta animația.
Odată ce ați terminat, fiecare cadru cheie trebuie să aibă un clip video care conține un cadru al feței caracterului. Selectați din nou un cadru și apăsați pe Enter pentru a vedea animația.
Selectați clipul video de pe cadrul 1. Faceți clic dreapta și distribuiți în straturi. Din nou, faceți-o la toate clipurile video pe toate cadrele. Când ați terminat, nu veți mai putea vedea animația, ci doar imaginea din stratul superior.
Apăsați Ctrl + L pentru a deschide biblioteca și trageți "Symbol 2" pe scenă. În fila de proprietăți denumiți această instanță "displ_mc". Acest clip video va fi folosit în filtrul nostru de deplasare.
Vom scrie codul pentru filtrul hărții de deplasare în interiorul unui fișier de clasă de documente. Creați un nou fișier Actionscript și denumiți-l "pred_as3". Acum lipiți acest cod:
pachet 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; importul flash.events.Event; clasa publică pred_as3 extinde MovieClip
Reveniți la documentul flash și denumiți clasa pred_as3.
După cum puteți vedea că am importat deja toate clasele de care avem nevoie în acest tutorial, acum să continuăm să scriem clasa de documente. Adăugați acest cod la acesta:
private var clipcont = new Array (); // toate cadrele animate vor fi stocate în acest număr privat var array: Number; // parte din bucla de intrare; spune ce cadru de animatie va fi afisat privat var timer: uint = 0; // seteaza viteza animatiei publice var displ_mc: MovieClip; public var bkgd_mc: MovieClip;
Menționăm câteva variabile care vor fi utilizate mai târziu. Acestea trebuie să fie declarate în fața constructorului de clasă dacă acestea urmează să fie utilizate de mai multe funcții în clasa de documente.
Chiar sub ultima linie, începem să scriem parametrii și constructorul filtrului hărții de deplasare.
privat putere var1: int = 120; // valoarea scaleiX și scaleY - stabilește intensitatea filtrului de deplasare priv var varBitmap: BitmapData = nou BitmapData (320,240); // dimensiunea hărții de deplasare în pixeli private var mapPoint: Point = new Point (0,0 ); // poziția deplasării bitmap private var componentX = BitmapDataChannel.GREEN; // care canal de culoare este utilizat; nu contează cu adevărat, deoarece este în nuanțe de gri; privat var componentY = BitmapDataChannel.GREEN; privat var spe: int = 1; // modifică puterea filtrului de deplasare // toate variabilele sunt apoi aplicate unui filtru privat filtru privat: DisplacementMapFilter = new DisplacementMapFilter (mapBitmap, mapPoint, componentX, componentY, scaleX, scaleY); private var filterList = array nou (); // o matrice listă de filtre.
Așadar, am stabilit parametrii pentru puterea, dimensiunea, poziția și canalul RBG. Să aruncăm o privire mai atentă la fiecare dintre acești parametri ...
Așa cum am menționat mai devreme, deplasarea în bliț este posibilă numai de-a lungul axelor X și Y. Parametrii care stabilesc forța de deplasare pentru X și Y sunt scaleX
și scaleY
respectiv. În acest tutorial vom folosi aceeași forță atât pe axele X cât și pe cele Y, deci folosim aceeași forță variabilă1 pentru ambii parametri. Mai jos este un exemplu de deplasare de-a lungul axei orizontale, cu scaleY setat la zero (imaginea din stânga) și axa verticală, cu scaleX setată la zero (dreapta).
Observați cum este setată dimensiunea la 320x240. Știm deja dimensiunea bitmap-urilor din animație, iar constructorul trebuie să aibă aceeași dimensiune ca și ele. Dacă valoarea din constructor este mai mare decât cea a bitmapurilor, va exista o deplasare în zone unde nu ar trebui să se întâmple. Imaginea # 808080 în jurul capului personajului este o culoare neutră, pe de altă parte orice zonă care este goală sau un bitmap transparent ar deplasa imaginea de fundal.
Exemplu de valoare setată în constructor fiind mai mare decât harta efectivă a deplasării: Zonele goale înlocuiesc fundalul.
Filtrul de deplasare utilizează numai unul din cele 3 canale RGB pe un bitmap pentru fiecare axă. Atunci când utilizați o diagramă colorată ca o hartă de deplasare, fiecare canal va da rezultate foarte diferite, după cum se arată în exemplul de mai jos. În acest tutorial folosim o imagine în nuanțe de gri, deci canalul este irelevant. Componentul X și componenta Y sunt setate pe verde, dar același efect ar fi obținut utilizând canalele roșii sau albastre.
Diferitele rezultate obținute folosind canalul verde, canalul roșu sau canalul albastru.
Parametrul mapPoint stabilește poziția hărții de deplasare. Poziția este relativă la obiectul la care a fost aplicat, și nu la scenă. Prin poziționarea poziției la (0,0), harta de deplasare apare în colțul din stânga sus al imaginii de fundal, care nu coincide întotdeauna cu colțul din stânga sus al scenei, după cum se arată mai jos.
Parametrul mapPoint este relativ la obiect, nu la etapă.
Acum, să aplicăm filtrul de deplasare în imaginea de fundal "displ_mc". Filtrul de deplasare este împins într-o serie de filtre și facem acest lucru în interiorul constructorului de clasă. Adăugăm, de asemenea, cele două clipuri video principale pe scenă cu ajutorul metodei addchild. În AS3, constructorul de clase este prima funcție care trebuie executată într-o clasă de documente și se numește automat, deci este mai bine ca orice funcție sau metodă care trebuie rulată la încărcare să fie apelată din interiorul unui constructor de clasă.
funcția publică pred_as3 () addChild (displ_mc); addChild (bkgd_mc); // adăugați ambele instanțe pentru clipul filmului în filtrul stageList.push (filtru); // adăugați filtrul hărții de deplasare în matrice. bkgd_mc.filters = filterList; // aplică matricea de filtre la clipul video vizat. storeClips ();
Ultimul rând de cod numește o funcție care nu a fost încă scrisă. După cum sugerează și numele, această funcție va stoca toate clipurile video animate într-o matrice. Să mergem mai departe și să scriem acum.
Așadar, am creat un filtru de hartă a deplasării și l-am aplicat în clipul video, dar nu am adăugat încă filtre bitmaps la filtru. Vom face acest lucru în două etape: Mai întâi vom stoca animația într-o matrice, după care vom adăuga această animație la filtru.
Funcția privată storeClips (): void // stochează animația într-un array count = displ_mc.numChildren; // numărul total de movieclips din interiorul displ_mc pentru (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
Această funcție utilizează a pentru
pentru a scana toate clipurile video din interiorul displ_mc. Vrem cadrele de animație care au fost convertite în clipuri video mai devreme în acest tutorial. Amintiți-vă când am spus să-i convertiți în cadru? Am făcut acest lucru astfel încât cadrele să poată fi sortate corespunzător și apoi accesate folosind metoda getChildAt (). Deoarece nu am numit niciuna dintre aceste instanțe, Flash le sortează pe plan intern. Dacă fișierele bitmap au fost transformate aleatoriu în clipuri video, animația nu va juca corect. Deci cadrele pot fi acum împinse în matricea clipcont, unul câte unul.
Codul ar trebui să arate astfel:
pachet 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; importul flash.events.Event; clasa publica pred_as3 extinde MovieClip private var clipcont = new Array (); // toate cadrele animate sunt stocate in acest array private count count: Number; // parte din bucla de intrare; spune ce cadru de animație este afișat privat var timer: uint = 0; public var displ_mc: MovieClip; public var bkgd_mc: MovieClip; privat putere var1: int = 120; // stabilește intensitatea filtrului de deplasare private var mapBitmap: BitmapData = nou BitmapData (320,240); // mărimea hărții de deplasare în pixeli private var mapPoint: Point = punct nou (0,0); // poziția deplasarea bitmap private var componentX = BitmapDataChannel.GREEN; // care canal de culoare este folosit; nu contează cu adevărat, deoarece este în nuanțe de gri; privat var componentY = BitmapDataChannel.GREEN; privat var spe: int = 1; // toate variabilele sunt apoi aplicate unui filtru privat filtru var: DisplacementMapFilter = nou DisplacementMapFilter (mapBitmap, mapPoint, componentX, componentY, scaleX, scaleY); private var filterList = array nou (); // o matrice listă de filtre. // funcția publică CLASS CONSTRUCTOR pred_as3 () addChild (displ_mc); addChild (bkgd_mc); // adăugați ambele instanțe clip video la scenariul storeClips (); filterList.push (filtru); // adăugați filtrul de deplasare la matrice. bkgd_mc.filters = filterList; // aplică setul de filtre la clipul video vizat. private function storeClips (): void // stochează animația într-un array count = displ_mc.numChildren; // numărul total de movieclips din interiorul displ_mc pentru (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
Acum, când avem animația gata de utilizat, să o punem în filtrul de deplasare. Vom accesa matricea clipcont cu o buclă "release time" folosind Event.ENTER_FRAME
clasă. Fiecare 4 cadre, un bitmap nou în matrice este accesat și apoi aplicat la filtru folosind metoda draw (). După ce ultimul cadru din clipcont este desenat, bucla începe din nou și primul cadru din clipcont este desenat. Este o buclă fără sfârșit.
funcția animată privată (e: Eveniment) filter.scaleX = forță1; // stabilește valoarea scaleY și scaleX filter.scaleY = strength1; dacă (timer> 3) // se creează un nou cadru la fiecare 4 cadre 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
Copiați liniile de mai sus în fișierul dvs. cu acțiuni. Acum, să facem acest lucru prin adăugarea unui ascultător al evenimentului la constructorul de clasă.
funcția publică pred_as3 () addChild (displ_mc); addChild (bkgd_mc); // adăugați ambele instanțe pentru clipul filmului în filtrul stageList.push (filtru); // adăugați filtrul hărții de deplasare în matrice. bkgd_mc.filters = filterList; // aplică setul de filtre la clipul video vizat. storeClips (); addEventListener (Event.ENTER_FRAME, animat); // apelează funcția de animare pe intrarea în cadru
Actualizați constructorul de clasă cu addEventListener
metodă. Acum, funcția de animație a fost adăugată la scenă și este apelată pe fiecare cadru. Testați efectul apăsând pe Ctrl + Enter. Ar trebui să vedeți fața animată în colțul din stânga sus al filmului.
Avem o buclă de animație care rulează în colțul filmului. Să facem ca harta deplasării să urmeze mouse-ul, astfel veți putea vedea modul în care efectul de camuflaj activ seamănă cu diferite părți ale fundalului. Inserați această linie în interiorul funcției animate:
funcția animată privată (e: Eveniment) filter.scaleY = forță1; // stabilește valoarea scaleY și scaleX filter.scaleX = strength1; timer ++; dacă (timer> 3) // se creează un nou cadru la fiecare 4 cadre 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;
În acest mod, actualizăm poziția hărții de deplasare pe baza unui cadru de intrare folosind proprietățile mouseX și mouseYY. Apăsați Ctrl + Enter pentru al testa. Capul ar trebui să urmeze acum mouse-ul.
În ultima etapă a acestui tutorial vom juca un pic cu puterea filtrului nostru, crescând valoarea parametrilor scaleX și scaleY pe o perioadă de timp, apoi scăzând înapoi la valoarea inițială. Ceea ce încercăm să realizăm cu asta este să facem efectul să arate mai dinamic și ... vizibil. În timp ce totul despre camuflaj în viața reală ar trebui să fie acela de a face lucrurile mai puțin vizibile, ceea ce încercăm să facem aici este să-l facem să arate bine. Să înghețăm animația pentru a înțelege ce vorbesc. În funcția de animație, înlocuiți linia
filter.mapBitmap.draw (clipcont [count]);
cu această linie:
filter.mapBitmap.draw (clipcont [20]);
În loc să extragem animația, îi spunem blițului să deseneze același cadru din nou și din nou. Apăsați Ctrl + Enter pentru al testa.
Efectul pare complet static și plictisitor. Să-i dăm o mișcare. Lipiți codul de mai jos în interiorul funcției de animare:
funcția animată privată (e: Eveniment) filter.scaleY = forță1; // actualizează valoarea scaleY și scaleX filter.scaleX = strength1; timer ++; dacă (timer> 3) // se creează un nou cadru la fiecare 4 cadre 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;
Acum, testați-l cu Ctrl + Enter.
Vedeți cât arată mai bine? Ok, astfel încât să puteți restaura acum animația, fixați linia care a fost modificată:
filter.mapBitmap.draw (clipcont [count]);
Acest efect este, de asemenea, util în cazul în care doriți să atașați un corp static animației faciale mai târziu. Ar fi mai activă lângă animația bitmap.
Fișierul poate fi un pic cam greu dacă folosiți 100 de calitate jpeg, ceea ce vă recomand. Într-o calitate inferioară, efectul își pierde puțin farmecul. Dacă doriți un film mai mic, puteți comprima imaginile chiar mai mult în Photoshop, dar asigurați-vă că păstrați corect schema de culori. Culoarea din jurul capului personajului trebuie să fie întotdeauna # 808080 sau veți vedea o cutie în jurul acestuia.
Așa este. Primul tutorial pe care l-am scris vreodată, a fost distractiv să o fac și sper că te-ai distrat citit și ai o bună utilizare. Aș aprecia foarte mult feedbackul dvs. Vă mulțumim pentru lectură!