Creați un sistem eficient de DecalSheet Flash

Am venit cu ideea de a crea ceea ce eu numesc Flash DecalSheets de pe autocolantele care vin cu modelul de avion și au folosit "decalcomanii" pentru a-mi pielea propriile aplicații Flash încă de atunci. Un DecalSheet este în esență o imagine mare (.JPG, .PNG sau .GIF) care se taie în imagini mai mici denumite "Decals", care sunt Bitmap-uri și pot fi folosite oriunde ar fi folosite DisplayObjects.

Această tehnică este una dintre cele mai eficiente modalități de a aduce o mulțime de active într-o aplicație Flash, fără a se baza pe Bibliotecă (dacă utilizați Flash IDE) sau pe eticheta Embed (dacă utilizați Flex Compiler). Să aruncăm o privire asupra modului de realizare a unui sistem DecalSheet simplu.

Cu DecalSheets, puteți reduce amprenta memoriei aplicației prin consolidarea imaginilor mai mici în imagini mai mari. Orice grafic pe care l-ați încorporat într-o clasă sau într-o locație într-o bibliotecă a FLA poate fi stocat într-o singură decaloare sau poate fi împărțit pe mai multe DecalSheets, în funcție de nevoile dvs. Din moment ce DecalSheets poate fi setat să se încarce numai când este cerut, puteți încărca în grafice aplicație exact atunci când aveți nevoie de ele, reducerea inițială de pornire și timp de încărcare. În cele din urmă, puteți reînsufleți întreaga aplicație prin simpla modificare a BitmapData a DecalSheets-ului dvs. la momentul executării.

Această diagramă ilustrează modul în care luăm o singură imagine DecalSheet și folosim coordonatele pentru a decupa un nou Decal.

În acest tutorial vom crea două clase: DecalSheet și Decal. Definiți coordonatele X, Y, Lățime și Înălțime pentru a decupa grafice din DecalSheet și va returna Decalcomanii. Decalctele sunt Bitmap-uri și pot fi folosite oriunde ar fi folosite în mod normal DisplayObjects. Ceea ce face ca decalcomantele să fie speciale este să păstreze o referință la DecalSheet de la care decupează. Când actualizați BitmapData din DecalSheet, toate decalcomantele decupate din acea foaie vor fi, de asemenea, actualizate. Acest lucru vă permite să re-derulați o întreagă aplicație la timpul de execuție prin încărcarea pur și simplu în imagini noi sursă.

Exemplul următor indică sursa DecalSheet sursă din stânga și un SimpleButton în partea dreaptă, utilizând Decals pentru fiecare stare a butonului. Când faceți clic pe buton, este încărcată o nouă imagine și datele sale Bitmap înlocuiesc pielea originală în DecalSheet. Toate butoanele din butonul simplu vor fi actualizate. Re-jupuirea este aproape instantanee!

La sfârșitul tutorialului veți avea următoarele .SWF:

Decal Sursa Sursa Imagini

Înainte de a începe, asigurați-vă că aveți următoarele două imagini. Acestea vor fi sursele DecalSheet, pe care le vom folosi pentru a elimina stările de la butoane.


button_skin_a.png
button_skin_b.png

Pasul 1: Configurarea clasei Doc

Primul lucru pe care îl vom face este să ne creăm clasa Principal Doc. Am creat deja o clasă simplă care va încărca o imagine și o va adăuga în lista de afișare.

 pachet import flash.display.Bitmap; import flash.display.Loader; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; importul flash.events.Event; import flash.net.URLRequest; clasa publica DeaclSheetTutorial extinde Sprite private var loader: Loader; funcția publică DeaclSheetTutorial () configureStage (); loadDecalSheetSource ( "images / button_skin_a.png");  funcția privată configureStage (): void stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE;  funcția publică loadDecalSheetSource (url: String): void loader = new Loader (); loader.contentLoaderInfo.addEventListener (eveniment.COMPLETE, onImageLoad); loader.load (nou URLRequest (url));  funcția privată onImageLoad (eveniment: Eveniment): void loader.removeEventListener (Event.COMPLETE, onImageLoad); var bitmap: bitmap = Bitmap (încărcător.content); addChild (bitmap); 

Când conduceți această clasă, ar trebui să ne vedeți button_skin_a.png fiind afișate pe scenă. Acum suntem gata să începem să creăm DecalSheet.

Pasul 2: Crearea clasei DecalSheet

DecalSheet extinde clasa Bitmap. Am instalat cursurile mele în pachetele "com.flashartofwar", dar sunteți liber să le configurați oricum doriți. Creați o nouă clasă numită DecalSheet și lipiți-o în următorul cod:

pachet com.flashartofwar import flash.display.BitmapData; import flash.display.Bitmap; public class DecalSheet extinde Bitmap funcția publică DecalSheet (bitmapData: BitmapData = null, pixelSnapping: String = "auto", netezirea: Boolean = false) super (bitmapData, pixelSnapping, netezirea); 

Pasul 3: Testarea DecalSheet-ului

Acum, că am creat DecalSheet-ul nostru, să ne asigurăm că poate afișa imagini. Vom face acest lucru prin trecerea în BitmapData din .png pe care l-am încărcat mai devreme. Du-te înapoi în clasa Doc și înlocui linia 40, unde numim addChild, cu următoarele:

decalSheet = nou DecalSheet (bitmap.bitmapData); addChild (decalSheet);

De asemenea, vom fi nevoiți să importați clasa DecalSheet la linia 3:

import com.flashartofwar.DecalSheet;

Pe lângă configurarea unei variabile pentru a salva DecalSheet la linia 16:

private var decalSheet: DecalSheet;

Acum, când compilați, ar trebui să vedeți aceeași imagine, dar acum este în interiorul DecalSheet-ului. Să vorbim despre modul în care putem tăia aceste grafice.

Pasul 4: Stocarea decalcomanjelor în decalaj

În acest moment avem o clasă DecalSheet simplă care extinde clasa Bitmap. Scopul nostru este acela de a putea defini zonele DecalSheet care pot fi decupate și transformate în Decalcomanii. Înainte de a putea înregistra decalcomanii, vom avea nevoie de un loc pentru a le stoca.

Adăugați următoarea proprietate pe linia 8:

protejat var decalRectangles: Dicționar = nou Dicționar (adevărat);

Și importați clasa Dictonary pe linia 5:

import flash.utils.Dictionary;

După cum puteți vedea, acest Dictonary va fi locul unde putem asocia numele unui Decal cu coordonatele sale.

Pasul 5: Înregistrarea decalcomanelor

La baza ei, un Decal este într-adevăr doar un nume și valorile lui X, Y, Width și Height pe care le folosim pentru a decupa BitmapData din DecalSheet. Vom înregistra aceste informații cu următoarea funcție pe linia 16.

funcția publică funcțiaDecal (nume: șir, dreptunghi: dreptunghi): void decalRectangles [name] = dreptunghi; 

Acum puteți asocia coordonatele decupajului unui decal la un nume și un dreptunghi.

De asemenea, va trebui să importați clasa Rectangle la rândul 5:

import flash.geom.Rectangle;

Pasul 6: Metoda eșantionului DecalSheet

Vom adăuga cea mai importantă funcție a metodei DeaclSheet, sample (). Această funcție este cea pe care o vom folosi pentru a elimina BitmapData din DecalSheet pentru a crea decalcomanii. Să punem următoarea funcție pe linia 22 a clasei DecalSheet.

proba funcției publice (nume: String): BitmapData var rect: Rectangle = decalRectangles [nume]; // Aplică decalajul corect atunci când eșantionează datele var m: Matrix = new Matrix (); m.translate (-rect.x, -rect.y); // Crează o nouă BitmapData var bmd: BitmapData = BitmapData nouă (rect.width, rect.height, true, 0xffffff); bmd.draw (bitmapData, m); retur bmd; 

De asemenea, va trebui să importați Clasa Matrix pe linia 5:

import flash.geom.Matrix;

Există o mulțime de lucruri în această funcție, așa că haideți să mergem linie cu linia prin procesul.

var rect: Dreptunghi = decalRunghiuri [nume];

Aici, folosim numele trecut în Denumire pentru a căuta dreptunghiul înregistrat din decalaj.

Înainte vom crea o Matrice pentru a compensa unde vom eșantiona BitmapData.

var m: Matrice = Matrice nouă (); m.translate (-rect.x, -rect.y);

Aici folosim poziția X și Y a dreptunghiului pentru a crea o compensare corespunzătoare a eșantionului.

Acum trebuie să creați o nouă BitmapData pentru a stoca întreruperea.

var bmd: BitmapData = BitmapData nou (rect.width, rect.height, true, 0xffffff);

După cum puteți vedea, folosim lățimea și înălțimea dreptunghiului ca dimensiuni noi, setați parametrul transparent la adevărat și dați noua culoare BitmapData o culoare de fundal de 0xffffff. Prin setarea transparentă la adevărată și furnizarea unei culori de fundal, vom putea proba corect imagini transparente .png precum exemplele "button_skin" pe care le încărcăm.

În cele din urmă, trebuie să desenați DecalSheets BitmapData în noua instanță BitmapData și să aplicați matricea.

bmd.draw (bitmapData, m);

Acum avem bitmapData compusă și vom returna pur și simplu noua instanță BitmapData.

Pasul 7: Testarea metodei eșantionului

Înainte de a merge mai departe, vom dori să facem câteva lucruri simple pentru a testa noua noastră metodă de eșantionare DecalSheet. Să ne întoarcem în clasa Doc Doc și să adăugăm următoarea funcție la linia 49 după metoda onImageLoad:

funcția publică funcțiiDecalii (): void decalSheet.registerDecal ("up", new Rectangle (0,0,99,31)); decalSheet.registerDecal ("în jos", nou dreptunghi (0,32,99,31)); decalSheet.registerDecal ("over", new Rectangle (99,0,99,31)); 

Aici puteți vedea că înregistrăm fiecare dintre butoanele de stări pe care le vom avea nevoie mai târziu atunci când creăm SimpleButton. Va trebui să importați clasa Rectangle pe linia 11:

import flash.geom.Rectangle;

... precum și adăugarea apelului pentru registerDecals pe linia 46, în interiorul funcției onImageLoad după ce am adăugat DecalSheet la scenă.

registerDecals ();

Acum vom crea o ultimă funcție în partea de jos a clasei noastre, în jurul liniei 54:

funcția publică decalSheetDemo (): void var sampleBitmap: Bitmap = Bitmap nou (decalSheet.sample ("up")); sampleBitmap.x = 230; addChild (sampleBitmap); 

Această funcție va fi principala noastră zonă de așteptare pentru restul demo-ului. În acest moment, creăm un nou Bitmap din coordonateleDecalului "up" al DecalSheetului, compensându-i poziția x și adăugându-l pe scenă.

Vom numi această funcție după apelul registerDecals pe care l-am adăugat la onImageLoad în jurul liniei 46:

decalSheetDemo ();

Acum, dacă facem o compilare, ar trebui să vedem imaginea DecalSheet din partea stângă și eșantionul Bitmap din DecalSheet din dreapta. Puteți testa toate Decalcomantele schimbând "sus" pentru "jos" sau "peste". Acum avem destule pentru a începe clasa Decal.

Pasul 8: Crearea clasei Decal

La fel ca DecalSheet, Decal va extinde, de asemenea, clasa Bitmap. Decal cu toate acestea, va avea un scop foarte specializat și se va baza pe DecalSheet pentru a furniza este BitmapData, în loc de a fi trecut în constructor. Creați o nouă clasă numită Decalare și lipiți în următorul cod:

pachet com.flashartofwar import flash.display.Bitmap; clasa publica Decal extinde Bitmap protejat var decalSheetSrc: DecalSheet; funcția publică funcțională Decal (nume: String, src: DecalSheet, pixelSnapping: String = "auto", netezirea: Boolean = false) super (null, pixelSnapping, netezirea); // Salvați sursa coli decal. decalSheetSrc = src; // Salvați numele decalului pentru a putea fi probat din DecalSheet. this.name = nume; // Obțineți date bitmap din decalSheet src. reîmprospăta();  funcția publică refresh (): void bitmapData = decalSheetSrc.sample (nume); 

Deci ce se întâmplă? După cum puteți vedea, schimbăm argumentele constructorului din BitmapClass. Decalajul nostru va trebui să știe numele acestuia (folosim acest lucru pentru a solicita BitmapData din DecalSheet prin metoda eșantionului) și trebuie să cunoaștem src DecalSheet Decal a fost decuplat de la.

Trecând prin procesul de construcție, treceți null la proprietatea BitmapData a lui super, împreună cu orice valori pentru pixelMapping și netezire. Apoi salvăm o referință a DecalSheet src în proprietatea deaclSheetSrc. Apoi salvăm valoarea trecută în numele din proprietatea moștenită de nume din BitmapData. Utilizăm "acest" pentru a distinge diferența dintre parametrul promovat și parametrul de nume al instanței clasei. În cele din urmă numim metoda de refresh.

Metoda de actualizare a decalului realizează o sarcină simplă. Solicită o nouă BitmapData din DecalSheet-ul părinte și o stabilește. Aceasta creează afișarea Decalului. Frânarea logicii pentru a solicita BitmapData de la decalSheet-ul părinte va juca un rol important mai târziu când vom începe să schimbăm BitampData din DecalSheet.

Pasul 9: Returnați decalcomanii din DecalSheet

Înainte de a putea testa că decalajul funcționează, vom dori să adăugăm capacitatea de a solicita Decalcomanii după nume din DecalSheet și să îi returnați o instanță Decal. Putem face acest lucru prin adăugarea următoarei funcții în DecalSheet după metoda registerDecal în jurul liniei 21:

funcția publică getDecal (nume: String): Decal return decalRectangles [name]? nou Decal (nume, acest): null; 

Acum putem cere decalcomanii din DecalSheet prin simpla trecere în numele oricărui Decalaj înregistrat. Veți observa această condiție scurtă. Practic, primul element este ceea ce testez. În acest caz, vrem să știm dacă numele furnizat a fost înregistrat cu decalRentangles Dictonary. Ce? denotă ce se întâmplă dacă există. Aici vom crea un nou Decal, vom da acelasi nume care a fost transferat in functia getDecal si vom furniza o referinta a instantei DecalSheet (aceasta) in Decal. Denumirea: indică ce se întâmplă dacă numele furnizat nu a fost găsit pe diagrama DactonaryRectangles. Pur și simplu ne întoarcem. Să testăm acest lucru pentru a ne asigura că totul funcționează.

Pasul 10: Testarea DecalSheet și Decal

Suntem gata să testăm decalajul nostru. Pentru a face acest lucru vom reveni la clasa Doc și vom înlocui metoda decalSheetDemo cu următorul cod:

funcția publică decalSheetDemo (): void var upDecal: Decal = decalSheet.getDecal ("sus"); upDecal.x = 230; addChild (upDecal); 

De asemenea, va trebui să importem clasa decal la linia 3:

import com.flashartofwar.Decal;

Dacă compilați clasa, ar trebui să vedeți decalajul din partea dreaptă a exemplului DecalSheet de la care a fost decuplat. Deci, care este marele lucru? Am avut același lucru cu 4 pași în urmă, cu mai puțin cod. Ei bine, permiteți-mi să vă explic de ce este o modalitate puternică de a aduce active în aplicația dvs. Flash.

Imaginați-vă că aveți o galerie foto. Dacă ați avea multe site-uri folosind toate aceleași galerie foto, dar trebuie să marcați fiecare galerie foto pe baza site-ului individual la care a fost găzduit. În funcție de modul în care creați galeria foto, puteți decide să creați un .SWF cu fiecare buton ca element din bibliotecă cu un ID de legare. Sau puteți încărca fiecare imagine individuală câte unul la un moment dat. Pentru o lungă perioadă de timp am folosit ambele căi, dar am considerat întotdeauna că este limitat să aștept un unul mare .SWF să se încarce sau multe imagini mai mici să se încarce până când am venit cu sistemul DecalSheet.

Acum, pur și simplu fac o imagine DeaclSheet, definesc coordonatele pentru fiecare buton și trebuie doar să administrez o imagine și unele date decupate. De obicei, am pus coordonatele tăiate într-un fișier .XML și acum pot să dau imaginea unui designer care poate să nu știe nimic despre Flash, dar poate crea o temă nouă cu ușurință dintr-un șablon .PSD. Știu că sună un exemplu unic, dar folosesc acest sistem în fiecare site Flash pe care îl construiesc. Nici măcar nu am atins funcția cea mai tare!

Ce se întâmplă dacă trebuie să repetați o aplicație în zbor? Va trebui să reîncărcați toate imaginile și să creați instanțe de clasă noi sau să construiți logică în componentele dvs. pentru a putea obține noile active pentru a le reconstrui. Re-jupuirea unei aplicații Flash construită cu decalcomanii este la fel de simplă ca schimbarea BitmapData a DeaclSheet-ului. Lasă-mă să-ți arăt cum.

Pasul 11: Schimbarea BitmapData cu DecalSheet

Vom avea nevoie de o modalitate de a spune tuturor decalcomanelor decupate dintr-un DecalSheet că BitmapData a fost schimbată și trebuie să fie reamplasate. Putem face acest lucru cu ușurință prin suprascrierea metodei bitmapData setată în DecalSheet. Adăugați următoarea metodă sub constructorul DecalSheet pe linia 17:

suprascrie setul de funcții publice bitmapData (valoare: BitmapData): void super.bitmapData = value; dispatchEvent (eveniment nou (Event.CHANGE)); 

... împreună cu o declarație de import pentru Eveniment la rândul 5:

importul flash.events.Event;

Acum că un nou eveniment este expediat ori de câte ori BitmapData din DecalSheet este schimbat, va trebui să ascultăm acest lucru în clasa Decal.

Pasul 12: Ascultarea evenimentelor DecalSheet

Acum că DecalSheet expediază un eveniment de schimbare atunci când BitmapData este actualizat, putem avea decalajul să asculte aceste evenimente și să reanamănească propria BitmapData din DecalSheet. Să adăugăm următoarele 3 metode în clasa Decal în cadrul funcției de refresh la rândul 27:

funcția protejată addListeners (țintă: IEventDispatcher): void target.addEventListener (Event.CHANGE, onChange, false, 0, true);  funcția protejată removeListeners (țintă: IEventDispatcher): void target.removeEventListener (Event.CHANGE, onChange);  funcția protejată peChange (eveniment: Eveniment): void refresh (); 

De asemenea, trebuie să importăm clasele IEventDispatcher și Event pe linia 4:

importul flash.events.Event; import flash.events.IEventDispatcher;

În cele din urmă, va trebui să aplicăm ascultătorului DecalSheet-ul decal al Decal prin adăugarea următorului cod la sfârșitul constructorului la linia 23 a constructorului:

addListeners (src);

Înainte de a merge mai departe, aș vrea să explic de ce am rupt adăugarea și eliminarea ascultătorilor de evenimente în funcții separate. Ori de câte ori creez cursuri, încerc să mă gândesc cum mă voi extinde de la ei și de asemenea cum pot desprinde logica în cele mai mici piese posibile. Aceste trei funcții reprezintă o caracteristică principală a Decalului și sunt probabil cele mai importante pe care am dori să le modificăm atunci când extindem această clasă. De asemenea, încerc să folosesc interfețele ori de câte ori este posibil. Eu explic acest lucru mai în detaliu mai târziu. După cum puteți vedea, putem adăuga și elimina cu ușurință ascultătorii Schimbarea evenimentului și sunăm reîmprospătați atunci când instanța Decal aude evenimentul corespunzător. În pasul următor vom construi SimpleButton și vom explora această nouă funcționalitate.

Pasul 13: Crearea unui SimpleButton

Să ne întoarcem la clasa Doc și să creăm un SimpleButton folosind toate Decalcomantele pe care le-am înregistrat în DecalSheet. Încă o dată vom înlocui funcția decalSheetDemo cu următorul cod:

funcția publică decalSheetDemo (): void var up: Decal = decalSheet.getDecal ("sus"); var peste: Decal = decalSheet.getDecal ("peste"); var jos: decal = decalSheet.getDecal ("jos"); var myButton: SimpleButton = nou SimpleButton (sus, peste, în jos); myButton.useHandCursor = adevărat; myButton.hitTestState = sus; myButton.x = 230; this.addChild (myButton); 

De asemenea, trebuie să importem SimpleButton pe linia 8:

import flash.display.SimpleButton;

Deci, acum am instalat fiecare dintre Decalcomanii, creând o nouă instanță SimpleButton și trecând în decalcomanii constructorului. Deoarece SimpeButton folosește DisplayObjects pentru fiecare stat, iar Decalcomantele noastre extinde clasa Bitmap, putem înlocui Decalcomanalele noastre oriunde se utilizează DisplayObjects. Compilați clasa Doc și verificați butonul. Veți vedea că, în sus și în jos Decalcomenzile sunt afișate atunci când butonul modifică starea.

Pasul 14: Actualizarea BitmapData lui DecalSheet

Acum o să încărcăm al doilea buton de piele "button_skin_b.png"și înlocuiți BitmapData-ul DecalSheet.Deoarece decalajele ascultă pentru evenimentul Change de pe DecalSheet, vom putea să retrăim SimpleButton fără a schimba o singură proprietate pe ea.

Această diagramă ilustrează modul în care prin schimbarea BitmapData a DecalSheet putem difuza un eveniment pentru toți copiii Decalcomanii pentru a reamplasa.

Să începem prin adăugarea în următorul ascultător al evenimentului butonului de pe linia 72 a clasei Doc după adăugarea butonului în lista de afișare:

myButton.addEventListener (MouseEvent.CLICK, onClick);

Odată ce este în loc să adăugăm următoarele trei metode sub funcția decalSheetDemo:

funcția privată onClick (eveniment: MouseEvent): void loadBlueSkin ("images / button_skin_b.png") funcția privată loadBlueSkin (url: String): void loader = new Loader (); loader.contentLoaderInfo.addEventListener (eveniment.COMPLETE, onBlueSkinLoaded); loader.load (nou URLRequest (url));  funcția privată onBlueSkinLoaded (eveniment: Eveniment): void loader.removeEventListener (Event.COMPLETE, onImageLoad); var bitmap: bitmap = Bitmap (încărcător.content); decalSheet.bitmapData = bitmap.bitmapData; 

În cele din urmă, va trebui să importim MouseEvent pe linia 13:

importul flash.events.MouseEvent;

Ceea ce am făcut aici este adăugat un clic pe Ascultarea evenimentului la SimpleButton. Când auzim acel clic pe care începem să-l încărcăm - în pielea nouă. Odată ce Skinul este încărcat, tastăm conținutul încărcătorului ca un Bitmap și îi transmitem BitmapData în setterul de date BitmapData din DecalSheet. Când rulați acest lucru acum și faceți clic pe butonul veți vedea instantaneu pielea SimpleButton și DecalSheet obține actualizat la noua imagine. Schimbarea este instantanee!

Acum ați văzut cum creăm un DecalSheet, inscripționăm Decalcomanii, obținem Decalcomanii și pielea un SimpleButton. De asemenea, mergem la restabilirea butonului la momentul executării prin simpla încărcare într-o nouă grafică. Asta se refera la capacitatea de a folosi Decalcomanii pentru a aplica aplicatia Flash. Următorii pași pur și simplu curățați codul pe care l-am scris și adăugați câteva funcționalități suplimentare pentru a ajuta la întărirea sistemului DecalSheet.

Pasul 15: Ștergeți decalajul

Nu putem lăsa DecalSheet-ul fără abilitatea de a șterge decalcomantele pe care le-am înregistrat, deci să adăugăm într-o metodă deleteDecal după metoda registerDecal:

funcția publică deleteDecal (nume: String): Boolean return delete decalRectangles [name]; 

Pasul 16: Obțineți nume înregistrate cu decalaj

Ar fi probabil util să obțineți o listă cu toate denumirile decalcate înregistrate dintr-un DecalSheet, deci să adăugăm în Array pentru a stoca doar numele Decal. Va trebui să adăugăm următoarea proprietate după decalRectangle în jurul liniei 13:

public var decal Nume: Array = Array nou ();

Și înlocuiți metodele registerDecal și deleteDecal cu următoarele funcții:

funcția publică funcțiaDecal (nume: șir, dreptunghi: dreptunghi): void decalRectangles [name] = dreptunghi; decalNames.push (nume);  funcția publică deleteDecal (nume: String): Boolean var index: Number = decalNames.indexOf (nume); dacă (index! = -1) decalNames.splice (index, 1); întoarce șterge decalRectangles [nume]; 

Putem testa acest lucru executând următoarele în Doc Class:

urmări ("Decals", decalSheet.decalNames); decalSheet.deleteDecal ( "jos"); urmări ("Decals rămase", decalSheet.decalNames);

Pasul 17: Detașați un Decal din DecalSheet

Legătura dintre decal și DecalSheet-ul său parental este incredibil de puternică, dar uneori vrem ca decalcomantele să fie puțin mai independente. De aceea vom adăuga o metodă detach la clasa decal după metoda onChange:

funcția publică detach (): void removeListeners (decalSheetSrc); decalSheetSrc = null; 

Odată ce metoda de detașare este chemată, eliminăm ascultătorii evenimentului, precum și renunțăm la referința la decalSheet src. Acest lucru întrerupe complet orice relație cu DecalSheet-ul parental.

Pasul 18: Crearea unei interfețe DecalSheet

Unul dintre conceptele fundamentale de construire a codurilor și modelelor de design OO (Object Oriented) este "Programarea unei interfețe, nu o implementare". Din păcate, pentru a explica pe deplin acest concept este în afara acestui tutorial, dar acest lucru nu înseamnă că nu putem încerca să insuflamă unele bune practici. Dacă nu ați utilizat Interfețele înainte de a fi foarte simple. Întreaga interfață nu este definită de un set de funcții publice pe care o clasă trebuie să le conțină. Deci, în sistemul nostru DecalSheet vom crea o interfață IDecalSheet și vom scrie decalajul. Acest lucru ne va păstra decalcomanii cuplați în mod liber la DecalSheet și vom permite cea mai mare flexibilitate la extinderea sistemului nostru.

Pentru a începe, va trebui să creați o nouă interfață în același pachet ca și clasele DecalSheet și Decal. Iată structura Interfeței:

pachet com.flashartofwar import flash.display.BitmapData; import flash.display.IBitmapDrawable; import flash.events.IEventDispatcher; import flash.geom.Rectangle; interfața publică IDecalSheet extinde IBitmapDrawable, IEventDispatcher function registerDecal (nume: String, dreptunghi: dreptunghi): void; funcția deleteDecal (nume: String): Boolean; funcția getDecal (nume: String): Decal; funcția eșantion (nume: String): BitmapData; 

Deci, în interfața noastră definim cele mai utilizate funcții publice care alcătuiesc DecalSheet-ul nostru. De asemenea, țineți cont de faptul că și interfața noastră poate extinde alte interfețe. Vom extinde IBitmapDrawable și IEventDispatcher. Acest lucru va permite DecalSheet-ul nostru să facă aceleași sarcini ca și clasa Bitmap și vom putea expedia și asculta evenimente de la acesta.

Acum trebuie să-i spunem DecalSheet-ului să implementeze această interfață. Mergeți în clasa DecalSheet și înlocuiți definiția clasei în jurul liniei 10 cu următoarele:

clasa publica DecalSheet extinde Bitmap implementa IDecalSheet

Dacă interfața dvs. se află în același pachet ca DecalSheet, nu trebuie să vă faceți griji cu privire la importul interfeței IDecalSheet.

Apoi trebuie să implementăm interfața în clasa Decal. Ori de câte ori vom folosi tipul DecalSheet, vom dori să îl înlocuim cu IDecalSheet:

În jurul liniei 9:

protejat var decalSheetSrc: IDecalSheet;

În jurul liniei 11:

funcția publică funcțională Decal (nume: String, src: IDecalSheet, pixelSnapping: String = "auto", netezirea: Boolean = false)

În jurul liniei 32:

funcția protejată addListeners (țintă: IDecalSheet): void

În jurul liniei 37:

funcția protejată removeListeners (țintă: IDecalSheet): void

Acum Decal nostru este complet tastat la interfața DecalSheet lui în loc de clasa actuală. De asemenea, am insistat asupra faptului că orice clasă care dorește să utilizeze clasa Decal trebuie să implementeze toate aceleași funcții publice ca DeccalSheet.

Pasul 19: Ștergeți decalcomanii din DecalSheet

Ultima caracteristică pe care o vom adăuga este capacitatea de a șterge un DecalSheet de decalcomanii și de a deconecta orice decalaj care are legătură cu DecalSheet. Pentru a începe, să adăugăm următoarea metodă la DecalSheet:

funcția publică clear (): void dispatchEvent (eveniment nou (Event.DEACTIVATE, true, true)); decalRectangles = nou Dicționar (adevărat); decalNames = Array nou (); 

Acum, când numim metoda clară pe DecalSheet, vom expedia un eveniment Dezactivare și vom șterge Dictonarul și Array. Acum trebuie să adăugăm un ascultător de evenimente la Decal. În clasa Decal înlocui funcția addListeners și removeListeners cu următoarele:

funcția protejată addListeners (țintă: IDecalSheet): void target.addEventListener (Event.CHANGE, onChange, false, 0, true); target.addEventListener (Eveniment.DEACTIVATE, onDeactivate);  funcția protejată removeListeners (target: IDecalSheet): void target.removeEventListener (Event.CHANGE, onChange); target.removeEventListener (Event.DEACTIVATE, onDeactivate); 

De asemenea, va trebui să adăugăm următoarea metodă după funcția onChange:

funcția protejată onDeactivate (eveniment: eveniment): void event.stopPropagation (); desprinde(); 

Putem testa că toate Decalcomanalele au fost deconectate prin apelarea unei metode clare pe DecalSheet și apoi încercarea de a schimba BitmapData lui DecalSheet. Veți vedea că Decalcomantele nu se mai actualizează.

Pasul 20: Extinderea sistemului DecalSheet

Există multe posibilități de extindere a sistemului DecalSheet. Un spinoff interesant este de a face TextField DecalSheet. Puteți crea cu ușurință o clasă DecalSheet care implementează interfața IDecalSheet, dar în loc de a folosi BitmapData ar lua în schimb un TextField și o va descompune în Decals. Folosind TextLineMetrics, Decalcomanii pot fi create prin trecerea liniei prin linie în jos a TextField sau Caractere de caractere. Aceasta este o modalitate excelentă de a muta textul în jurul ecranului și de a evita denaturarea pe care o întâlniți atunci când vă mișcați animând Dynamic TextFields.

PaperVision este, de asemenea, un alt loc excelent de a utiliza DecalSheets. Imaginați-vă că puteți actualiza un model 3D în zbor! Prin setarea Decalajelor ca texturi puteți actualiza BitmapData-ul DecalSheet pentru a schimba imaginea modelelor dvs. 3D.

sfarsit!

Aceasta a fost o versiune simplificată a sistemului DecalSheet găsit în Flash Camoflauge, un cadru grafic pe care l-am scris. Am folosit această tehnică în proiectele mele de peste un an și nu cred că pot trăi fără ea. Sper să vă bucurați de ea la fel de mult ca mine!

Descărcați fișierul tutorial ActionScript


Cod