Aktiv camouflage er et sci-fi-konsept, vanligvis sett i form av en drakt som gjør at brukeren blir nesten usynlig. Det kan ses i filmer som Predator og Die Another Day, og spill som Halo og Crysis.
Denne opplæringen viser hvordan du oppnår en slik effekt i Flash ved å animere et forskyvningsfilter ved hjelp av en rekke bitmaps. Ikke bare er effekten kul, men denne teknikken er sjelden sett i online opplæringsprogrammer.
La oss se på det endelige resultatet vi vil jobbe for:
Displacement mapping er et tekstur kart som brukes til å modulere forskyvningsstyrken. Forskyvning betyr bokstavelig talt å flytte pikslene av en overflate ut av sted. I de fleste 3D-applikasjoner blir pikslene forskjøvet langs overflaten normal. I Adobe Flash skjer forskyvningen i 2D-plass, langs X- og Y-koordinatene til et bilde.
Forskydningsfiltre i Flash blir vanligvis animert ved dynamisk endring av intensiteten (skalaX, og skalaY parametere), endring av posisjonen for forskyvningsbitmapet (mapPoint-parameteren) eller ved å manipulere fargekanaler. Denne opplæringen vil videre forklare disse teknikkene, men vi vil også studere en annen, som bruker en bitmap-sekvens for å tegne et nytt forskyvningskart på hver ramme.
Eksempel på forskyvning langs overflaten normal.
Eksempel på forskyvningskartlegging i flash, langs X- og Y-aksene.
Åpne et nytt dokument i Flash og sett opp størrelsen til 550x368 slik at den samsvarer med vårt bakgrunnsbilde. Still inn bildefrekvensen til 48 fps. Forskyvningsfilteret skal faktisk kjøre på 12 fps, men hvis du vil ha ekstra animasjon senere, vil det se jevnere ut på 48 fps.
Klikk på Fil> Publiser innstillinger> ActionScript 3.0-innstillinger og slå av "auto-declare stage instances".
Importer rainforest.jpg til scenen.
Trykk Ctrl + K for å justere og matche lerretstørrelsen. Dette kommer til å være vårt bakgrunnsbilde.
Nå med bildet valgt, trykk F8 for å konvertere det til et symbol. Velg "Filmklipp" i typemenyen.
Hvis egenskapsvinduet er lukket, trykker du på Ctrl + F3 for å åpne det. Vi skal nevne filmklippet som nettopp ble opprettet. I feltet for instansnavn skriver du "bkgd_mc".
Trykk nå Ctrl + F8 for å lage et nytt filmklipp helt. Vi navngir ikke dette enda ennå. Først skal vi importere bitmap-sekvensen inne i dette filmklippet. Gå til Arkiv> Import> Importer til trinn. Velg det første bildet av sekvensen, som kalles "pred0001.jpg". Flash vil spørre om du vil importere alle bildene i denne sekvensen. Klikk ja.
Du vil legge merke til at hver bitmap er plassert på en keyframe langs filmklippslinjelinjen. Start med ramme 1, velg bildet og trykk på F8 for å skjule det til filmklippet. Gjør dette på hver ramme til slutten av sekvensen. Gjør det i orden, fra første til siste, og pass på at du ikke hopper over noen rammer, ellers vil det ødelegge animasjonen.
Når du er ferdig, bør hver nøkkelramme ha ett filmklipp som inneholder en ramme av tegnets ansikt. Velg rammen en igjen, og trykk enter for å se animasjonen.
Velg filmklippet på ramme 1. Høyreklikk og distribuér til lag. Igjen, gjør det til alle filmklipp på alle rammer. Når du er ferdig, vil du ikke lenger kunne se animasjonen, bare bildet på topplaget.
Trykk Ctrl + L for å åpne biblioteket, og dra "Symbol 2" til scenen. I fanen Egenskaper navn denne forekomsten "displ_mc". Dette filmklippet vil bli brukt i vårt forskyvningsfilter.
Vi skal skrive koden for vårt forskyvningskortfilter i en dokumentklassefil. Opprett en ny Actionscript-fil og oppgi navnet "pred_as3". Lim inn denne koden nå:
pakke import flash.display.MovieClip; importer flash.display.BitmapData; importer flash.display.IBitmapDrawable; importer flash.display.BitmapDataChannel; importer flash.filters.DisplacementMapFilter; importer flash.filters.DisplacementMapFilterMode; importer flash.geom.Point; importere flash.events.Event; offentlig klasse pred_as3 utvider MovieClip
Gå tilbake til flash-dokumentet og oppgi klassen pred_as3.
Som du kan se har vi allerede importert alle klassene som vi trenger i denne opplæringen, nå la vi fortsette å skrive dokumentklassen. Legg til denne koden til den:
private var clipcont = ny Array (); // alle animerte rammer vil bli lagret i denne gruppen private var teller: tall; // del av enterframe loop forteller hvilken ramme av animasjon som skal vises privat var-timer: uint = 0; // angir hastigheten til animasjonen offentlig var displ_mc: MovieClip; offentlig var bkgd_mc: MovieClip;
Vi oppgir noen få variabler som vil bli brukt senere. De må deklareres før klassekonstruktøren hvis de skal brukes av mer enn en funksjon i dokumentklassen.
Litt under den siste linjen begynner vi å skrive parametrene og konstruktøren til forskyvningskartfiltret.
privat var styrke1: int = 120; // verdien av skalaX og skalaY - angir intensiteten til forskyvningsfiltret privat var mapBitmap: BitmapData = ny BitmapData (320,240); // størrelsen på forskyvningskartet i piksler privat var mapPoint: Punkt = nytt punkt (0,0 ); // plasseringen av forskyvning bitmap private var componentX = BitmapDataChannel.GREEN; // hvilken fargekanal er brukt; spiller ingen rolle siden det er i gråtoner; private var komponentY = BitmapDataChannel.GREEN; privat var spe: int = 1; // endrer styrken på forskyvningsfilteret // alle variabler blir deretter påført et nytt filter privat varfilter: DisplacementMapFilter = ny DisplacementMapFilter (mapBitmap, mapPoint, komponentX, komponentY, skalaX, skalaY); private var filterList = nytt Array (); // en filterliste array.
Så vi har satt parametere for styrke, størrelse, posisjon og RBG kanal. La oss ta en nærmere titt på hver av disse parameterne ...
Som nevnt tidligere er forskyvning i blits kun mulig langs X- og Y-aksene. Parametrene som angir forskyvningsstyrken for X og Y er scaleX
og Scaley
henholdsvis. I denne opplæringen skal vi bruke samme styrke på både X- og Y-aksene, slik at vi bruker samme variable styrke1 for begge parametrene. Nedenfor er et eksempel på forskyvning langs den horisontale akse, med skala Y satt til null (venstre bilde), og den vertikale aksen, med skalaX satt til null (høyre).
Legg merke til hvordan størrelsen er satt til 320x240. Vi kjenner allerede størrelsen på bitmapsene i animasjonen, og konstruktøren må ha samme størrelse som dem. Hvis verdien i konstruktøren er større enn bitmapsverdiene, vil det bli forskyvning i områder der det ikke skal skje. # 808080 grått rundt tegnets hode er en nøytral farge, derimot et hvilket som helst område som er tomt, eller en gjennomsiktig bitmappe faktisk ville forstyrre bakgrunnsbildet.
Eksempel på at verdien i konstruktøren er større enn det faktiske forskyvningskartet: De tomme områdene fortrenker bakgrunnen.
Forskyvningsfilteret bruker bare en av de 3 RGB-kanalene på en bitmap for hver akse. Når du bruker en farget bitmap som et forskyvningskart, vil hver kanal gi svært forskjellige resultater som vist i eksemplet nedenfor. I denne opplæringen bruker vi et bilde i gråtoner, så kanalen er irrelevant. ComponentX og componentY er satt til grønt, men den samme effekten ville bli oppnådd ved å bruke de røde eller blå kanalene.
De forskjellige resultatene som ble oppnådd ved hjelp av den grønne kanalen, den røde kanalen eller den blå kanalen.
Parameter mapPoint angir posisjonen til forskyvningskartet. Stillingen er i forhold til objektet som den er brukt på, og ikke scenen. Ved å sette posisjonen til (0,0) vises forflytningskartet øverst i venstre hjørne av bakgrunnsbildet vårt, som ikke alltid vil falle sammen med scenens øverste venstre hjørne, som vist nedenfor.
MapPoint-parameteren er i forhold til objektet, ikke scenen.
La oss nå bruke forskyvningsfilteret til vårt bakgrunnsbilde "displ_mc". Forskyvningsfilteret skyves inn i en rekke filtre, og vi gjør dette inne i klassekonstruksjonen. Vi legger også våre to hovedfilmer til scenen med addchild-metoden. I AS3 er klassekonstruksjonen den første funksjonen som skal utføres i en dokumentklasse, og den kalles automatisk, så det er bedre at eventuelle funksjoner eller metoder som må kjøres ved lasting kalles fra en klassekonstruktør.
offentlig funksjon pred_as3 () addChild (displ_mc); addChild (bkgd_mc); // legg til begge filmklippsinstanser til scenen filterList.push (filter); // legg til forskyvningskartfiltret til matrisen. bkgd_mc.filters = filterList; // gjelder rekke filtre til målfilmklippet. storeClips ();
Den siste kodelinjen kaller en funksjon som ikke er skrevet ennå. Som navnet antyder, vil denne funksjonen lagre alle animerte filmklipp i en matrise. Så la oss gå videre og skrive det nå.
Så vi opprettet et forskyvningskartfilter og brukte det på filmklippet, men vi har ikke lagt til noen bitmaps til filteret ennå. Vi skal gjøre dette i to trinn: Først skal vi lagre animasjonen i en matrise, så vil vi senere legge til denne animasjonen til filteret.
Private Function StoreClips (): void // lagrer animasjonen i en array count = displ_mc.numChildren; // totalt antall filmklipp inne displ_mc for (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
Denne funksjonen bruker a til
loop for å skanne alle filmklippene inne displ_mc. Vi ønsker animasjonsrammer som ble konvertert til filmklipp tidligere i denne opplæringen. Husk da jeg sa å konvertere dem ramme for ramme? Vi gjorde det slik at rammene kunne sorteres riktig og senere åpnet ved hjelp av metoden getChildAt (). Siden vi ikke nevnte noen av disse tilfellene, sorterer Flash dem internt på bestilling. Hvis bitmapene ble tilfeldig konvertert til filmklipp, ville animasjonen aldri spille riktig. Så rammene kan nå skyves inn i clipcont array, en etter en.
Koden så langt skal se slik ut:
pakke import flash.display.MovieClip; importer flash.display.BitmapData; importer flash.display.IBitmapDrawable; importer flash.display.BitmapDataChannel; importer flash.filters.DisplacementMapFilter; importer flash.filters.DisplacementMapFilterMode; importer flash.geom.Point; importere flash.events.Event; offentlig klasse pred_as3 strekker seg MovieClip private var clipcont = new Array (); // alle animerte rammer lagres i denne gruppen private var teller: tall; // del av enterframe loop forteller hvilken animasjonsramme som blir vist privat var-timer: uint = 0; offentlig var displ_mc: MovieClip; offentlig var bkgd_mc: MovieClip; privat var styrke1: int = 120; // setter intensiteten til forskyvningsfiltret privat var mapBitmap: BitmapData = ny BitmapData (320,240); // størrelsen på forskyvningskartet i piksler private var mapPoint: Punkt = nytt punkt (0,0); // posisjonen til displacement bitmap private var componentX = BitmapDataChannel.GREEN; // hvilken fargekanal er brukt; spiller ingen rolle siden det er i gråtoner; private var komponentY = BitmapDataChannel.GREEN; privat var spe: int = 1; // alle variabler blir deretter brukt på et nytt filter privat var filter: DisplacementMapFilter = ny DisplacementMapFilter (mapBitmap, mapPoint, componentX, componentY, scaleX, scaleY); private var filterList = nytt Array (); // en filterliste array. // KLASS CONSTRUCTOR offentlig funksjon pred_as3 () addChild (displ_mc); addChild (bkgd_mc); // legge til begge filmklippsinstanser til scenen butikkklubber (); filterList.push (filter); // legg til forskyvningsfilteret i arrayet. bkgd_mc.filters = filterList; // bruker settet av filtre til målfilmklippet. Private Function StoreClips (): void // lagrer animasjonen i en array count = displ_mc.numChildren; // totalt antall filmklipp inne displ_mc for (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
Nå som vi har animasjonen klar til bruk, la oss sette den i forskyvningsfilteret. Vi kommer til å få tilgang til clipcont array med en "tidsløst" loop ved hjelp av Event.ENTER_FRAME
klasse. Hver fjerde ramme åpnes en ny bitmap i arrayet, og påføres deretter filteret ved hjelp av draw () -metoden. Etter at den siste rammen i clipcont er tegnet, begynner sløyfen over og den første rammen i clipcont er tegnet. Det er en endeløs løkke.
privat funksjon animere (e: Event) filter.scaleX = strength1; // angir verdien av skalaY og skalaX filter.scaleY = styrke1; hvis (timer> 3) // en ny ramme trekkes hver 4 rammer hvis (telle <= 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
Kopier ovenstående linjer til actionScript-filen din. La oss nå gjøre dette ved å legge til en hendelselytter til klassekonstruktøren.
offentlig funksjon pred_as3 () addChild (displ_mc); addChild (bkgd_mc); // legg til begge filmklippsinstanser til scenen filterList.push (filter); // legg til forskyvningskartfiltret til matrisen. bkgd_mc.filters = filterList; // bruker settet av filtre til målfilmklippet. storeClips (); addEventListener (Event.ENTER_FRAME, animere); // kaller animasjonsfunksjonen på innramme ramme
Oppdater klassekonstruktøren med addEventListener
metode. Nå har animasjonsfunksjonen blitt lagt til scenen og kaller på hver ramme. Test effekten ved å trykke Ctrl + Enter. Du bør se det animerte ansiktet øverst til venstre i filmen.
Vi har en animasjonsløkke som løper i hjørnet av filmen. La oss gjøre fortjenestekartet følge musen, slik at du kan se hvordan den aktive camouflage-effekten ser ut mot ulike deler av bakgrunnen. Lim inn denne linjen inne i animasjonsfunksjonen:
privat funksjon animere (e: Event) filter.scaleY = strength1; // angir verdien av skalaY og skalaX filter.scaleX = strength1; timer ++; hvis (timer> 3) // en ny ramme trekkes hver 4 rammer hvis (telle <= 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;
På denne måten oppdaterer vi posisjonen for forskyvningskortet på en innrammet ramme med musen og mouseY-egenskapene. Trykk Ctrl + Enter for å teste den. Hodet bør nå følge musen.
I det siste trinnet i denne opplæringen skal vi spille litt med styrken av filteret vårt, og øke verdien av skalaX og skalaY parametere over en tidsperiode, og deretter redusere tilbake til startverdien. Det vi prøver å oppnå med dette er å få effekten til å se mer dynamisk og ... synlig. Mens hele poenget med en kamuflasje i virkeligheten skulle være å gjøre ting mindre synlige, er det vi prøver å gjøre her, å få det til å se kult ut. La oss fryse animasjonen slik at du kan forstå hva jeg snakker om. I animasjonsfunksjonen, erstatt linjen
filter.mapBitmap.draw (clipcont [count]);
med denne linjen i stedet:
filter.mapBitmap.draw (clipcont [20]);
I stedet for å tegne animasjonen forteller vi flash for å tegne den samme rammen igjen og igjen. Trykk Ctrl + Enter for å teste den.
Effekten ser helt statisk og kjedelig ut. La oss gi det litt bevegelse. Lim inn koden nedenfor inne i animasjonsfunksjonen:
privat funksjon animere (e: Event) filter.scaleY = strength1; // oppdaterer verdien av skalaY og skalaX filter.scaleX = strength1; timer ++; hvis (timer> 3) // en ny ramme trekkes hver 4 rammer hvis (telle <= 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;
Test det nå med Ctrl + Enter.
Se hvor mye bedre ser det ut? Ok, så du kan nå gjenopprette animasjonen, fikse linjen som har blitt endret:
filter.mapBitmap.draw (clipcont [count]);
Denne effekten er også nyttig hvis du vil legge ved en statisk kropp til ansiktsanimasjonen senere. Det ville se mer aktivt ved siden av bitmap-animasjonen.
Filen kan være litt tung hvis du bruker JPEG-kvalitet 100, som er det jeg anbefaler. I en lavere kvalitet mister effekten litt av sin sjarm. Hvis du vil ha en mindre film, kan du komprimere bildene enda mer i Photoshop, men sørg for at du holder fargeskjemaet riktig. Fargen rundt tegnets hode skal alltid være # 808080, eller du får se en boks rundt den.
Så dette er det. Den første opplæringen jeg noensinne har skrevet, det var morsomt å gjøre det, og jeg håper du hadde det gøy å lese og gjøre god bruk av det. Jeg vil gjerne sette pris på tilbakemeldingen din. Takk for at du leste!