Managementul sunetului este foarte important pentru multe tipuri de aplicații Flash, cum ar fi site-uri și jocuri interactive. Atâta timp cât doriți să furnizați o experiență interactivă bogată, vă recomandăm să luați în considerare utilizarea efectelor sonore și a muzicii de fundal. În acest tutorial, voi prezenta un cadru minimalist de gestionare a sunetului care gestionează sunetele în piese audio. Și voi arăta cum să integrez cadrul de sunet cu cadrul de comandă din tutorialele mele anterioare.
Am jucat jocuri cu gestionarea inadecvată a sunetului, ceea ce degradează experiența utilizatorului. Ați jucat vreodată un joc, să spunem, un joc de acțiune, unde vocea exclamării personajului se joacă înainte ca vocea anterioară să se termine, suprapunându-se unul pe altul? Acesta este rezultatul unei gestionări nepotrivite a sunetului: nu trebuie să existe mai mult de o singură voce a aceluiași personaj care joacă la un moment dat. Cadrul de gestionare a sunetului pe care urmează să-l acopere va avea grijă de această problemă, gestionând sunete cu piese de sunet.
Exemplele din acest tutorial utilizează cadrul de comandă și cadrul de gestionare a scenelor din tutorialul meu precedent, Gândirea în comenzi (Partea 1, Partea 2), iar exemplele utilizează de asemenea clasa manager de date din Încărcare date cu comenzi. Vă recomandăm să treceți mai întâi prin aceste tutoriale înainte de a merge mai departe. De asemenea, veți avea nevoie de platforma GreenSock Tweening pentru a completa exemplele.
Piesa de sunet despre care vorbim aici nu are nimic de-a face cu piese de sunet pentru jocuri sau pentru filme. O piesă sonoră este o "piesă" imaginară asociată cu o redare a unui singur sunet. O singură melodie audio nu permite mai mult de un sunet să fie redat la un moment dat. Dacă o melodie sună în prezent la un sunet, spunem că este ocupat. Dacă un alt sunet va fi redat pe o piesă sonoră ocupată, sunetul redat în prezent este oprit și apoi cel nou este redat pe pistă. Este deci rezonabil să joci voci ale unui singur personaj pe o singură piesă sonoră, pentru a evita problema suprapusă de sunet menționată mai sus. De asemenea, în majoritatea cazurilor, ar trebui să existe o singură melodie pentru muzica de fundal.
Să aruncăm o privire asupra unor figuri conceptuale. O singură aplicație poate avea mai multe piste de sunet.
Fiecare piesă de sunet poate conține un singur sunet de redare.
Dacă un sunet trebuie redat pe o pistă ocupată, sunetul "vechi" este mai întâi oprit și apoi sunetul "nou" este redat pe pistă.
Cadrul de gestionare a sunetului constă din două clase: SoundManager clasa și SoundTrack clasă. Fiecare piesă de sunet are un șir de chei unic. Un sunet de sunet care se află sub forma unui sunet ocupat este de fapt un obiect nativ SoundChannel obținut din metoda nativă Sound.play () și SoundManager clasa gestionează piese audio și organizează redarea sunetelor.
Iată câteva previzualizări rapide ale utilizării cadrului. Următorul cod redă un sunet nou pe o piesă de sunet asociată cu șirul cheie "muzică", unde MySound este o clasă de sunet din bibliotecă.
// redă un sunet pe piesa "muzică" SoundManager.play ("muzică", noul MySound ());
Dacă același rând de cod este executat din nou înainte de finalizarea redării, sunetul original este oprit și un sunet nou este redat pe piesa "muzică".
// opriți sunetul original pe piesa "muzică" și redați un sunet nou SoundManager.play ("muzică", noul MySound ());
SoundManager.stop () metoda oprește o piesă sonoră asociată cu un șir de chei specificat.
// opri melodia muzicală SoundManager.stop ("muzică");
Pentru a transforma sunetul, cum ar fi să ajustăm volumul, va trebui să obținem o referință la canalul de sunet sub fundul unei sonore. Referința poate fi obținută accesând SoundTrack.channel proprietate.
canal var: SoundChannel = SoundManager.getSoundTrack ("muzică"). Var transform: SoundTransform = channel.soundTransform; transform.volume = 0.5; channel.soundTransform = transform;
Teoria suficientă. Să mergem la codificare. Vom folosi diferite chei de caractere cheie pentru a distinge diferite piste de sunet. Iată-l SoundTrack , care reprezintă în esență o pereche de canale-cheie. Detaliile sunt descrise în comentarii.
pachete de sunete import flash.media.SoundChannel; / ** * O piesă audio reprezintă o pereche de canale-cheie. * / clasa publica SoundTrack // valoare cheie numai pentru citire privat var _key: String; funcția publică get get (): String return _key; // referință canal numai pentru citire privat var _channel: SoundChannel; funcția publică obține canal (): SoundChannel return _channel; funcția publică SoundTrack (cheie: String, canal: SoundChannel) _key = cheie; _channel = canal; / ** * Opreste canalul de sunet care sta la baza. * / funcția publică stop (): void _channel.stop ();
Și iată-l SoundManager clasă. Rețineți că asocierea cu cheie este urmată de utilizarea clasei Dicționar. O piesă este golită automat dacă un sunet de redare a ajuns la sfârșit.
pachete de sunete import flash.events.Event; import flash.media.Sound; import flash.media.SoundChannel; import flash.media.SoundTransform; import flash.utils.Dictionary; / ** * Această clasă vă permite să gestionați sunete în termeni de piste audio. * / clasa publica SoundManager // un dicționar care ține piese ale tuturor pistelor de sunet private static var _soundTracks: Dictionary = new Dictionary (); // un dicționar care cartografiază un canal de sunet la cheia corespunzătoare pentru finalizarea redării de manipulare privată statică var _soundKeys: Dictionary = new Dictionary (); / ** * Redă un sunet și returnează un obiect de melodie corespunzător. * / redarea funcției statice publice (cheia: String, sunet: Sound, startTime: int = 0, bucle: int = 0, transformare: SoundTransform = null): SoundTrack dacă (isPlaying (cheie)) este oprit (cheie); // redați sunetul, creând un nou canal de sunet var canal: SoundChannel = sound.play (startTime, bucle, transformare); // ascultați pentru evenimentul complet al canalului de canal channel.addEventListener (Event.SOUND_COMPLETE, onSoundComplete); // creați o nouă melodie de sunet var soundtrack: SoundTrack = SoundTrack nou (cheie, canal); // adăugați piesa de sunet în dicționar _soundTracks [key] = soundtrack; // adăugați relația de mapare a canalului _soundKeys [channel] = cheie; retur soundtrack; / ** * Returnează o referință la piesa de sunet corespunzătoare șirului de taste furnizat. * / funcția statică publică getSoundTrack (cheie: String): SoundTrack return _soundTracks [key]; / ** * Determină dacă o melodie audio este redată în prezent. * / funcția statică publică estePlaying (cheie: String): Boolean return Boolean (_soundTracks [cheie]); / ** * Oprește o melodie audio. * / stop statică publică (cheie: String): void var soundtrack: SoundTrack = _soundTracks [cheie]; // verifica dacă piesa de sunet există dacă (soundtrack) // opri piesa de sunet soundTrack.stop (); // și eliminați-l din dicționar ștergeți _soundTracks [key]; // împreună cu relația canal-cheie șterge _soundKeys [soundTrack.channel]; / ** * Elimină o piesă de sunet când redarea sunetului este completă * / funcția statică privată onSoundComplete (e: Event): void // distribuie dispecerul evenimentului la un canal de sunet var canal: SoundChannel = SoundChannel (e. ţintă); // elimina canalul evenimentului listener.removeEventListener (Event.SOUND_COMPLETE, onSoundComplete); // extrageți cheia corespunzătoare var var: String = _soundKeys [channel]; // elimina oprirea melodiei (tasta);
Acum, să examinăm cadrul nostru de gestionare a sunetului. Vom compara rezultatul solicitărilor repetate de a reda un sunet cu și fără a utiliza managerul de sunet.
Creați un nou document Flash (duh).
Creați două butoane pe scenă. Puteți să vă desenați și să le convertiți în simboluri sau puteți, ca în cazul meu, să trageți două componente ale butoanelor din panoul Componente. Denumiți-le "boing_btn" și "managedBoing_btn".
Importați sunetul pe care îl vom juca la bibliotecă. Puteți găsi fișierul "Boing.wav" în directorul sursă de exemplu.
În cele din urmă, creați un fișier AS pentru clasa de documente. Codul este destul de simplu, așa că explic doar în comentariu.
pachet import flash.display.Sprite; importul flash.events.MouseEvent; import flash.media.Sound; import sounds.SoundManager; clasa publică BoingPlayer extinde Sprite funcția publică BoingPlayer () // adăugați ascultătorii de clic pentru ambele butoane boing_btn.addEventListener (MouseEvent.CLICK, onBoing); managedBoing_btn.addEventListener (MouseEvent.CLICK, onManagedBoing); // reda sunetul direct prin invocarea metodei Sound.play (). funcția privată onBoing (e: MouseEvent): void var sound: Sound = new Boing (); sound.play (); / / redă sunetul cu managerul de sunet pe funcția privată a melodiei "boing" onManagedBoing (e: MouseEvent): void var sound: sound = new Boing (); SoundManager.play ("boing", sunet);
Au fost efectuate. Apăsați Ctrl + Enter pentru a testa filmul și încercați să faceți rapid clic pe butoane (nu uitați să porniți difuzoarele). Pentru "Boing!" , sunetele multiple se suprapun atunci când au fost redate. În ceea ce privește "Boing-ul gestionat!" butonul care utilizează managerul de sunet, un sunet este forțat să se oprească înainte ca următorul să fie redat, astfel încât nu veți auzi sunetele amestecate împreună.
Milestone Vizualizați-l onlineComenzi, comenzi, comenzi. Este întotdeauna plăcut să vă integrați munca cu cele anterioare, nu? Acum vom integra cadrul de management al sunetului cu cadrul de comandă, împreună cu cadrul de management al scenelor. Din nou, dacă nu sunteți familiarizat cu cadrul de comandă și cu cadrul de gestionare a scenelor, mai bine ar trebui să le verificați în tutorialele mele anterioare (Partea 1, Partea 2) înainte de a merge.
Numele acestei comenzi este destul de explicativ: joacă un sunet cu managerul de sunet.
pachet comands.sounds import commands.Command; import flash.media.Sound; import flash.media.SoundTransform; import sounds.SoundManager; / ** * Această comandă redă un sunet. * / clasa publica PlaySound extinde comanda public var key: String; public var sound: Sound; public var startTime: int; publice var bucle: int; public var transform: SoundTransform; funcția publică PlaySound (cheie: șir, sunet: sunet, startTime: int = 0, bucle: int = 0, transformare: SoundTransform = null) this.key = cheie; this.sound = sunet; this.startTime = startTime; this.loops = bucle; this.transform = transforma; suprascrie funcția protejată execute (): void // spune managerului de sunet să redea sunetul SoundManager.play (key, sound, startTime, bucle, transform); // completează comanda completă ();
Acesta este în esență vărul rău al comenzii anterioare. Această comandă oprește o pistă sonoră utilizând managerul de sunet.
pachet comands.sounds import commands.Command; import sounds.SoundManager; / ** * Această comandă oprește o piesă de sunet corespunzătoare unei chei date. * / clasa publica StopSound extinde comanda public var key: String; funcția publică StopSound (cheie: String) this.key = cheie; suprascrie funcția protejată execute (): void // spune managerului de sunet să oprească piesa sonoră, cât de rău>:] SoundManager.stop (cheie); // completează comanda completă ();
Această comandă încarcă un fișier MP3 extern într-un Sunet obiect. Nu până când încărcarea este completă va fi comanda complet() să fie numită. Acest lucru ne permite să lanțăm ușor comanda împreună cu alte comenzi, fără să ne mai facem griji în privința manipulării finalizării încărcării.
pachete commands.loading import commands.Command; importul flash.events.Event; import flash.media.Sound; import flash.net.URLRequest; / ** * Această comandă încarcă un sunet. * / clasa publica SoundLoad extinde Command public var sound: Sound; public var url: URLRequest; funcția publică SoundLoad (sunet: sunet, url: URLRequest) this.sound = sunet; this.url = url; suprascrie funcția protejată execute (): void // adăugați ascultătorul complet sound.addEventListener (Event.COMPLETE, onComplete); // începe încărcarea sunetului (url); funcția privată onComplete (e: Event): void // elimina ascultătorul complet sound.removeEventListener (Event.COMPLETE, onComplete); // completează comanda completă ();
Integrarea sa încheiat. Pregătiți-vă pentru exemplul nostru final!
În acest exemplu, vom permite utilizatorilor să redea două melodii pe aceeași piesă de sunet. Dacă un sunet urmează să fie redat când piesa sunetului este ocupată, muzica originală este mai întâi decolorată și apoi este redată noua muzică. Îndepărtarea este efectuată de către TweenMaxTo care utilizează în mod intern proprietatea specială volum furnizate de TweenMax din platforma GreenSock Tweening. Cele două muzică sunt fișiere MP3 externe încărcate în timpul run-time.
Rețineți că vom folosi cadrul de gestionare a scenelor. Dacă doriți să vă reîmprospătați memoria, verificați-o aici.
Faceți o copie a fișierului FLA utilizat în exemplul anterior. Redenumiți butoanele la "music1_btn" și "music2_btn". De asemenea, puteți schimba etichetele butoanelor la "Muzică 1" și "Muzică 2". Și adăugați un buton suplimentar numit "stop_btn", care este pentru oprirea muzicii.
Fișierele MP3 pot fi găsite în directorul sursă. Copiați-le în același folder ca fișierul FLA.
Creați un nou fișier AS pentru clasa de documente a noului fișier FLA. Instanțiați un manager de scenă și inițiați-l la o stare de încărcare, unde sunt încărcate cele două fișiere MP3.
pachet import flash.display.Sprite; Scene de import.SceneManager; clasa publică MusicPlayer extinde Sprite funcția publică MusicPlayer () // instanțiează un obiect manager de scenă var sceneManager: SceneManager = nou SceneManager (); // a seta o scenă de încărcare ca scena inițială scenaManager.setScene (noua LoadingScene (aceasta));
Scena de încărcare are două instanțe Sunet obiecte pentru încărcarea celor două fișiere MP3. Butoanele sunt setate invizibile la început și vor fi vizibile din nou când încărcarea este terminată. Când încărcarea este finalizată, scena îi instruiește imediat pe managerul de scenă să treacă la scena principală, așa cum este scris în versiunea superioară onSceneSet () metodă. Mai multe detalii sunt descrise în comentarii.
pachet import commands.Command; comenzi de import.data.RegisterData; import commands.loading.SoundLoad; comenzi de import.ParallelCommand; comenzi de import.SerialCommand; import commands.utils.SetProperties; importul flash.events.Event; import flash.media.Sound; import flash.net.URLRequest; scenarii de import.Scene; clasa publică LoadingScene extinde Scena // o referință la containerul containerului rădăcină document private var container: MusicPlayer; funcția publică LoadingScene (container: MusicPlayer) this.container = container; suprascrie funcția publică createIntroCommand (): Command // crea două obiecte de sunet pentru a încărca cele două fișiere MP3 var music1: Sound = new Sound (); var music2: Sunet = nou Sunet (); var: Command = new ParallelCommand (0, // ascundeți butoanele noi SetProperties (container.music1_btn, alpha: 0, visible: false), noul SetProperties (container.music2_btn, alpha: 0, visible: false) , noi SetProperties (container.stop_btn, alpha: 0, visible: false), // înregistrarea celor două obiecte de sunet la managerul de date noul RegisterData ("music1", music1), new RegisterData ("music2" // începe încărcarea fișierelor MP3 noi SoundLoad (music1, new URLRequest ("Music1.mp3")), noul SoundLoad (music2, new URLRequest ("Music2.mp3"))); comanda retur; suprascrie funcția publică onSceneSet (): void // spune administratorului de scenă să treacă la scena principală imediat după ce intro comanda este completă sceneManager.setScene (nou MainScene (container));
Scena principală aduce înapoi butoanele ascunse și înregistrează reda muzică() și metoda stopMusic () metodă ca ascultători pentru evenimentul de clic. În reda muzică() , se execută o comandă serială dacă pista de sunet "bgm" este ocupată. Comanda prima elimină temporar ascultătorii de clicuri, elimină muzica curentă, oprește melodia curentă, redă muzica nouă pe melodia sonoră "bgm" acum, și apoi adaugă în cele din urmă ascultătorii de clic. stopMusic metoda nu face practic același lucru, doar că nu există o redare muzicală nouă. Această serie complexă de acțiuni se desfășoară numai în câteva linii de cod curat. Destul de curat, huh?
Rețineți că adăugarea și eliminarea ascultătorilor sunt acțiuni comune care sunt prezente în ambele reda muzică() și metoda stopMusic () metodă. Deci, ele sunt considerate ca două proprietăți private, addListeners și removeListeners, inițializată în constructor.
pachet import commands.Command; import commands.events.AddEventListener; import commands.events.RemoveEventListener; import commands.greensock.TweenMaxTo; comenzi de import.ParallelCommand; comenzi de import.SerialCommand; import comands.sounds.PlaySound; import commands.sounds.StopSound; import date.DataManager; import flash.display.Sprite; importul flash.events.Event; importul flash.events.MouseEvent; import flash.media.Sound; import flash.utils.Dictionary; scenarii de import.Scene; import sounds.SoundManager; import sounds.SoundTrack; / ** * Scena principală este afișată când încărcarea este completă. * / clasa publică MainScene extinde Scene // o referință la containerul rădăcină de document private var container: MusicPlayer; privat var btn1: Sprite; privat var btn2: Sprite; privat var btn3: Sprite; private var dataKeys: Dicționar = nou Dicționar (); private var adăugațiListeners: Command; private var eliminareListeners: Command; funcția publică MainScene (container: MusicPlayer) this.container = container; btn1 = container.music1_btn; btn2 = container.music2_btn; btn3 = container.stop_btn; // chei de date utilizate pentru a prelua obiecte de sunet din managerul de date în metoda playMusic () dataKeys [btn1] = "music1"; dateKeys [btn2] = "muzică2"; // această comandă adaugă tuturor ascultătorilor addListeners = new ParallelCommand (0, noul AddEventListener (btn1, MouseEvent.CLICK, playMusic), noul AddEventListener (btn2, MouseEvent.CLICK, playMusic), noul AddEventListener (btn3, MouseEvent.CLICK, stopMusic)) ; // această comandă elimină toți ascultătorii removeListeners = new ParallelCommand (0, new RemoveEventListener (btn1, MouseEvent.CLICK, playMusic), noul RemoveEventListener (btn2, MouseEvent.CLICK, playMusic), noul RemoveEventListener (btn3, MouseEvent.CLICK, stopMusic)) ; suprascrie funcția publică createIntroCommand (): comanda var comanda: Command = new SerialCommand (0, // fade în butoanele noi ParallelCommand (0, noul TweenMaxTo (btn1, 1, autoAlpha: 1, autoAlpha: 1), noul TweenMaxTo (btn3, 1, autoAlpha: 1)), // adauga click ascultatori addListeners); comanda retur; / ** * Redă muzica. * / funcția privată playMusic (e: Event): void // preluarea obiectului de sunet corespunzător unei taste de date var: Sound = DataManager.getData (dataKeys [e.target]); // verificați dacă piesa de sunet BGM este deja redată dacă (SoundManager.isPlaying ("bgm")) // regăsiți melodia de redare var varTrack: SoundTrack = SoundManager.getSoundTrack ("bgm"); Var comandă: Command = new SerialCommand (0, // eliminați temporar clic pe ascultători removeListeners, // decolorarea melodiei curente noi TweenMaxTo (soundtrack.channel, 1, volume: 0), // apoi opriți melodia sonoră noul StopSound ("bgm"), // reda un nou sunet pe aceeași piesă de sunet PlaySound nou ("bgm", muzică, 0, int.MAX_VALUE), // re-adăugați click ascultători addListeners); command.start (); altceva // jucați doar sunetul dacă piesa de sunet este inactivă SoundManager.play ("bgm", muzică, 0, int.MAX_VALUE); / ** * Oprește muzica care se redă în prezent. * / funcția privată stopMusic (e: Event): void // verificați dacă piesa de sunet BGM este deja redată dacă (SoundManager.isPlaying ("bgm")) // regăsiți melodia sonoră de redare var soundTrack: SoundTrack = SoundManager. getSoundTrack ( "BGM"); Var comandă: Command = new SerialCommand (0, // eliminați temporar clic pe ascultători removeListeners, // decolorarea melodiei curente noi TweenMaxTo (soundtrack.channel, 1, volume: 0), // apoi opriți melodia sonoră nou StopSound ("bgm"), // re-adăugați clic pe ascultători addListeners); command.start ();
Suntem gata să testăm filmul. Apăsați CTRL + ENTER pentru al testa. Când faceți clic pe un buton, începe să se redea o muzică. După ce faceți clic pe altul, muzica se estompează, iar apoi una nouă începe de la început.
Milestone Vizualizați-l onlineEste sfarsitul tutorialului, stiu. Dar nu am rezistat să vă arăt asta. Dacă sunteți un jockey de cod, pariez că ați observat deja că există o mulțime de asemănări în reda muzică() și metoda stopMusic () metodă. De ce nu le refacționați într-una singură? Dacă nu sunteți interesat (ă) de acest cod cu versiunea jocky a playerului muzical, puteți să treceți la secțiunea rezumat. În caz contrar, continuați să citiți!
Mai întâi, înlocuiți toate reda muzică și stopMusic în codul sursă cu handleMusic, noul nostru ascultător de evenimente. Apoi, ștergeți reda muzică si stopMusic și adăugați următoarele handleMusic () în clasa principală de scenă.
/ ** * Redă sau oprește muzica. Versiunea de jockey cod. * / funcția privată handleMusic (e: Event): void var muzică: Sound = DataManager.getData (dataKeys [e.target]); dacă (SoundManager.isPlaying ("bgm")) var soundtrack: SoundTrack = SoundManager.getSoundTrack ("bgm"); var comanda: Command = comanda SerialCommand nou (0, removeListeners, new TweenMaxTo (soundtrack.channel, 1, volum: 0), StopSound ("bgm" ) (nou PlaySound ("bgm", muzică, 0, int.MAX_VALUE)): (nou Dummy ()), addListeners); command.start (); altceva if (muzică) SoundManager.play ("bgm", muzică, 0, int.MAX_VALUE);
Veți observa că singura diferență majoră între această metodă și ascultătorii originali este următoarea bucată de cod:
(muzică)? (nou PlaySound ("bgm", muzică, 0, int.MAX_VALUE)): (nou Dummy ()),
Ce naiba este asta oricum? Acesta este de fapt operatorul?: Condițional. Este un operator ternar, adica are nevoie de trei operandi, A, B si C. Declaratia "A? B: C" se evalueaza la B daca A este adevarata, sau C altfel. muzică variabila ar trebui să dețină o referință la a Sunet obiect, astfel încât variabila să fie evaluată la adevărat. Cu toate acestea, dacă destinația expeditorului evenimentului este butonul "stop_btn", variabila conține o valoare nulă, care se evaluează la fals în operatorul ternar. Deci, dacă sunt apăsate cele două butoane muzicale, bucata de cod de mai sus este considerată drept singura linie de cod de mai jos.
PlaySound nou ("bgm", muzică, 0, int.MAX_VALUE)
În caz contrar, dacă butonul de oprire este apăsat, bucata de cod este privită ca o comandă inactivă, care pur și simplu nu face nimic.
nou Dummy ()
Doar un alt lucru de observat. Următorul rând de cod
SoundManager.play ("bgm", muzică, 0, int.MAX_VALUE);
este schimbat la
dacă (muzică) SoundManager.play ("bgm", muzică, 0, int.MAX_VALUE);
Aceasta este pentru tratarea excepției că piesa audio este momentan goală. Dacă înțelegeți fragmentul de cod de mai sus, sunt destul de sigur că vă puteți da seama despre ce este vorba această linie.
Testați filmul apăsând Ctrl + Enter, veți vedea exact același rezultat ca ultimul exemplu. Puteți să o considerați o împlinire a unei vanități codificate de jockey.
În acest tutorial, ați învățat cum să gestionați sunetele cu piese de sunet. O piesă sonoră permite redarea unui singur sunet simultan, fiind ideal pentru a reprezenta o voce sau o muzică de fundal pentru un singur personaj. De asemenea, ați văzut cum să integrați cadrul de gestionare a sunetului cu cadrul de comandă, ceea ce vă oferă o întreținere uriașă și o flexibilitate imensă pentru aplicațiile dvs..
Acesta este sfârșitul tutorialului. Sper ca ti-a placut. Vă mulțumesc foarte mult pentru lectură!