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 și este prima parte a unei serii.
Codul simplu, de întreținut este frumos. Cu toate acestea, atunci când avem o secvență de acțiuni care trebuie să se declanșeze, codul nostru poate deveni dezordonat, ceea ce face imposibilă modificarea ulterioară. Model de comandă păstrează lucrurile curate.
În acest tutorial, vă voi arăta cum să creați un cadru minimalist de comandă AS3, capabil să efectueze acțiuni în ordine, în paralel sau cu întârziere. Veți baza pe modul de utilizare a acestui cadru pentru a crea un efect complex cu un cod simplu și curat.
Instrucțiunile de încapsulare în "comenzi" reprezintă o abordare populară de programare pentru a simplifica lucrurile - modelul de comandă este de fapt unul dintre cele mai des utilizate modele de design în programarea orientată pe obiecte. Practic, conceptul de comandă este implementat prin crearea de clase de comandă, fiecare clasă reprezentând un tip de comandă. În restul tutorialului, când mă refer la "o comandă", vreau să spun "un obiect de comandă".
Vă puteți gândi la o comandă ca pe un buton de pe telecomandă. Fiecare buton face ceva diferit, dar toate sunt folosite în același mod: îl apăsați, apoi magia se întâmplă. Fie că porniți televizorul, modificați canalele sau ajustați volumul, toate aceste funcții pot fi efectuate prin simpla apăsare a unui buton.
Imagine de la freedigitalphotos.net
Conceptul de comenzi este același. Instrucțiunile de bază ale unei comenzi sunt la fel ca și funcția butonului de comandă de la distanță. Puteți încorpora instrucțiuni diferite în comenzi, cum ar fi urmărirea unui mesaj simplu, mutarea unui obiect dintr-un loc în altul sau comutarea vizibilității unui obiect afișat. Odată ce se realizează încapsularea, acestea pot fi efectuate pur și simplu prin informarea programului de a "apăsa butoanele telecomenzii" sau, cu alte cuvinte, pentru a "executa comenzile".
Dacă doriți ca programul să funcționeze diferit, puteți să schimbați codul din clasa de comandă: programul execută încă aceleași comenzi pe care le-a făcut anterior, dar codul din interiorul comenzilor este diferit. Lista dvs. generală de acțiuni pe care doriți să o faceți este separată de lista detaliată a instrucțiunilor privind modul în care trebuie întreprinse fiecare acțiune.
"Aș putea spune că" am putea face asta folosind funcții. De ce mă deranjează să folosesc comenzi? " Bine, să ne uităm la două seturi de coduri care creează același efect, unul utilizând funcții, iar celălalt utilizând cadrul de comandă pe care îl vom crea în acest tutorial. Avantajul comenzilor va deveni clar.
Să spunem că vrem să creăm un cerc, să îl adăugăm pe scenă, să îl adăugăm de la invizibil la vizibil peste o jumătate de secundă, să așteptăm două secunde, să ne întoarcem la invizibil peste o jumătate de secundă și apoi să îl scoatem de pe scenă. Pentru a face toate acestea, vom folosi clasa TweenNano a lui Greensock.
Dacă utilizați numai funcții, codul va arăta astfel:
var cerc: cerc = cerc nou (); addChild (cerc); TweenNano.from (cerc, 0.5, alpha: 0, onComplete: func1); function func1 (): void TweenNano.to (cerc, 0.5, întârziere: 2, alfa: 0, onComplete: func2); func func2 (): void removeChild (cerc);
Vedeți cum lista noastră de acțiuni este încurcată cu instrucțiunile noastre de a efectua fiecare acțiune? Pentru a afla ce se va întâmpla, trebuie să urmați toate onCompleteși să vedem unde conduc.
Iată același cod, folosind un cadru de comandă:
var cerc: cerc = cerc nou (); var: Command = nou comanda SerialCommand (0, noul AddChild (acest cerc), noul TweenNanoFrom (cerc, 0.5, alpha: 0), noul TweenNanoTo (cerc, 0.5, new RemoveChild (acest cerc)); command.start ();
Aici, AddChild (), TweenNanoFrom, TweenNanoTo, și removeChild sunt toate clasele de comandă pe care le definim în altă parte a codului și SerialCommand este o altă clasă de comandă pe care o putem folosi pentru a crea secvențe de comenzi în zbor.
Rezultat: nu mai funcționează "salturi". Este clar ce va face această secvență și în ce ordine. De asemenea, este ușor să modificați ordinea acțiunilor sau să inserați o acțiune nouă între cele existente, fără a fi nevoie să căutați în jurul codului pentru fiecare acțiune și să schimbați onComplete proprietate.
De asemenea, comenzile ne permit să facem față unor acțiuni diferite, astfel încât să se întâmple în același timp - dar vom ajunge la asta mai târziu!
Un exemplu de lucru rapid este în valoare de mai mult de o mie de cuvinte, așa că să examinăm elementul esențial al cadrului nostru de comandă: clasa de comandă.
pachete comenzi import flash.events.Event; import flash.events.EventDispatcher; import flash.events.TimerEvent; import flash.utils.Timer; comanda de clasă publică extinde EventDispatcher private var _timer: Timer; funcția publică Comandă (întârziere: număr = 0) _timer = nou Cronometru (int (1000 * întârziere), 1); _timer.addEventListener (TimerEvent.TIMER_COMPLETE, onTimerComplete); funcția privată onTimerComplete (e: TimerEvent): void execute (); / ** * Pornește comanda. * Se așteaptă ca cronometrul să se termine și apelează metoda execute (). * Această metodă poate fi utilizată direct ca ascultător de evenimente. * / startul funcției finale publice (e: Event = null): void _timer.start (); / ** * Metoda abstractă pentru a vă suprascrie pentru a vă crea propria comandă. * / funcția protejată execute (): void / ** * Completează comanda. * Trimite un eveniment complet. * Această metodă poate fi utilizată direct ca ascultător de evenimente. * / funcția finală protejată este completă (e: Event = null): void dispatchEvent (eveniment nou (Event.COMPLETE));
Metoda "cel mai gol" este metoda execute (); totuși, această metodă este cea mai importantă parte a comenzii. Pentru a crea diferite obiecte de comandă, trebuie să extindeți această clasă de comandă și să înlocuiți metoda execute (), completând instrucțiunile pe care doriți ca programul să le efectueze.
Pentru a face un obiect Command să funcționeze, apelați metoda start (); contorizează timpul de întârziere folosind un obiect Timer și apelează metoda execute () atunci când cronometrul finalizează numărătoarea în jos. Un timp de întârziere zero înseamnă simplu că metoda execute () a obiectului Command va fi apelată imediat după ce îi apelați metoda start ().
(Rețineți că atunci când comanda este completă, trebuie să apelați manual metoda completă (), determinând-o să trimită un eveniment COMPLET. Scopul acestei metode va deveni clar mai târziu în tutorial.)
Apropo, setarea parametrului evenimentului pentru metodele start () și complete () cu o valoare implicită nulă este doar obiceiul meu personal. În acest fel, metodele pot fi numite așa cum ați proceda la orice alte metode cu parametri zero sau pot fi utilizate direct ca ascultători de evenimente.
Acum, când avem clasa noastră de comandă, să începem să jucăm cu ea cu o simplă urmărire.
În primul rând, trebuie să deschideți IDE-ul Flash și să creați un nou document Flash. Se numește SimpleTracing.fla.
Apoi, creați o clasă de documente pentru acest document Flash. Citiți acest sfat rapid pentru o introducere în clasele de documente.
pachet import flash.display.Sprite; clasa publică SimpleTracing extinde Sprite funcția publică SimpleTracing ()
Salvați-l ca SimpleTracing.as.
Creați un nou fișier AS și copiați clasa Comandă (de sus) în el.
Creați un nou director în clasa dvs. de cale numit "comenzi" și salvați acest nou fișier AS ca Command.as în interiorul acelui dosar.
Am dori să începem prin încapsularea unei funcții de urmărire în comenzi, așa că să extindem clasa de comandă pentru a crea o clasă TraceCommand în acest scop. Această clasă va conține un șir de mesaje care urmează să fie urmărit când se va apela metoda execute () și va apela metoda completă () după trasarea.
pachete comenzi clasa publica TraceCommand extinde Command private var _message: String; funcția publică TraceCommand (întârziere: Număr, mesaj: String) super (întârziere); _message = mesaj; suprascrie funcția protejată execute (): void trace (_message); complet();
Salvați acest lucru ca și TraceCommand.as, de asemenea în dosarul "comenzi". Vedeți cum am înlocuit-o a executa() funcția de a face această comandă de fapt face ceva?
Completați clasa de documente cu obiecte TraceCommand. Adăugați ascultători pentru evenimentul COMPLET al acestor comenzi.
pachet import commands.Command; comenzi de import.TraceCommand; import flash.display.Sprite; importul flash.events.Event; clasa publică SimpleTracing extinde Sprite funcția publică SimpleTracing () var comanda: Command; comanda = TraceCommand nou (0, "prima comandă"); command.addEventListener (Event.COMPLETE, onCommandComplete); command.start (); comanda = TraceCommand nou (1, "a doua comandă"); command.addEventListener (Event.COMPLETE, onCommandComplete); command.start (); comanda = TraceCommand nou (2, "a treia comandă"); command.addEventListener (Event.COMPLETE, onCommandComplete); command.start (); funcția privată onCommandComplete (e: Event): void trace ("o comandă este completă");
Spunerea programului de a executa comenzile este la fel de simplă ca apelarea metodelor start () ale obiectelor de comandă. Testați filmul și veți vedea următoarea ieșire, imprimată line-by-line cu un decalaj de timp de o secundă. De asemenea, puteți vedea mesajele intercalate imprimate de către ascultătorii de evenimente complete ale comenzilor. Aceeași variabilă este folosită pentru a menține referințe la diferite obiecte de comandă, însă programul face același lucru cu variabila: apelați metoda start () și ascultați pentru un eveniment COMPLET.
Există momente când doriți să executați mai multe comenzi cu o sincronizare complexă. Aici introduc două tipuri comune de comenzi care pot realiza sincronizarea avansată a comenzilor: comenzi paralele și seriale. Ambele sunt comenzi compuse, ceea ce înseamnă că acestea conțin mai multe subcomenzi. Să le verificăm unul câte unul.
O comandă paralelă execută simultan toate subcomandările sale - sau, cu alte cuvinte, în paralel. Comanda este completă numai când toate subcomandările sale sunt complete. Figura următoare prezintă un concept vizual al unei comenzi paralele. Săgețile negre denotă "fluxul" executării comenzii
Acum este momentul să creați clasa noastră pentru comenzi paralele.
Mai jos este codul complet pentru clasa ParallelCommand. Salvați-l ca ParallelCommand.as în folderul "comenzi".
Subcomandele sunt transmise constructorului ca " (restul). Aceasta ne permite să trecem cât mai multe comenzi pentru constructor; acestea vor fi automat introduse într-o matrice numită comenzi. Vom vedea frumusețea acestui tip special de parametru foarte curând.
pachete comenzi import flash.events.Event; clasa publica ParallelCommand extinde Command private var _commands: Array; funcția publică ParallelCommand (întârziere: Număr ,? comenzi) //? comenzile este parametrul "? (restul)" super (întârziere); _commands = comenzi; privată var _completeCommandCount: int; suprascrie funcția protejată finală execute (): void // a seta numărul total de comenzi la zero _completeCommandCount = 0; pentru fiecare (var comandă: comandă în _commands) // asculta pentru evenimentul complet al unui subcomandaj? command.addEventListener (Event.COMPLETE, onSubcommandComplete); //? și porniți comanda subcomandă command.start (); funcția privată onSubcommandComplete (e: Event): void // opri ascultarea comenzii complete eveniment (e.target) .removeEventListener (Event.COMPLETE, onSubcommandComplete); // incrementați numărul total de comenzi _completeCommandCount ++; // dacă toate comenzile sunt complete? dacă (_completeCommandCount == _commands.length) //? atunci această comandă paralelă este completă completă ();
Această clasă înlocuiește metoda execute (); noua metodă execute () numește acum metoda start () a tuturor subcomandanelor și ascultă pentru evenimentele lor COMPLETE. Aplicatorul COMPLETE pentru subcomenzi determină numărul de subcomenzi pe care le-ați finalizat; odată ce toate subcomandele sunt terminate, metoda full () a ParallelCommand este apelată și trimite un eveniment COMPLET propriu.
Să încercăm clasa ParallelCommand. Creați un nou document Flash, copiați folderul "comenzi" pe calea de clasă și scrieți o nouă clasă de documente, după cum urmează:
pachet import commands.Command; comenzi de import.ParallelCommand; comenzi de import.TraceCommand; import flash.display.Sprite; importul flash.events.Event; ParallelTracing extinde Sprite funcția publică ParallelTracing () var paralelCommand: Command = nou ParallelCommand (0, noul TraceCommand (0, "1 din 3"), noul TraceCommand , "Al treilea din 3"),); paralelCommand.addEventListener (Event.COMPLETE, onCommandComplete); parallelCommand.start (); funcția privată onCommandComplete (e: Event): void trace ("toate comenzile sunt complete");
Avantajul utilizării parametrului "? (Restul)" pentru parametrul constructor devine acum evident. Puteți să formatați subcomandele cu o indentare corectă a codului pentru a scrie coduri vizual explicative.
Testați filmul și veți vedea cele trei mesaje trasate în același timp, apoi un mesaj final care indică finalizarea comenzii paralele:
Cum de a stabili întârzieri în cadrul unei comenzi paralele? Simplu. Schimbați funcția constructorului clasei de document așa cum este acesta:
(0, noul TraceCommand (0, "primul val, primul din 2"), noul TraceCommand (0, "primul val, al doilea din 2"), noul TraceCommand (1, "al doilea val, al doilea din 3"), noul TraceCommand (1, "al doilea val, al treilea din 3"), noul TraceCommand (2, ultimul val, 1 din 2 "), noul TraceCommand (2," ultimul val, 2 din 2 ")); paralelCommand.addEventListener (Event.COMPLETE, onCommandComplete); parallelCommand.start ();
Testați filmul și veți vedea următoarele trei valuri de mesaje tipărite, cu un decalaj de o secundă între fiecare val:
Pentru a obține o idee mai bună despre ce se întâmplă, verificați această ilustrație:
Al doilea tip de comanda compusa este comanda serial. O comandă de serie execută subcomandele sale una după alta - sau, cu alte cuvinte, în serie. De exemplu, a doua comandă este executată după finalizarea primei și a treia este executată după finalizarea celui de-al doilea. Figura următoare prezintă un concept vizual al unei comenzi de serie:
Iată codul sursă pentru clasa SerialCommand. Metoda execute () executată () a apelat metoda start () a primei subcomandări și asculta pentru evenimentul COMPLETE. Apoi, ascultatorul evenimentului pornește următorul subcomandă și asculta pentru evenimentul său COMPLET și așa mai departe, până când toate subcomandanele sunt finalizate. În acel moment, evenimentul COMPLET pentru întregul Comandament Serial este expediat.
pachete comenzi import flash.events.Event; public class SerialCommand extinde comanda private var _commands: Array; funcția publică SerialCommand (întârziere: număr, comenzi) super (întârziere); _commands = comenzi; privată var _completeCommandCount: int; suprascrie funcția protejată finală execute (): void // a seta numărul total de comenzi la zero _completeCommandCount = 0; // ascultați pentru evenimentul complet al primei subcomandări? _comandă [0] .addEventListener (Event.COMPLETE, onSubcommandComplete); //? și porniți comanda _commands [0] .start (); funcția privată onSubcommandComplete (e: Event): void // opri ascultarea comenzii complete eveniment (e.target) .removeEventListener (Event.COMPLETE, onSubcommandComplete); // incrementați numărul total de comenzi _completeCommandCount ++; // dacă toate comenzile sunt complete? dacă (_completeCommandCount == _commands.length) //? atunci această comandă serială este completă completă (); altfel //? altfel ascultați pentru evenimentul complet al următorului subcomandă? _comanda [_completeCommandCount] .addEventListener (eveniment.COMPLETE, onSubcommandComplete); //? și porniți subcomandarea _comandă [_completeCommandCount] .start ();
Să folosim clasa SerialCommand pentru a face o urmărire în serie. Ca și înainte, creați un nou document Flash, copiați dosarul "comenzi" și scrieți o nouă clasă de documente:
pachet import commands.Command; comenzi de import.SerialCommand; comenzi de import.TraceCommand; import flash.display.Sprite; importul flash.events.Event; (1, "noua comandă"), noul TraceCommand (1, "comanda secundară"), noul TraceCommand (1, a treia comandă ")); serialCommand.addEventListener (Event.COMPLETE, onCommandComplete); serialCommand.start (); funcția privată onCommandComplete (e: Event): void trace ("toate comenzile sunt complete");
Testați filmul și următoarele mesaje sunt urmărite unul câte unul, cu un decalaj de o secundă, urmat de "toate comenzile sunt complete".
Iată o figură conceptuală a acestui exemplu, care vă ajută să înțelegeți mai bine ce se întâmplă.
Până acum, am explorat doar modul de utilizare cel mai de bază al comenzilor paralele și seriale, și nu pare să existe niciun punct de a le folosi în loc de comenzi separate. Cu toate acestea, există momente când aveți nevoie de execuții de comenzi mult mai complexe și puteți combina mai multe comenzi compuse pentru a crea comenzi imbricate pentru a se potrivi nevoilor dvs. Următorul exemplu demonstrează modul de utilizare a clasei ParallelCommand și a clasei SerialCommand pentru a crea astfel de comenzi imbricate.
Ca și înainte, creați un nou document Flash, copiați dosarul "comenzi" și scrieți o nouă clasă de documente:
pachet import commands.Command; comenzi de import.ParallelCommand; comenzi de import.SerialCommand; comenzi de import.TraceCommand; import flash.display.Sprite; importul flash.events.Event; (0, noul ParallelCommand (0, noul TraceCommand (0, "comandă paralelă 1, partea 1 din 2"), noul TraceCommand (0, "comanda paralelă # 1, partea 2 din 2"), noul TraceCommand (0, "------------------------------- - "), noul ParallelCommand (1, noul TraceCommand (0," comanda paralela 2, partea 1 din 3 "), noul TraceCommand , "comandă paralelă # 2, partea 3 din 3"), noul TraceCommand (0, "------------------------------ - ")), noul ParallelCommand (1, noul TraceCommand (0," ultima comandă "), noul TraceCommand (0," ---------------------- ---------- ")))); nestedCommands.addEventListener (Event.COMPLETE, onCommandComplete); nestedCommands.start (); funcția privată onCommandComplete (e: Event): void trace ("toate comenzile sunt complete");
Testați filmul, iar programul va imprima unul după altul următoarele fragmente de mesaje, cu un decalaj de o secundă. Ca și în exemplele anterioare, va fi tipărit un mesaj complet final când toate subcomandanele vor fi terminate.
Iată figura conceptuală a acestui exemplu.
În sfârșit, să examinăm un exemplu mai practic. Vom folosi cadrul de comandă pe care l-am construit pentru a crea o demonstrație a circuitului ușor, cu o programare avansată. Înainte de a începe, (ați ghicit-o) creați un nou document Flash, copiați dosarul "comenzi" și creați o nouă clasă de documente.
Creați un simbol pentru clip video, cu o animație cronologică în care un cerc își schimbă culoarea de la gri la galben.
În cronologie, la ultimul cadru cheie, adăugați următorul cod. Acest lucru face ca videoclipul să înceteze animarea și expedierea unui eveniment COMPLET:
Stop(); dispatchEvent (eveniment nou (Event.COMPLETE));
Dacă doriți să evitați codarea pe cronologie, puteți crea o clasă pentru movieclip cu lumină, cu o funcție:
funcția publică a ajunsEndOfAnimation (): void stop (); dispatchEvent (eveniment nou (Event.COMPLETE));
? și apoi în constructor pentru acea clasă, scrieți următoarele:
addFrameScript (4, reachedEndOfAnimation) // unde 4 este unul mai mic decât numărul de cadre
Aranjați instanțe luminoase pe scenă și denumiți-le, după cum arată figura următoare:
Glisați o componentă de buton din panoul Componente pe scenă și denumiți-o "start_btn". Vrem să executăm comenzile noastre atunci când este apăsat acest buton.
Creați un câmp de text pe scenă și introduceți mesajul de completare. Apoi, convertiți-l la un simbol pentru film și denumiți instanța "completeMessage_mc".
Acum este momentul să editați clasa de documente. Declarați o variabilă privată "circuitCommand", care va fi utilizată pentru a menține o referință la un obiect Command:
private var circuitCommand: Command;
La începutul programului, toate luminile trebuie să fie oprite, adică oprite la primul cadru, iar mesajul de finalizare trebuie ascuns. Așa că numim metoda reset () în constructor.
reset ();
Apoi, creați comenzile noastre imbricate care redau animațiile clipurilor video luminoase, aprinzându-le cu un calendar adecvat. Folosim aici o clasă PlayCommand, care apelează pur și simplu metoda play () a unui film. Vom scrie clasa mai târziu.
(0, light_2_1), noul PlayCommand (0, light_2_2), noul PlayCommand (0.5, light_3), noul ParallelCommand (0.5, noul PlayCommand (0, noul PlayCommand (0, light_4_1), noul PlayCommand (0, light_4_2)), noul PlayCommand (0.5, light_5));
Apoi, ascultați evenimentul COMPLET al comenzii și evenimentul CLICK al butonului de pornire:
circuitCommand.addEventListener (Event.COMPLETE, onCommandComplete); start_btn.addEventListener (MouseEvent.CLICK, startCircuit);
Afișați mesajul de finalizare când comanda este finalizată:
funcția privată peCommandComplete (e: Event): void completeMessage_mc.visible = true;
Resetați circuitul și porniți comanda la apăsarea butonului de pornire.
funcția privată startCircuit (e: MouseEvent): void reset (); circuitCommand.start ();
Ultima parte pentru clasa de documente este metoda reset (). Nu are nimic de a face cu comenzile de aici.
resetarea funcției private (): void completeMessage_mc.visible = false; light_1.gotoAndStop (1); light_2_1.gotoAndStop (1); light_2_2.gotoAndStop (1); light_3.gotoAndStop (1); light_4_1.gotoAndStop (1); light_4_2.gotoAndStop (1); light_5.gotoAndStop (1);
Ultima parte a acestui exemplu este clasa PlayCommand. Așa cum am menționat mai sus, ceea ce face este la fel de simplu ca și apelarea unei metode play () a unui film. Imediat ce metoda play () este apelată în metoda execute () executată de comanda, metoda full () este de asemenea numită.
pachete comenzi import flash.display.MovieClip; importul flash.events.Event; clasa publică PlayCommand extinde comanda private var _movieClip: MovieClip; funcția publică PlayCommand (întârziere: Număr, filmClip: MovieClip) super (întârziere); _movieClip = movieClip; suprascrie funcția protejată execute (): void _movieClip.addEventListener (Event.COMPLETE, complete); _movieClip.play ();
Salvați acest lucru ca PlayCommand.as în folderul "comenzi".
În regulă, am terminat! Acum, testați filmul și veți vedea lumina aprinsă de la stânga la dreapta după ce ați apăsat butonul de pornire. Mesajul de finalizare este afișat când toate luminile sunt aprinse.
Iată reprezentarea vizuală a ceea ce se întâmplă în acest exemplu:
Comparați-l cu codul real și vedeți cât de ușor este să înțelegeți:
noul PlayCommand (0, light_2_2), noul PlayCommand (0.5, light_3), noul ParallelCommand (0.5, noul PlayCommand (0, light_4_1), noul PlayCommand (0, light_4_2)), noul PlayCommand (0.5, light_5));
Din nou, cu o indentare corectă a codului, o comandă complexă imbricată poate fi exprimată ca un cod simplu și curat.
În acest tutorial ați învățat conceptul de comenzi. Instrucțiunile pot fi încapsulate în comenzi care au interfețe identice, la fel ca fiecare buton de pe o telecomandă are o acțiune diferită, dar metoda de invocare a fiecărei acțiuni este aceeași: apăsați butonul.
De asemenea, acest tutorial vă prezintă două tipuri de comenzi compuse: paralele și seriale. Acestea pot fi folosite pentru a crea comenzi imbricate care să permită executarea avansată a comenzii în timp ce codul este curat.
Conceptul de comenzi este foarte convenabil și puternic. Încapsularea codului este principala abordare a simplificării lucrurilor în timpul programării, iar una dintre metodele cele mai frecvent utilizate este utilizarea obiectelor de comandă. Sper că acest tutorial vă ajută să înțelegeți mai bine cum să utilizați comenzi în aplicații practice.
În următoarea parte a acestui tutorial, vă voi arăta cum să integrați TweenLite cu cadrul de comandă pe care l-am creat în acest tutorial, apoi să efectuați tranzițiile scenelor cu un cod simplu și curat. Vă mulțumesc foarte mult pentru lectură.