1.AS3中声音控制相关类
在ActionScript中控制声音之前,需要先将声音信息加载到Flash Player中。可以使用四种方法将音频数据加载到Flash Player中,以便通过ActionScript对其进行使用:
ü将外部声音文件(如mp3文件)加载到SWF中(方法一是本文要用的,背景音乐及游戏中的按钮声效都是单独的mp3文件,然后加载到游戏中);
ü在创建SWF文件时将声音信息直接嵌入到其中(前面我们讲到的,创建SWF文件时将声音信息直接嵌入到其中,我们可以将所有的声效放嵌入到一个swf中,并将所有声效放到一个时间轴上,播放的时候跳到相应帧,这样可以保证每次只播放一个声效。);
ü使用连接到用户计算机上的麦克风来获取音频输入;
ü访问从服务器流式传输的声音数据。
从外部声音文件加载声音数据时,可以在仍加载其余声音数据的同时开始回放声音文件的开头部分。虽然可以使用各种不同的声音文件格式对数字音频进行编码,但是ActionScript 3.0和Flash Player支持以mp3格式存储的声音文件。它们不能直接加载或播放其它格式的声音文件,如WAV或AIFF。
在ActionScript中处理声音时,可能会使用flash.media包中的某些类。通过使用Sound类,您可以加载声音文件并开始回放以获取对音频信息的访问。开始播放声音后,Flash Player可为您提供对SoundChannel对象的访问。由于已加载的音频文件只能是在用户计算机上播放的几种声音之一,因此,所播放的每种单独的声音使用其自己的SoundChannel对象;混合在一起的所有SoundChannel对象的组合输出是实际通过计算机扬声器播放的声音。可以使用此SoundChannel实例来控制声音的属性以及将其停止回放。最后,如果要控制组合音频,可以通过SoundMixer类对混合输出进行控制。
ActionScript 3.0声音体系结构使用flash.media包中的以下类。
类
描述
flash.media.Sound
Sound类处理声音加载、管理基本声音属性以及启动声音播放。
flash.media.SoundChannel
当应用程序播放Sound对象时,将创建一个新的SoundChannel对象来控制回放。SoundChannel对象控制声音的左和右回放声道的音量。播放的每种声音具有其自己的SoundChannel对象。
flash.media.SoundLoaderContext
SoundLoaderContext类指定在加载声音时使用的缓冲秒数,以及Flash Player在加载文件时是否从服务器中查找跨域策略文件。SoundLoaderContext对象用作Sound.load()方法的参数。
flash.media.SoundMixer
SoundMixer类控制与应用程序中的所有声音有关的回放和安全属性。实际上,可通过一个通用SoundMixer对象将多个声道混合在一起,因此,该SoundMixer对象中的属性值将影响当前播放的所有SoundChannel对象。
flash.media.SoundTransform
SoundTransform类包含控制音量和声相的值。可以将SoundTransform对象应用于单个SoundChannel对象、全局SoundMixer对象或Microphone对象等。
flash.media.ID3Info
ID3Info对象包含一些属性,它们表示通常存储在mp3声音文件中的ID3元数据信息。
flash.media.Microphone
Microphone类表示连接到用户计算机上的麦克风或其它声音输入设备。可以将来自麦克风的音频输入传送到本地扬声器或发送到远程服务器。Microphone对象控制其自己的声音流的增益、采样率以及其它特性。
加载和播放的每种声音需要其自己的Sound类和SoundChannel类的实例。然后,全局SoundMixer类在回放期间将来自多个SoundChannel实例的输出混合在一起。另外,Sound、SoundChannel和SoundMixer类不能用于从麦克风或流媒体服务器(如Flash Media Server)中获取的声音数据。
单例模式(Singleton)单例模式(也叫单件模式)的作用就是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个。一般编程语言中,单例模式有以下两个特点:
ü单例模式使类在程序生命周期的任何时刻都只有一个实例
ü单例的构造函数是私有的,这样可以阻止调用构造函数生成实例,必须通过getInstance()接口得到这个单例类的实例
然而由于AS3中的构造函数必须是public,所以不可以像其它编程语言一样,将构造函数置为private来阻止调用构造函数生成实例。这样是不是说as3天生就不支持单例模式了呢?很多人这样来实现单例模式:
protected static var instance : Singleton; public function Singleton() { if (instance != null) { //throw new Error("只能用getInstance()来获取实例"); } } public static function getInstance() : Singleton { if (instance == null) { instance = new Singleton(); } return instance; }
想阻止构造函数在类的外部被调用还有另外一种方法,使用as3中的包外类。包外类:只能被包中的类访问,它属于当前类的私有类。此包外类对外不可见。定义位置为package{ }外。可以定义一个或者多个class类。但类名不能与文件同名。具体如何使用包外类实现单例模式,见下面小节。
注意:flash是单线程模式的,不用考虑线程安全问题。
有了上面的基础,下面可以游戏中的声音管理类了,声音管理类设计成一个单例类。通过两个声道SoundChannel分别播放背景音乐、声效;SoundLoaderContext类设置MP3文件加载上下文;Sound类处理声音加载、管理基本声音属性以及启动声音播放。完整的代码如下:
package utils { import flash.events.EventDispatcher; import flash.media.Sound; import flash.media.SoundChannel; import flash.media.SoundLoaderContext; import utils.QAssetManager; /** * 游戏中背景音乐、声效管理类: * 声音的播放,即将Sound.play()方法赋值给SoundChannel实例就可以开始播放歌曲了。 * 如果使用Sound和SoundChannel装载和播放另一个mp3时,这个声音也会开始播放,因为没有对实例做任何限制,因此两个实例都可以正常播放。 * 因此必须检测是否对SoundChannel实例赋值了,如果它是null,脚本继续执行并播放选择的文件;如果它不是null,先停止当前正在播放的文件 * 后再装载和播放另一个mp3文件。这样就可以保证某一时刻只播放一个文件了。 * * 游戏中声音有2两种: * 1. 背景音乐:循环播放一直存在 * 2. 按钮音效等:点击才触发,这种声音任何时候只播放一个,如果两个瞬间点击多个按钮,只播放最后一个声音 * @author tyler */ public class GameSound extends EventDispatcher { //public static const SOUND_BACKGROUND:int = 0; protected var m_bkmusicChannel:SoundChannel; protected var m_soundChannel:SoundChannel; //单态实例 protected static var m_instance:GameSound; //单态构造函数 public function GameSound(pvt:PrivateClass) { } //单态构造方法 public static function getInstance():GameSound { if (m_instance == null) { m_instance = new GameSound(new PrivateClass()); } return m_instance; } //开始播放背景音乐 public function bkmusicPlay(music:String):void { bkmusicStop(); QAssetManager.getInstance().getAssets( music, {context: new SoundLoaderContext() }, function(content:Object):void { m_bkmusicChannel = (content as Sound).play(); }); } //停止播放背景音乐 public function bkmusicStop():void { if (m_bkmusicChannel != null) { m_bkmusicChannel.stop(); } } //播放音效 public function soundPlay(sound:String):void { soundStop(); QAssetManager.getInstance().getAssets( sound, {context: new SoundLoaderContext() }, function(context:Object):void { m_soundChannel = (context as Sound).play(); }); } //停止音效 public function soundStop():void { if (m_soundChannel != null) { m_soundChannel.stop(); } } } } class PrivateClass { public function PrivateClass() { trace("包外类,用于实现单例"); } }
播放背景音乐的时候只需要这样调用:GameSound.getInstance().bkmusicPlay(url);播放其它声效时:GameSound.getInstance().soundPlay(url)。停止的话调用相应接口即可。
原文来自:技术之家
网友评论