游戏中的声音管理

好久没有写教程了,自结婚到现在差不多有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首歌…结果是怎样呢?多首歌曲同时播放,音乐变成了噪音。

musicPlayer

怎么解决这个问题呢?用一个播放器播放音乐,也就是用一个SoundChannel播放Sound对象。我们可以将Sound.play()返回的SoundChannel对象保存起来,每次都用这个SoundChannel停止当前声音的播放.

musicPlayer2

点击下面的按钮试试看,每次点击时,都会停止前一次播放

[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();

源文件下载地址:

http://vdisk.weibo.com/s/irzl9N4hx0qE

联系作者

公众号:拉小登 | 微博:拉登Dony | B站:拉小登Excel

One Reply to “游戏中的声音管理”

回复 TKCB

您的电子邮箱地址不会被公开。 必填项已用 * 标注