Lydbehandling er svært viktig for mange typer Flash-applikasjoner, for eksempel interaktive nettsteder og spill. Så lenge du vil levere en rik interaktiv opplevelse, vil du kanskje vurdere å bruke lydeffekter og bakgrunnsmusikk. I denne opplæringen presenterer jeg et minimalistisk lydhåndteringsramme som styrer lyder i lydspor. Og jeg vil vise hvordan du integrerer lydrammen med kommandorammen fra mine tidligere opplæringsprogrammer.
Jeg har spilt spill med uheldig lydbehandling, og det forringer brukeropplevelsen. Har du noen gang spilt et spill, si et actionspill hvor karakterens utropstemme spiller før den forrige stemmen slutter, overlapper hverandre? Det er et resultat av dårlig lydadministrasjon: det bør ikke være mer enn én stemme av samme karakter som spiller av gangen. Lydstyringsrammen jeg skal til å dekke, tar seg av dette problemet ved å håndtere lyder med lydspor.
Eksemplene i denne opplæringen gjør bruk av kommandorammen og scenestyringsrammen fra min tidligere opplæring, Tenk i kommandoer (Del 1, Del 2), og eksemplene bruker også databehandlerklassen fra Lasting av data med kommandoer. Jeg anbefaler at du går gjennom disse opplæringene først før du går videre. Du trenger også GreenSock Tweening Platform for å fullføre eksemplene.
Lydsporet vi snakker om her har ingenting å gjøre med spill eller film lydspor. Et lydspor er et imaginært "spor" forbundet med en avspilling av a enkelt lyd. Et enkelt lydspor tillater ikke at mer enn én lyd spiller om gangen. Hvis et lydspor spiller en lyd, sier vi det er okkupert. Hvis en annen lyd skal spilles på et opptatt lydspor, stoppes lyden som spilles av, og den nye spilles av på sporet. Det er derfor rimelig å spille en enkelt tegn stemmer på et enkelt lydspor for å unngå det overlappende problemet som tidligere nevnt. Også i de fleste tilfeller bør det bare være ett spor for bakgrunnsmusikk.
La oss ta en titt på noen konseptuelle figurer. En enkelt applikasjon kan ha flere lydspor.
Hvert lydspor kan inneholde en enkelt spillelyd.
Hvis en lyd skal spilles på et opptatt spor, stoppes den "gamle" lyden først, og deretter spilles den "nye" lyden på sporet.
Lydstyringsrammen består av to klasser, den Soundmanager klasse og SoundTrack klasse. Hvert lydspor tilordnes en unik nøkkelstreng. Et opptatt lydspor underliggende spillelyd er faktisk et innfødt SoundChannel objekt oppnådd fra den native Sound.play () -metoden, og den Soundmanager klassen administrerer lydspor og organiserer avspilling av lyder.
Her er noen raske forhåndsvisninger av bruken av rammen. Følgende kode spiller en ny lyd på et lydspor knyttet til nøkkelstrengen "musikk", hvor MySound er en lyd klasse fra biblioteket.
// spille en lyd på "musikk" sporet SoundManager.play ("music", ny MySound ());
Hvis samme linje av kode utføres igjen før avspillingen er ferdig, stoppes den opprinnelige lyden, og en ny lyd spilles på "musikk" -sporet.
// Stopp den originale lyden på "Musikk" sporet og spill et nytt SoundManager.play ("musikk", ny MySound ());
De SoundManager.stop () Metoden stopper et lydspor tilknyttet en spesifisert nøkkelstreng.
// Stopp "musikk" lydsporet SoundManager.stop ("musikk");
For å forandre lyden, for å justere volumet, må vi få en referanse til et lydspor underliggende lydkanal. Referansen kan fås ved å få tilgang til SoundTrack.channel eiendom.
var kanal: SoundChannel = SoundManager.getSoundTrack ("musikk"). kanal; var transformere: SoundTransform = channel.soundTransform; transform.volume = 0,5; channel.soundTransform = transform;
Nok teori. La oss gå ned til kodingen. Vi skal bruke forskjellige nøkkelstrenger å skille forskjellige lydspor. Her er SoundTrack klassen, som hovedsakelig representerer et nøkkelkanalpar. Detaljer er beskrevet i kommentarene.
pakke lyder import flash.media.SoundChannel; / ** * Et lydspor representerer et nøkkelkanalpar. * / offentlig klasse SoundTrack // skrivebeskyttet nøkkelverdi privat var _key: String; offentlig funksjon få nøkkel (): String return _key; // skrivebeskyttet lydkanalreferanse privat var _kanal: SoundChannel; offentlig funksjon få kanal (): SoundChannel return _channel; offentlig funksjon SoundTrack (nøkkel: String, kanal: SoundChannel) _key = key; _kanalen = kanal; / ** * Stopper den underliggende lydkanalen. * / offentlig funksjonstopp (): void _channel.stop ();
Og her er det Soundmanager klasse. Legg merke til at tastesporforeningen håndteres ved hjelp av Dictionary-klassen. Et spor tømmes automatisk hvis en lyd har nådd sin ende.
pakke lyder import flash.events.Event; importere flash.media.Sound; importere flash.media.SoundChannel; importer flash.media.SoundTransform; importere flash.utils.Dictionary; / ** * Denne klassen lar deg håndtere lyder når det gjelder lydspor. * / offentlig klasse SoundManager // en ordbok som holder spor av alle lydspor privat statisk var _soundTracks: Dictionary = new Dictionary (); // en ordbok som kartlegger en lydkanal til den tilhørende nøkkelen for avspilling av ferdigbehandling av privat statisk var _soundKeys: Dictionary = new Dictionary (); / ** * Spiller en lyd og returnerer et tilsvarende lydsporobjekt. * / offentlig statisk funksjonspille (tast: String, lyd: Lyd, startTime: int = 0, looper: int = 0, transform: SoundTransform = null): SoundTrack // hvis lydsporet er opptatt, stopper gjeldende lydspor hvis (isPlaying (key)) stopper (tast); // spill lyden, opprett en ny lydkanal var kanal: SoundChannel = sound.play (startTime, loops, transform); // lytt etter den komplette hendelsen til lydkanalkanalen.addEventListener (Event.SOUND_COMPLETE, onSoundComplete); // lage et nytt lydspor var soundTrack: SoundTrack = ny SoundTrack (nøkkel, kanal); // legge lydsporet til ordlisten _soundTracks [key] = soundTrack; // legg til kanal-nøkkel kartlegging forhold _soundKeys [channel] = key; return soundtrack; / ** * Returnerer en referanse til lydsporet som svarer til den angitte nøkkelstrengen. * / offentlig statisk funksjon getSoundTrack (nøkkel: String): SoundTrack return _soundTracks [key]; / ** * Bestemmer om et lydspor spiller for øyeblikket. * / offentlig statisk funksjon isPlaying (nøkkel: String): Boolsk return Boolean (_soundTracks [key]); / ** * Stopper et lydspor. * / Statisk statisk funksjonstopp (nøkkel: String): void var soundTrack: SoundTrack = _soundTracks [key]; // Sjekk om lydsporet eksisterer hvis (soundtrack) // stopp lydsporet soundTrack.stop (); // og fjern det fra ordlisten slett _soundTracks [key]; // sammen med kanalnøkkelrelasjonen slett _soundKeys [soundTrack.channel]; / ** * Fjerner et lydspor når lydavspillingen er fullført * / privat statisk funksjon onSoundComplete (e: Event): void // kaster hendelsesforsendelsen til et lydkanalobjekt var kanal: SoundChannel = SoundChannel (e. mål); // fjern hendelseslytteren channel.removeEventListener (Event.SOUND_COMPLETE, onSoundComplete); // trekk ut den tilsvarende nøkkelen var-tasten: String = _soundKeys [channel]; // fjern lydsporet stopp (tast);
La oss nå teste våre rammeverk for lydstyring. Vi skal sammenligne utfallet av gjentatte forespørsler for å spille en lyd med og uten å bruke lydbehandleren.
Opprett et nytt Flash-dokument (duh).
Lag to knapper på scenen. Du kan tegne din egen og konvertere dem til symboler, eller du kan, som i tilfelle, trekke to knappekomponenter fra komponentpanelet. Gi dem navnet "boing_btn" og "managedBoing_btn".
Importer lyden vi skal spille på biblioteket. Du kan finne filen "Boing.wav" i eksempelkildemappen.
Endelig opprett en AS-fil for dokumentklassen. Koden er ganske enkel, så jeg bare forklarer alt i kommentarene.
pakke import flash.display.Sprite; importer flash.events.MouseEvent; importere flash.media.Sound; importere sounds.SoundManager; offentlig klasse BoingPlayer utvider Sprite offentlig funksjon BoingPlayer () // legg til klikk lyttere for begge knappene boing_btn.addEventListener (MouseEvent.CLICK, onBoing); managedBoing_btn.addEventListener (MouseEvent.CLICK, onManagedBoing); // spille lyden direkte ved å aktivere Sound.play () -metoden. privat funksjon onBoing (e: MouseEvent): void var lyd: Sound = new Boing (); sound.play (); // spille lyden med lydbehandleren på "Boing" lydspor privat funksjon onManagedBoing (e: MouseEvent): void var lyd: Lyd = nytt Boing (); SoundManager.play ("boing", lyd);
Vi er ferdige. Trykk Ctrl + Enter for å teste filmen, og prøv raskt å klikke på knappene (husk å slå på høyttalerne). For "Boing!" knappen, flere lyder overlapper når de spilles. Som for "Managed Boing!" knappen, som bruker lydstyreren, må en lyd tvinges til å stoppe før den neste spilles, slik at du ikke hører lydene sammenblandet sammen.
Milestone Se det på nettetKommandoer, kommandoer, kommandoer. Det er alltid hyggelig å integrere arbeidet med de forrige, ikke sant? Nå skal vi integrere lydstyringsrammen med kommandorammen, sammen med scenestyringsrammen. Igjen, hvis du ikke er kjent med kommandorammen og scenestyringsrammen, bør du sjekke dem bedre ut i mine tidligere opplæringsoppgaver (del 1, del 2) før du går videre.
Navnet på denne kommandoen er ganske selvforklarende: det spiller en lyd med lydbehandleren.
pakke kommandoer.sounds Import Commands.Command; importere flash.media.Sound; importer flash.media.SoundTransform; importere sounds.SoundManager; / ** * Denne kommandoen spiller en lyd. * / offentlig klasse PlaySound utvider kommando public var-nøkkel: String; offentlig var lyd: lyd; offentlig var starttid: int; offentlige var looper: int; offentlig var transformasjon: SoundTransform; offentlig funksjon PlaySound (nøkkel: String, lyd: Lyd, startTime: int = 0, looper: int = 0, transform: SoundTransform = null) this.key = key; this.sound = lyd; this.startTime = startTime; this.loops = loops; this.transform = transform; overstyr beskyttet funksjon (): void // fortell lydbehandleren for å spille av lyden SoundManager.play (tast, lyd, startTime, loops, transform); // fullfør kommandoen fullstendig ();
Dette er i utgangspunktet den onde fetteren til den forrige kommandoen. Denne kommandoen stopper et lydspor ved hjelp av lydbehandleren.
pakke kommandoer.sounds Import Commands.Command; importere sounds.SoundManager; / ** * Denne kommandoen stopper et lydspor som svarer til en gitt tast. * / offentlig klasse StopSound utvider kommando public var-nøkkel: String; offentlig funksjon StopSound (nøkkel: String) this.key = key; overstyr beskyttet funksjon utfør (): void // fortell lydbehandleren for å stoppe lydsporet, hvor ondt>:] SoundManager.stop (key); // fullfør kommandoen fullstendig ();
Denne kommandoen laster en ekstern MP3-fil til a Lyd gjenstand. Ikke før lastingen er fullført, vil kommandoen være fullstendig() metode kalles. Dette gjør at vi enkelt kan kjede sammen kommandoen med andre kommandoer, uten å måtte bekymre deg om å håndtere lasting.
pakke kommandoer.loading import kommandoer.kommando; importere flash.events.Event; importere flash.media.Sound; importere flash.net.URLRequest; / ** * Denne kommandoen laster en lyd. * / offentlig klasse SoundLoad utvider kommando public var lyd: lyd; offentlig var url: URLRequest; offentlig funksjon SoundLoad (lyd: lyd, url: URLRequest) this.sound = lyd; this.url = url; tilsidesatte beskyttet funksjon utfør (): void // legg til hele lytteren sound.addEventListener (Event.COMPLETE, onComplete); // begynn å laste sound.load (url); privat funksjon onComplete (e: Event): void // fjern den komplette lytteren sound.removeEventListener (Event.COMPLETE, onComplete); // fullfør kommandoen fullstendig ();
Integrasjonen er fullført. Bli forberedt på vårt siste eksempel!
I dette eksemplet skal vi tillate brukere å spille to musikk på samme lydspor. Hvis en lyd skal spilles når lydsporet er opptatt, blir den opprinnelige musikken først bleknet, og deretter spilles den nye musikken. Fading-out håndteres av TweenMaxTo kommando, som internt bruker den spesielle egenskapen volum levert av TweenMax klasse fra GreenSock Tweening Platform. De to musikene er eksterne MP3-filer lastet i løpet av kjøretiden.
Legg merke til at vi skal bruke scenestyringsrammen. Hvis du vil oppdatere minnet ditt, kan du sjekke det her.
Lag en kopi av FLA-filen som ble brukt i forrige eksempel. Gi nytt navn til knappene til "music1_btn" og "music2_btn". Du kan også endre knappetikettene til "Musikk 1" og "Musikk 2". Og legg til en ekstra knapp med navnet "stop_btn", som er for å stoppe musikken.
MP3-filene finnes i kildemappen. Kopier dem til samme mappe som FLA-filen.
Opprett en ny AS-fil for dokumentklassen til den nye FLA-filen. Instantiate en scene manager, og initialiser den til en lastetilstand, der de to MP3-filene er lastet.
pakke import flash.display.Sprite; importere scener.SceneManager; offentlig klasse MusicPlayer utvider Sprite offentlig funksjon MusicPlayer () // instantiate en scene manager objekt var sceneManager: SceneManager = new SceneManager (); // angi en laste scene som den første scenen sceneManager.setScene (nytt LoadingScene (dette));
Lasting scenen instantiates to Lyd objekter for å laste de to MP3-filene. Knappene er satt usynlige i begynnelsen, og vil bli satt synlige igjen når lastingen er ferdig. Når lastingen er fullført, instruerer scenen straks scenemanageren til å flytte til hovedstedet, som skrevet i overskriften onSceneSet () metode. Ytterligere detaljer er beskrevet i kommentarene.
pakke import kommandoer.kommando; importere kommandoer.data.RegisterData; importere kommandoer.loading.SoundLoad; importere kommandoer.ParallelCommand; importere kommandoer.SerialCommand; importere kommandoer.utils.SetProperties; importere flash.events.Event; importere flash.media.Sound; importere flash.net.URLRequest; importere scener.Scene; offentlig klasse LoadingScene utvider Scene // en referanse til dokumentroten beholder private var container: MusicPlayer; offentlig funksjon LoadingScene (container: MusicPlayer) this.container = container; overstyr offentlig funksjon createIntroCommand (): Command // opprett to lydobjekter for å laste de to MP3-filene var music1: Sound = new Sound (); var music2: Sound = new Sound (); var command: Command = new ParallelCommand (0, // skjul knappene nye SetProperties (container.music1_btn, ala: 0, synlig: false), nye SetProperties (container.music2_btn, ala: 0, synlig: false) , nye SetProperties (container.stop_btn, alpha: 0, visible: false), // registrer de to lydobjektene til datastyreren New RegisterData ("music1", music1), ny RegisterData ("music2", music2) // begynn lasting av MP3-filene nytt SoundLoad (music1, ny URLRequest ("Music1.mp3")), ny SoundLoad (music2, ny URLRequest ("Music2.mp3"))); returnere kommando; overstyr offentlig funksjon onSceneSet (): void // fortell scene manager for å bytte til hovedspillet direkte etter at intro kommandoen er fullført sceneManager.setScene (new MainScene (container));
Hovedsporet bringer de skjulte knappene tilbake til synlig, og registrerer spille musikk() metode og stopMusic () metode som lyttere for klikkhendelse. I spille musikk() Metode, en seriell kommando blir utført hvis "bgm" lydspor er opptatt. Kommandoen fjerner først klikklyttene, fjerner gjeldende musikk, stopper gjeldende musikk, spiller den nye musikken på det nåværende "bgm" lydsporet, og til slutt legger du til klikklyttene. De stopMusic Metoden gjør i utgangspunktet det samme, bare at det ikke er noen ny musikkavspilling. Denne komplekse rekke handlinger utføres i bare noen få linjer med ren kode. Ganske pent, huh?
Merk at legge til og fjerne lytterne er vanlige handlinger som er tilstede i begge spille musikk() metode og stopMusic () metode. Så de er fakturert som to private eiendommer, addListeners og removeListeners, initialisert i konstruktøren.
pakke import kommandoer.kommando; importere kommandoer.events.AddEventListener; importere kommandoer.events.RemoveEventListener; importere kommandoer.greensock.TweenMaxTo; importere kommandoer.ParallelCommand; importere kommandoer.SerialCommand; importere kommandoer.sounds.PlaySound; importere kommandoer.sounds.StopSound; importer data.DataManager; importer flash.display.Sprite; importere flash.events.Event; importer flash.events.MouseEvent; importere flash.media.Sound; importere flash.utils.Dictionary; importere scener.Scene; importere sounds.SoundManager; importere lyder.SoundTrack; / ** * Hovedbildet vises når lastingen er fullført. * / offentlig klasse MainScene utvider Scene // en referanse til dokumentroten beholder private var container: MusicPlayer; private var btn1: Sprite; private var btn2: Sprite; private var btn3: Sprite; private var dataKeys: Dictionary = new Dictionary (); private var addListeners: Command; privat var removeListeners: Command; offentlig funksjon MainScene (container: MusicPlayer) this.container = container; btn1 = container.music1_btn; btn2 = container.music2_btn; btn3 = container.stop_btn; // datataster som brukes til å hente lydobjekter fra datalageret i playMusic () metoden dataKeys [btn1] = "music1"; dataKeys [btn2] = "music2"; // denne kommandoen legger til alle lyttere addListeners = ny ParallelCommand (0, ny AddEventListener (btn1, MouseEvent.CLICK, playMusic), ny AddEventListener (btn2, MouseEvent.CLICK, playMusic), ny AddEventListener (btn3, MouseEvent.CLICK, stopMusic)) ; // denne kommandoen fjerner alle lyttere removeListeners = ny ParallelCommand (0, ny RemoveEventListener (btn1, MouseEvent.CLICK, playMusic), ny RemoveEventListener (btn2, MouseEvent.CLICK, playMusic), ny RemoveEventListener (btn3, MouseEvent.CLICK, stopMusic)) ; overstyr offentlig funksjon createIntroCommand (): Command var kommando: Kommando = ny SerialCommand (0, // fade i knappene nye ParallelCommand (0, ny TweenMaxTo (btn1, 1, autoAlpha: 1), ny TweenMaxTo (btn2, 1, autoAlpha: 1), ny TweenMaxTo (btn3, 1, autoAlpha: 1)), // legge til klikklyttere addListeners); returnere kommando; / ** * Spiller av musikken. * / privat funksjon playMusic (e: Event): void // hente lydobjektet som svarer til en datatast var musikk: Sound = DataManager.getData (dataKeys [e.target]); // Sjekk om BGM lydsporet allerede spiller hvis (SoundManager.isPlaying ("bgm")) // hente lydsporet var soundTrack: SoundTrack = SoundManager.getSoundTrack ("bgm"); var kommandoen: Command = new SerialCommand (0, // midlertidig fjern klikklyttere removeListeners, // fade ut det nåværende lydsporet nytt TweenMaxTo (soundTrack.channel, 1, volume: 0), // og deretter stoppe lydsporet ny StopSound ("bgm"), // spill en ny lyd på samme lydspor, nytt PlaySound ("bgm", musikk, 0, int.MAX_VALUE), // re-add click listeners addListeners); command.start (); ellers // bare spill lyden hvis lydsporet er tomt SoundManager.play ("bgm", musikk, 0, int.MAX_VALUE); / ** * Stopper musikken som spilles for øyeblikket. * / Private Function StopMusic (e: Event): void // Sjekk om BGM lydsporet allerede spiller hvis (SoundManager.isPlaying ("bgm")) // hente lydsporet var soundTrack: SoundTrack = SoundManager. getSoundTrack ( "BGM"); var kommandoen: Command = new SerialCommand (0, // midlertidig fjern klikklyttere removeListeners, // fade ut det nåværende lydsporet nytt TweenMaxTo (soundTrack.channel, 1, volume: 0), // og deretter stoppe lydsporet ny StopSound ("bgm"), // re-add click listeners addListeners); command.start ();
Vi er klare til å teste filmen. Trykk CTRL + ENTER for å teste den. Når du klikker på en knapp, begynner en musikk å spille. Etter å ha klikket på en annen, begynner musikken og begynner en ny fra begynnelsen.
Milestone Se det på nettetDet er slutten på opplæringen, vet jeg. Men jeg kunne ikke motstå fra å vise dette til deg. Hvis du er en kodejockey, satser jeg på at du allerede har lagt merke til at det er mange likheter i spille musikk() metode og stopMusic () metode. Hvorfor ikke refactor dem til en enkelt? Hvis du ikke er interessert i denne koden jocky-versjonen av musikkspilleren, kan du hoppe over til sammendragsseksjonen. Ellers bare fortsett å lese!
Først erstatt alle spille musikk og stopMusic i kildekoden med handleMusic, vår nye hendelseslytter. Deretter slett du spille musikk og stopMusic metode, og legg til følgende handleMusic () metode i hovedscenen.
/ ** * Spiller eller stopper musikken. Code jockey versjon. * / Private Function handleMusic (e: Event): void var musikk: Sound = DataManager.getData (dataKeys [e.target]); hvis (SoundManager.isPlaying ("bgm")) var soundTrack: SoundTrack = SoundManager.getSoundTrack ("bgm"); var command: Command = new SerialCommand (0, removeListeners, new TweenMaxTo (soundTrack.channel, 1, volum: 0), ny StopSound ("bgm"), // avgjøre om vi skal spille en annen musikk )? (Ny PlaySound ("bgm", musikk, 0, int.MAX_VALUE)): (ny Dummy ()), addListeners); command.start (); ellers hvis (musikk) SoundManager.play ("bgm", musikk, 0, int.MAX_VALUE);
Du vil merke at den eneste store forskjellen mellom denne metoden og de opprinnelige lytterne, er følgende del av koden:
(musikk)? (ny PlaySound ("bgm", musikk, 0, int.MAX_VALUE)): (ny Dummy ()),
Hva i helvete er dette likevel? Dette er faktisk den?: Betinget operatør. Det er en ternær operatør, noe som betyr at det krever tre operander, A, B og C. Erklæringen "A? B: C" vurderer til B hvis A er sant, eller C ellers. De musikk variabel skal inneholde en referanse til a Lyd objekt, slik at variabelen vurderes til sann. Men hvis hendelsesforsendelsesmålet er "stop_btn" -knappen, inneholder variabelen en nullverdi som vurderer til falsk i den ternære operatøren. Så, hvis de to musikknappene klikkes, blir koden ovenfor angitt som den enkle linjen med kode nedenfor.
ny PlaySound ("bgm", musikk, 0, int.MAX_VALUE)
Ellers, hvis stoppeknappen klikkes, betraktes kodebrikken som en dummy-kommando, som ganske enkelt ikke gjør noe.
Ny Dummy ()
Bare en annen ting å legge merke til. Følgende linje av kode
SoundManager.play ("bgm", musikk, 0, int.MAX_VALUE);
er endret til
hvis (musikk) SoundManager.play ("bgm", musikk, 0, int.MAX_VALUE);
Dette er for å håndtere unntaket at lydsporet er tomt. Hvis du kan forstå kodeksen ovenfor, er jeg ganske sikker på at du kan finne ut hva denne linjen handler om.
Test filmen ved å trykke Ctrl + Enter, du vil se nøyaktig samme resultat som det siste eksemplet. Du kan betrakte det som en oppfyllelse av en kodejockeyens kodende forfengelighet.
I denne opplæringen har du lært hvordan du håndterer lyder med lydspor. Ett lydspor tillater bare én lyd av gangen, derfor ideell til å representere en enkelt tegns stemme eller bakgrunnsmusikk. Du har også sett hvordan du integrerer lydstyringsrammen med kommandorammen, som gir deg et stort vedlikeholds- og fleksibilitetsforbedring på applikasjonene dine..
Dette er slutten av opplæringen. Jeg håper du likte det. Tusen takk for lesing!