Suflați o imagine cu un efect vânt particularizat

De două ori pe lună, revizuim câteva postări preferate ale cititorilor noștri de-a lungul istoriei Activetuts +. Acest tutorial a fost publicat pentru prima oară în martie 2010.

În acest tutorial, vom crea o clasă personalizată care rupe o imagine într-o mie de piese și simulează un vânt care le suflă. Am creat acest proiect exclusiv cu AS3 și FlashDevelop - Flash nu este necesar!


Rezultatul final al rezultatelor

Să aruncăm o privire asupra rezultatului final la care vom lucra. Mergeți mai departe și faceți clic oriunde în interiorul SWF:


Intro rapid la FlashDevelop

FlashDevelop este un editor de cod gratuit pentru Flash și Flex. Puteți să-l utilizați pentru a edita fișierele de clasă atunci când lucrați cu software-ul Flash sau puteți crea un proiect AS3 care nu necesită Flash deloc - și exact asta vom face în acest tutorial.

Deci, descărcați FlashDevelop și instalați-l. Din păcate, FlashDevelop rulează numai pe Windows. Alternativele pentru Mac includ FDT și Flex Builder, deși nici unul nu este gratuit. Puteți utiliza Flash în sine și vă voi explica cum să faceți acest lucru pe măsură ce mergem împreună.


Pasul 1: Creați un proiect nou

Deschideți FlashDevelop și faceți clic pe Proiect> Proiect nou?


Pasul 2: Configurați

Selectați Actionscript 3> Proiectul AS3. Pentru numele proiectului pus în "WindEffect". Pentru locație, dați clic și navigați la dosarul în care doriți să-l salvați. Lăsați caseta de selectare "Creare director pentru proiect" selectată și faceți clic pe OK.

Dacă doriți să utilizați Flash CS3 / CS4, creați un nou fișier Flash și setați lățimea și înălțimea scenei la 550x250px, setați culoarea de fundal în negru. Denumiți-o "windEffect.fla" și salvați-o oriunde doriți.


Pasul 3: Deplasați imaginea sursă

Pentru FlashDevelop, deschideți directorul proiectului și copiați sau trageți windEffect.jpg din sursa de descărcare (legată în partea de sus a paginii) în directorul \ bin \.

Pentru Flash, copiați sau trageți windEffect.jpg de la sursa de descărcare în același director unde aveți windEffect.fla.


Pasul 4: Instalați TweenLite

Vom folosi TweenLite de către Greensock pentru derularea. Puteți descărca ultima versiune a componentei aici; De asemenea, l-am inclus în descărcarea sursei.

Pentru FlashDevelop, continuați și copiați sau trageți greensock.swc din sursa de descărcare în folderul \ lib \ pentru acest proiect.

Din FlashDevelop, faceți clic pe Vizualizare> Manager proiect


Pasul 5: Biblioteca externă

Totuși, în FlashDevelop, faceți clic pe semnul "+" din stânga folderului lib pentru ao extinde. Faceți clic dreapta pe greensock.swc și selectați Adăugare la bibliotecă.

Pentru Flash, copiați sau trageți directorul \ com \ de la sursa de descărcare în același director ca fișierul windEffect.fla.


Pasul 6: Clasa de documente

Pentru FlashDevelop, deschideți din nou managerul de proiect (consultați Pasul 4), extindeți directorul \ src \ și faceți dublu clic pe Main.as. Sub importurile și chiar deasupra definiției clasei, adăugați următoarea etichetă de metadate pentru a configura proprietățile stadiului:

[SWF (lățimea = 550, înălțimea = 250, frameRate = 30, backgroundColor = 0)]

În cadrul metodei init () după punctul de intrare al comentariului, adăugați următorul cod:

 stage.scaleMode = StageScaleMode.NO_SCALE; // nu întindeți efectul etapei var: WindEffect = nou WindEffect ('windEffect.jpg'); // vom crea clasa WindEffect în curând addChild (efect);

Asta e pentru clasa de documente principale.

Pentru Flash, creați o nouă clasă Main.as în același folder ca și proiectul dvs. Asigurați-vă că clasa Main.as se află în același director ca și fla. & com folder. Adăugați următoarele rânduri:

pachet import flash.display.Sprite; import flash.display.StageScaleMode; importul flash.events.Event; clasa publică principală extinde Sprite funcția publică Main (): void if (stage) init (); altfel addEventListener (Event.ADDED_TO_STAGE, init);  funcția privată init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); stage.scaleMode = StageScaleMode.NO_SCALE; // nu întindeți efectul etapei var: WindEffect = nou WindEffect ('windEffect.jpg'); // vom crea clasa WindEffect în curând addChild (efect); 

Deschideți Flash și atribuiți "Main" ca clasă Document.

(Nu știți sigur despre ce este vorba? Citiți această introducere rapidă la utilizarea unei clase de documente.)

Dacă încercați să rulați acest lucru acum, veți primi o eroare deoarece încă nu am creat clasa WindEffect. Asigurați-vă că salvați fișierul și lăsați-l acum.


Pasul 7: Creați clasa WindEffect

Pentru FlashDevelop, faceți clic pe Vizualizare> Manager proiect, faceți clic dreapta pe dosarul \ src \ și selectați Adăugați> Clasă nouă.


Pasul 8: Configurarea clasei

Denumiți clasa WindEffect, faceți clic pe butonul de navigare pentru clasa de bază și introduceți flash.display.Sprite. Apăsați OK pentru a finaliza.


Pasul 9: Importul altor clase

Adăugați toate importurile necesare în interiorul parantezelor de pachete chiar sub "import flash.display.Sprite;" și înainte de definirea clasei. Dați clic pe Salvați.

import com.greensock.easing.Strong; import com.greensock.TweenLite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; importul flash.events.Event; importul flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.URLRequest;

Pentru Flash, creați un nou fișier ActionScript, denumiți-l "WindEffect.as" și salvați-l în același director pe care l-ați utilizat. Ar trebui să fie chiar lângă fla. fișier, folder com și Main.as.

Adăugați următorul cod:

pachet import com.greensock.easing.Strong; import com.greensock.TweenLite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; importul flash.events.Event; importul flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.URLRequest; clasa publică WindEffect extinde Sprite funcția publică WindEffect () 

Pasul 10: Adăugați o variabilă de instanță

Adăugați o variabilă privată numită "_pictureArray". Aceasta este singura variabilă pe care o vom avea în această clasă. Scopul său principal este de a face referiri la toate spritele mici care conțin bucățile mici ale imaginii odată ce au fost sparte.

Adăugați următoarea linie de cod în paranteze
din clasa:

public class WindEffect extinde Sprite // aceasta va găzdui toate piesele imaginii pe care o vom anima. privat var _pictureArray: Array; 

Pasul 11: Adăugați constructorul

Adăugați următoarele rânduri după declarația _pictureArray:

public class WindEffect extinde Sprite // aceasta va găzdui toate piesele imaginii pe care o vom anima. privat var _pictureArray: Array; funcția publică WindEffect ($ url: String) // sunăm doar imaginea de încărcare din constructor loadPicture ($ url); 

Pasul 12: Accesați imaginea

În interiorul metodei loadPicture (), numită prin metoda constructorului, instanțiăm un încărcător pentru a încărca windEffect.jpg. Adăugăm, de asemenea, un ascultător de eveniment COMPLET pentru a asculta când încărcarea se termină.

Adăugați următoarele rânduri de cod după metoda WindEffect (). (Rețineți că parametrul "$ url" este calea către imaginea pe care o încărcăm trecată de la Main.as.)

funcția privată loadPicture ($ url: String): void // creăm un încărcător cu ascultătorii pentru a încărca imaginea sursă pe care o folosim. // și apoi încărcăm imaginea. var loader: Loader = încărcător nou; loader.contentLoaderInfo.addEventListener (eveniment.COMPLETE, onLoadComplete); // când este încărcat, apelați funcția onLoadComplete () loader.load (noua adresă URLRequest ($ url)); 

Pasul 13: Încărcare

După ce imaginea a fost importată corect, se solicită această metodă. Adăugați următoarele linii de cod după metoda loadPicture () și salvați fișierul.

funcția privată onLoadComplete (e: Event): void // pentru testarea addChild (e.target.content); 

Pasul 14: Încercați unul

Mergeți mai departe și apăsați CTRL + Enter pe tastatură. Ar trebui să funcționeze și imaginea ar trebui să fie în colțul din stânga sus al scenei.

Acum că am verificat că se încarcă corect, eliminați metoda addChild și înlocuiți-o cu următorul cod:

createEffect (e.target.content);

Clasa dvs. WindEffect ar trebui să arate astfel:

pachet import com.greensock.easing.Strong; import com.greensock.TweenLite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; importul flash.events.Event; importul flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.URLRequest; [SWF (lățime = 550, înălțime = 250, frameRate = 30, backgroundColor = 0)] clasa publică WindEffect extinde Sprite private var _pictureArray: Array; funcția publică WindEffect ($ url: String) loadPicture ($ url); 
 funcția privată loadPicture ($ url: String): void var loader: Loader = încărcător nou; loader.contentLoaderInfo.addEventListener (eveniment.COMPLETE, onLoadComplete); loader.load (noua adresă URLRequest ($ url));  funcția privată onLoadComplete (e: Event): void createEffect (e.target.content); 

Pasul 15: Configurați variabilele

Metoda createEffect () va lua parametrul de imagine care este în esență un bitmap și o va rupe până la 1250 de piese.

Mai întâi se calculează pozițiile x și y pentru a centra imaginea pe scenă. Le salvăm în variabilele locale numite centerWidth și centerHeight.

Deoarece dimensiunea imaginii pe care o folosim este de 300x100, am decis să împărți imaginea de 50 de ori pe orizontală și de 25 de ori pe verticală. Aceste valori au dat un rezultat destul de decent, cu performanțe optime. Le salvăm în variabilele locale, pe care le-am numit "numberOfColumns" și "numberOfRows".

Salvăm rezultatul împărțirii lățimii imaginii pe numărOfColume în "sizeWidth" și rezultatul divizării înălțimii imaginii prin numberOfRows în "sizeHeight".

Variabila "numberOfBoxes" deține numărOfColume înmulțit cu numberOfRows.

Apoi vom instantiza _pictureArray, astfel încât să putem începe să punem niște sprites mici în ea. Adăugați următoarele linii de cod după metoda onLoadComplete ():

funcția privată createEffect ($ bitmap: Bitmap): void // centrarea imaginii pe orizontală. var centerWidth: Numărul = (stadium.stageWidth - $ bitmap.width) * .5; // centrați imaginea pe verticală. var centerHeight: Numărul = (stadium.stageHeight - $ bitmap.height) * .5; var numărOfColume: uint = 50; var numărulOfRows: uint = 25; var dimensiuneWidth: uint = $ bitmap.width / numberOfColumns; var dimensiuneHeight: uint = $ bitmap.height / numberOfRows; var numberOfBoxes: uint = număr de coloane * numberOfRows; _pictureArray = []; 

Pasul 16: Loops inversat

Dupa instantierea _pictureArray vom adauga doua bucle, una in interiorul celeilalte. Prima buclă se va ocupa de deplasarea pe poziția x și va trece prin toate coloanele, în timp ce a doua bucla se va deplasa în poziția y și va trece prin toate rândurile.

Adăugați următoarele linii de cod în cadrul metodei createEffect () imediat după instanțarea _pictureArray, apoi salvați fișierul:

pentru (var i: uint = 0; i < numberOfColumns; i++)  //these loops are what splits the image into 1250 pieces. for (var j:uint = 0; j < numberOfRows; j++)  //let's see what it does. trace ('i:' + i, 'j:' + j);  

Pasul 17: Testul doi

Testați filmul atingând CTRL + Enter.

După cum puteți vedea, pentru fiecare eu există o buclă completă de j. Aceasta se numește "bucle de cuiburi". Aceasta înseamnă că eu care reprezintă axa x rămâne pe o valoare în timp ce a doua bucla iterează pentru axa y.

Puneți pur și simplu, începem cu x = 0, y = 0; atunci următoarea iterație este x = 0, y = 1; apoi x = 0, y = 2 și așa mai departe.

Când y atinge sfârșitul, prima buclă crește cu 1 și apoi trece din nou prin a doua bucla: x = 1, y = 0; x = 1, y = 1, x = 1, y = 2, etc. Aceasta se întâmplă până când se termină prima buclă.

Veți vedea ce se întâmplă atunci când îl aplicăm unei manipulări bitmap în următoarele câteva linii.


Pasul 18: Împărțirea imaginii

Din cadrul celei de-a doua buclă, mergeți mai departe și eliminați următoarea funcție pe care am utilizat-o pentru testare. De fiecare dată când am o buclă, trebuie să creăm o imagine mică având lățimea "sizeWidth" și înălțimea "sizeHeight".

Această imagine mică va face o fotografie dintr-o mică parte a imaginii pornind de la colțul din stânga sus și deplasându-vă spre dreapta-jos. "TempBitmapData" este locul în care vom desena partea mică a imaginii. "SourceRect" este dreptunghiul pe care îl vom folosi pentru a specifica care parte a imaginii va fi copiată.

Adăugați următoarele linii în bucla a doua și salvați fișierul:

// 1 bitmapdata temporară var tempBitmapData: BitmapData = BitmapData nou (sizeWidth, sizeHeight); // 1 dreptunghi temporar (x, y, lățime, înălțime) // treceți i * sizeWidth pentru parametrul x & i * sizeHeight pentru parametrul y // și dimensiunea Width & sizeHeight pentru parametrii de lățime și înălțime. var sourceRect: Rectangle = dreptunghi nou (i * sizeWidth, j * sizeHeight, sizeWidth, sizeHeight); urmăriți (sourceRect); // pentru testarea

Pasul 19: Testează chiar mai mult

Testați filmul. Ceea ce face acum este să creeze un dreptunghi care să-și ajusteze pozițiile x și y fiecare iterație.

După cum puteți vedea, exemplul 1 arată x = 0, y = 0, iar următorul este x = 0, y = 4. Aceasta este ceea ce folosim pentru a împușca imaginea sursă capturată. Scoateți funcția de testare atunci când sunteți pregătit să vă deplasați.


Pasul 20: BitmapData.copyPixels ()

Apoi folosim metoda BitmapData.copyPixels () pentru a copia o bucată mică a imaginii bazată pe sourceRect. Parametrii pentru această metodă sunt imaginea bitmap pentru a copia, zona dreptunghiului pentru a copia și punctul de destinație unde vom copia.

Adăugați următoarea linie de cod sub declarația sourceRect.

tempBitmapData.copyPixels ($ bitmap.bitmapData, sourceRect, punct nou);

Apoi creem o Bitmap temporară pentru a găzdui BitmapData pe care tocmai l-am copiat și un Sprite temporar pentru a găzdui Bitmap-ul respectiv.

Apoi apăsați o referință a fiecărui Sprite pe _pictureArray pentru a accesa mai târziu. După aceasta, adăugăm Sprite pe scenă cu aceeași coordonate ca și în cazul în care l-am copiat, redând astfel imaginea originală.

Apoi am compensat imaginea cu ajutorul centerWidth și centerHeight pentru a centra în mod corect pe scenă.

Adăugați următoarele linii de cod și, din nou, salvați fișierul:

// vom crea apoi un bitmap temporar pentru a găzdui bitmapdatele pe care tocmai le-am copiat. var tempBitmap: Bitmap = Bitmap nou (tempBitmapData); // și 1 sprite temporar pentru a găzdui bitmap-ul pentru a permite interactivitatea. var tempSprite: Sprite = Sprite nou; // adăugăm fiecare cutie în interiorul propriului sprite pentru a permite interactivitatea, deoarece bitmap-urile de la sine nu sunt interactive. tempSprite.addChild (tempBitmap); // fiecare sprite este adăugat în matricea _pictureArray pentru accesare mai târziu. _pictureArray.push (tempSprite); // apoi poziționați fiecare pe scena. // Adăugăm lățimea și înălțimea centrului astfel încât centrele de imagine să se afle pe scenă. tempSprite.x = i * sizeWidth + centerWidth; tempSprite.y = j * sizeHeight + centerHeight; addChild (tempSprite);

Pasul 21: Testul trei

Mergeți și încercați din nou. Ar trebui să vedeți imaginea corectă expusă pe scenă. Nici nu ar părea că a fost separat în 1250 de piese.

Chiar după brațul de închidere al celei de-a doua buclă, înainte de a închide metoda, adăugați următoarea linie de cod:

stage.addEventListener (MouseEvent.CLICK, blowwind);

Adăugăm un ascultător la eveniment pentru a asculta un MouseEvent.CLICK. Aceasta va declanșa animația executând funcția blowWind (), pe care o vom crea în pasul următor.

Clasa dvs. WindEffect ar trebui să arate astfel:

pachet import com.greensock.easing.Strong; import com.greensock.TweenLite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; importul flash.events.Event; importul flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.URLRequest; clasa publică WindEffect extinde Sprite private var _pictureArray: Array; funcția publică WindEffect ($ url: String) loadPicture ($ url);  funcția privată loadPicture ($ url: String): void var loader: Loader = încărcător nou; loader.contentLoaderInfo.addEventListener (eveniment.COMPLETE, onLoadComplete); loader.load (noua adresă URLRequest ($ url));  funcția privată onLoadComplete (e: Event): void createEffect (e.target.content);  funcția privată createEffect ($ bitmap: Bitmap): void var centerWidth: Number = (stadiu.stageWidth - $ bitmap.width) * .5; var centerHeight: Numărul = (stadium.stageHeight - $ bitmap.height) * .5; var numărOfColume: uint = 50; var numărulOfRows: uint = 25; var dimensiuneWidth: uint = $ bitmap.width / numberOfColumns; var dimensiuneHeight: uint = $ bitmap.height / numberOfRows; var numberOfBoxes: uint = număr de coloane * numberOfRows; _pictureArray = []; pentru (var i: uint = 0; i < numberOfColumns; i++)  for (var j:uint = 0; j < numberOfRows; j++)  var tempBitmapData:BitmapData = new BitmapData (sizeWidth, sizeHeight); var sourceRect:Rectangle = new Rectangle (i * sizeWidth, j * sizeHeight, sizeWidth, sizeHeight); tempBitmapData.copyPixels ($bitmap.bitmapData, sourceRect, new Point); var tempBitmap:Bitmap = new Bitmap (tempBitmapData); var tempSprite:Sprite = new Sprite; tempSprite.addChild (tempBitmap); _pictureArray.push (tempSprite); tempSprite.x = i * sizeWidth + centerWidth; tempSprite.y = j * sizeHeight + centerHeight; addChild (tempSprite);   stage.addEventListener (MouseEvent.CLICK, blowWind);   

Pasul 22: Crearea efectului vântului

Începeți prin eliminarea ascultătorului evenimentului MouseEvent.CLICK, deoarece avem nevoie să se întâmple o singură dată. Adăugați următoarele rânduri de cod după metoda createEffect ():

funcția privată blowWind (e: MouseEvent): void stage.removeEventListener (MouseEvent.CLICK, blowWind); 

Trebuie să trecem prin toate spritele pe care le-am atribuit în _pictureArray și să le animăm în mod individual.

TweenLite este aplicat pentru a anima toate piesele spre dreapta ca și cum vântul ar fi suflat pe ele.

Parametrii sunt: ​​ținta pentru tween, durata tween-ului, un obiect variabil care deține toate proprietățile, împreună cu valorile pe care doriți să le aplicați pentru tween.

De exemplu: TweenLite.to (destinație, durată, x: 100, y: 100, rotație: 30, ușurință: Strong.easeIn, onComplete: trace, onCompleteParams: ['hello'.

Ultimii doi parametri ai exemplului de mai sus sunt utilizați atunci când finisajul se termină. Parametrul onComplete apelează funcția de urmărire și parametrul onCompleteParams trimite un matrice care conține șirul "hello" în funcția de urmărire.

Adăugați următoarele linii de cod imediat după ascultătorul evenimentului:

pentru (var i: uint = 0; i < _pictureArray.length; i++)  TweenLite.to ( _pictureArray[i], getRandomInRange (.25, 2, false),  x: stage.stageWidth + 100, y:_pictureArray[i].y + getRandomInRange (-100, 100, false),// rotation: getRandomInRange (-90, 90), ease:Strong.easeIn, onComplete:removeSprite, onCompleteParams:[_pictureArray[i]]  ); 

În implementarea reală, când sunăm TweenLite din bucla, îi atribuim țintă ca _pictureArray [iterația curentă].

Pentru durata atribuiți o valoare pentru lungimea combinației la un timp aleator între 25 secunde și 2 secunde.

Obiectul variabil deține 5 proprietăți:

  • x: stage.stageWidth + 100 care va anima proprietatea x a spritei.
  • y: _pictureArray [i] .y + getRandomRange (-100,100, fals) care va obține poziția curentă a sprite-ului și va adăuga un număr aleator între -100 și 100 pentru a da animației un efect de extindere.
  • rotație: getRandomRange (-90,90) rotește sprite-ul curent la orice valoare între -90 și 90 de grade.
  • usurinta: Strong.easeIn ceea ce face ca tween-ul să înceapă încet și brusc să urce.
  • onComplete: removeSprite care apelează metoda removeSprite odată ce tween-ul a terminat și Sprite este în afara ecranului.
  • onCompleteParams care trimite matricea [_pictureArray [iterația curentă]] ca parametru pentru removeSprite.

Pasul 23: removeSprite () Metoda

Această metodă este apelată de la TweenLite când animația pentru un anumit tween a terminat. Doar scoatem Sprite din lista de afișare, astfel încât nu există nici o dezordine. Adăugați următoarele rânduri de cod după metoda blowWind ():

funcția privată removeSprite ($ sprite: Sprite): void removeChild ($ sprite); 

Pasul 24: Metoda getRandomInRange ()

Sunt sigur că sunteți familiarizat cu acest lucru (dacă nu, Carlos Yanez a scris un sfat rapid cu privire la acest subiect.) Versiunea mea are o opțiune de a întoarce fie numere întregi (int, uint) sau flotante (fracții).

Adăugați următoarele linii de cod. Dacă utilizați FlashDevelop, îl puteți salva ca un fragment personalizat, astfel încât acesta să fie ușor adăugat la orice clasă / proiect. Am declarat că este o metodă statică publică pentru accesul deplin.

Funcția statică publică getRandomInRange ($ min: Număr, $ max: Număr, $ rotunjit: Boolean = true): Numărul if ($ rotunjit) returnează Math.round (Math.random () * ($ max - $ min) min); altceva returnează Math.random () * ($ max - $ min) + $ min; 

Asta e! Rulați filmul. Dacă este ceva în neregulă, verificați codul în funcție de clasa WindEffect inclusă în descărcarea sursei.


Concluzie

Cheia pentru crearea de efecte reci este de a învăța și de a stăpâni atât manipularea imaginilor, cât și animații de tweening precum TweenLite. Vă rugăm să nu ezitați să notați o notă pentru comentarii, preocupări sau sugestii. Vă mulțumim pentru lectură!

Cod