Android游戏开发学习(7)--MediaPlayer与SoundPool详解与应用
MediaPlayer:使用简单,适合做游戏的背景音乐,资源占用量较高、延迟时间较长、不支持多个音频同时播放等。
音乐文件正常播放完毕,而又没有设置循环播放的话就进入该状态,并会触发OnCompletionListener的onCompletion()方法。
此时可以调用start()方法重新从头播放文件,也可以stop()停止MediaPlayer,或者也可以seekTo()来重新定位播放位置,播放下一首音乐
如果你设置了循环播放 mp.setLooping(true); 的话,那么永远都不会监听到播放完成的状态!!!!这里一定要注意!
SoundPool:适合播放游戏中的特效,如技能声音,怪物叫声等时间很短的音乐
1. SoundPool最大只能申请1M的内存空间。
2. 音频格式建议使用OGG格式。使用WAV格式的音频文件存放游戏音效,经过反复测试,在音效播放间隔较短的情况下会出现异常关闭的情况
3.在使用SoundPool播放音频的时候,如果在初始化中就调用播放函数进行播放音乐那么根本没有声音,不是因为没有执行,而是 SoundPool需要一准备时间
----------------------------------------------------------------------------------------------------------------
下面以实例说明:
首先看效果
你不停的点击在MediaPlayer与SoundPool发射子弹是会发现,SoundPool的更适合做音乐特效,MediaPlayer适合做背景音乐。
其他不做解释:自己下载源码,亲自运行,然后打开背景音乐,不停的点击右侧的6个发射按钮,慢慢体验,你会明白的。。。
在看代码
package dk.game; import java.io.IOException; import android.app.Activity; import android.content.Context; import android.content.pm.ActivityInfo; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.SoundPool; import android.os.Bundle; import android.view.View; import android.view.Window; import android.view.WindowManager; public class MusicTestActivity extends Activity { private MediaPlayer mediaPlayerBg; private MediaPlayer mediaPlayerTeXiao1; private MediaPlayer mediaPlayerTeXiao2; private MediaPlayer mediaPlayerTeXiao3; private SoundPool soundPool; private AudioManager am; private int maxVol; private int loadId1,loadId2,loadId3; private Context context; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //全屏显示 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //去掉标题 requestWindowFeature(Window.FEATURE_NO_TITLE); //横屏 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); setContentView(R.layout.main); //获得当前的上下文 context=getApplicationContext(); mediaPlayerBg=MediaPlayer.create(context, R.raw.bgmusic); //背景音乐循环播放 mediaPlayerBg.setLooping(true); mediaPlayerTeXiao1=MediaPlayer.create(context, R.raw.shoot1); mediaPlayerTeXiao2=MediaPlayer.create(context, R.raw.shoot2); mediaPlayerTeXiao3=MediaPlayer.create(context, R.raw.shoot3); //SoundPool的初始化 /* * 第一个参数是:同时播放特效的数量 * 第二个参数是:音乐播放的音频流 * 第三个参数是:音乐的质量 */ soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 100); loadId1=soundPool.load(context, R.raw.shoot1, 1); loadId2=soundPool.load(context, R.raw.shoot2, 1); loadId3=soundPool.load(context, R.raw.shoot3, 1); /* * Android OS中,如果你去按手机上的调节音量的按钮,会分两种情况, * 一种是调整手机本身的铃声音量,一种是调整游戏,软件,音乐播放的音量 * 当我们在游戏中的时候 ,总是想调整游戏的音量而不是手机的铃声音量, * 可是烦人的问题又来了,我在开发中发现,只有游戏中有声音在播放的时候 * ,你才能去调整游戏的音量,否则就是手机的音量,有没有办法让手机只要是 * 在运行游戏的状态就只调整游戏的音量呢?试试下面这段代码吧! * setVolumeControlStream(AudioManager.STREAM_MUSIC); * 设定调整音量为媒体音量,当暂停播放的时候调整音量就不会再默认调整铃声音量了 */ setVolumeControlStream(AudioManager.STREAM_MUSIC); // 获取音频服务然后强转成一个音频管理器,后面方便用来控制音量大小用 am = (AudioManager)getSystemService(Context.AUDIO_SERVICE); // 获取最大音量值(15最大! .不是100!) maxVol = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); } /** * 播放背景音乐 * @param view */ public void startBgMusic(View view){ if(mediaPlayerBg != null) { mediaPlayerBg.stop(); } try { mediaPlayerBg.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } mediaPlayerBg.start(); } /** * 停止播放背景音乐 * @param view */ public void stopBgMusic(View view){ mediaPlayerBg.stop(); } /** * MediaPlayer特效1 * @param view */ public void playTeXiao1(View view){ if(mediaPlayerTeXiao1 != null) { mediaPlayerTeXiao1.stop(); } try { mediaPlayerTeXiao1.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } mediaPlayerTeXiao1.start(); } /** * MediaPlayer特效2 * @param view */ public void playTeXiao2(View view){ if(mediaPlayerTeXiao2 != null) { mediaPlayerTeXiao2.stop(); } try { mediaPlayerTeXiao2.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } mediaPlayerTeXiao2.start(); } /** * MediaPlayer特效2 * @param view */ public void playTeXiao3(View view){ if(mediaPlayerTeXiao3 != null) { mediaPlayerTeXiao3.stop(); } try { mediaPlayerTeXiao3.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } mediaPlayerTeXiao3.start(); } /** * SoundPool特效1 * @param view */ public void playSoundPoolTeXiao1(View view){ //参数1:播放特效加载后的ID值 //参数2:左声道音量大小(range = 0.0 to 1.0) //参数3:右声道音量大小(range = 0.0 to 1.0) //参数4:特效音乐播放的优先级,因为可以同时播放多个特效音乐 //参数5:是否循环播放,0只播放一次(0 = no loop, -1 = loop forever) //参数6:特效音乐播放的速度,1F为正常播放,范围 0.5 到 2.0 soundPool.play(loadId1, 0.5f, 0.5f, 1, 0, 1f); } /** * SoundPool特效2 * @param view */ public void playSoundPoolTeXiao2(View view){ soundPool.play(loadId2, 0.5f, 0.5f, 1, 0, 1f); } /** * SoundPool特效3 * @param view */ public void playSoundPoolTeXiao3(View view){ soundPool.play(loadId3, 0.5f, 0.5f, 1, 0, 1f); } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <RelativeLayout android:id="@+id/relativeLayout1" android:layout_width="fill_parent" android:background="@drawable/bg" android:layout_height="fill_parent" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentBottom="true" android:text="停止背景音乐" android:onClick="stopBgMusic" /> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/button1" android:layout_alignParentLeft="true" android:text="播放背景音乐" android:onClick="startBgMusic" /> <Button android:id="@+id/button43" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentBottom="true" android:text="SoundPool发射子弹3" android:onClick="playSoundPoolTeXiao3" /> <Button android:id="@+id/button42" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_above="@id/button43" android:text="SoundPool发射子弹2" android:onClick="playSoundPoolTeXiao2" /> <Button android:id="@+id/button41" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_above="@id/button42" android:text="SoundPool发射子弹1" android:onClick="playSoundPoolTeXiao1" /> <Button android:id="@+id/button23" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/button43" android:layout_alignParentBottom="true" android:text="MediaPlayer发射子弹3" android:onClick="playTeXiao3" /> <Button android:id="@+id/button22" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/button42" android:layout_above="@id/button23" android:text="MediaPlayer发射子弹2" android:onClick="playTeXiao2" /> <Button android:id="@+id/button21" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/button41" android:layout_above="@id/button22" android:text="MediaPlayer发射子弹1" android:onClick="playTeXiao1" /> </RelativeLayout> </LinearLayout>
最后源码 :郁闷文件大小不能超过10MB,分成2个压缩包了