游戏中的声音管理
好久没有写教程了,自结婚到现在差不多有3个月了,突然又提笔,感觉生疏了很多。也可能是要求过于完美,总想做一个好看的demo,所以这个简单的教程,写了有半个多月。好了,闲话少说,上教程。
先看看效果,在下面的示例中,点击”单轨/多轨”按钮进行音乐channel的控制,点击下面的music按钮,播放对应的音乐。
[swfobject]1140[/swfobject]
这个demo用到了《The Essential guide to Flash games》中的SoundManager类,它并不是一个像Tweenlite那样众所周知的第三方类库,重点是我们要学会控制声音的方法。它是游戏中统一管理声音、音效的一个类,完整的代码如下:
package { import flash.events.SampleDataEvent; import flash.media.Sound; import flash.media.SoundChannel; import flash.utils.getTimer; public class SoundManager { private var soundsList:Array; private var soundChannelsList:Array; private var soundTrackChannel:SoundChannel; public function SoundManager() { soundsList= new Array(); soundChannelsList = new Array(); } public function addSound(soundName:String,sound:Sound):void{ soundsList[soundName]=sound; } public function planSound(soundName:String, isSoundTrack:Boolean=false,loops:int=1):void{ var tempSound:Sound = soundsList[soundName]; if(isSoundTrack){ if(soundTrackChannel!=null){ soundTrackChannel.stop(); } soundTrackChannel= tempSound.play(); }else { //保存soundName音乐的soundChannel的引用 soundChannelsList[soundName]=tempSound.play(); } } public function stopSound(soundName:String,isSoundTrack:Boolean=false):void{ if(isSoundTrack){ if(soundTrackChannel!=null) soundTrackChannel.stop(); }else { //停止soundName对应的soundChannel的播放 soundChannelsList[soundName].stop(); } } public function stopAllSounds():void{ if(soundTrackChannel!=null) soundTrackChannel.stop(); for each(var s:SoundChannel in soundChannelsList){ s.stop(); } } } }
代码很简单,有编程经验的你如果已经看明白,可以忽略此教程。
说到声音,要从Flash中控制声音的Sound、SoundChannel等类说起。正常情况下,如果说到添加音乐,比如要播放一首歌的话,只要创建一个Sound对象,然后执行play()方法,就可以听到声音了。点击下面的按钮播放声音:
[swfobject]1142[/swfobject]
package { import com.bit101.components.PushButton; import flash.display.MovieClip; import flash.events.MouseEvent; import flash.media.Sound; /** * ... * @author ladeng6666 */ public class Demo1 extends MovieClip { public function Demo1() { var button:PushButton = new PushButton(this, 0, 0, "Play Music", onBtnClick); button.x = stage.stageWidth / 2 - button.width / 2; button.y = stage.stageHeight / 2; } private function onBtnClick(e:MouseEvent):void { var sound:Sound = new Music1(); sound.play(); } } }
看上去好像没有问题,但是多点几次按钮,你会发现问题,声音会再次播放,第三次播放…而不是重新播放这首歌曲。
要解决这个问题,就要弄清楚Sound和SoundChannel的关系,打个比方,平时听音乐,我们都用QQ音乐、千千静听、酷狗等播放器。Sound就好比是我们要播放的MP3文件,而SoundChannel就是QQ音乐、千千静听等播放器。按照前面的做法,每次播放音乐时,我们都会new一个Sound对象出来,在我们执行了play()方法后,Flash会自动为每个Sound对象衍生出一个SoundChannel对象,这就好比我们用QQ音乐打开了第一首MP3,然后又用千千静听打开了第2首歌,又用酷狗音乐盒打开了第3首歌…结果是怎样呢?多首歌曲同时播放,音乐变成了噪音。
怎么解决这个问题呢?用一个播放器播放音乐,也就是用一个SoundChannel播放Sound对象。我们可以将Sound.play()返回的SoundChannel对象保存起来,每次都用这个SoundChannel停止当前声音的播放.
点击下面的按钮试试看,每次点击时,都会停止前一次播放
[swfobject]1146[/swfobject]
代码如下:
package { import com.bit101.components.PushButton; import flash.display.MovieClip; import flash.events.MouseEvent; import flash.media.Sound; import flash.media.SoundChannel; /** * ... * @author ladeng6666 */ public class Demo2 extends MovieClip { private var soundChannel:SoundChannel; public function Demo2() { var button:PushButton = new PushButton(this, 0, 0, "Play Music", onBtnClick); button.x = stage.stageWidth / 2 - button.width / 2; button.y = stage.stageHeight / 2; } private function onBtnClick(e:MouseEvent):void { if (soundChannel != null) { soundChannel.stop(); } var sound:Sound = new Music1(); soundChannel=sound.play(); } } }
这是模拟音乐播放器的做法,但是在游戏中,会有多个声音同时播放的情况,这时候我们要管理的重点是,可以有效的控制每个声音的播放和暂停,也就示例中多轨的播放情况。这并不是什么难事,为每个声音指定专用的SoundChannel,并保存对这些SoundChannel的引用,然后需要播放声音时,我们找出其对应的SoundChannel对象,执行该对象的play()方法,进行播放。代码如下:
//保存soundName音乐的soundChannel的引用 soundChannelsList[soundName]=tempSound.play(); //停止soundName对应的soundChannel的播放 soundChannelsList[soundName].stop();
源文件下载地址:
联系作者
哈哈