Android3D游戏——添加背景音乐与音效

今天终于把主菜单做好了,虽然可能还有些小bug,不过在以后实现栏目功能的时候,应该都能处理好。

今天讲的是添加背景音乐和音效,做游戏怎么能没有声音呢,对不对。

一般添加声音是靠两种方法实现的。一种是MediaPlayer,一种是SoundPool。这两种方法的区别是MediaPlayer可以存储较大的音频文件,载入稍慢,不支持同时播放。而SoundPool只能存储较小的音频文件,载入较快,支持同时播放。这样就很显然了,MediaPlayer用来实现背景音乐,而SoundPool用来实现音效。

下面是我写的两个类,直接加到游戏中就可以用了,由于我开发的是小型的游戏,对声音处理的要求不高,更多的功能也没有写,不过基本功能都在了。

package my.Game.audio;

import java.io.IOException;

import com.threed.jpct.Logger;

import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;

public class MyMusic {

	protected static MediaPlayer mediaPlayer;
	protected static boolean mustResume = false;
	private static Activity act;
	
	public MyMusic(Activity act){
		mediaPlayer = new MediaPlayer();
		MyMusic.act=act;
	}
	
	public static void prepareMediaPlayer(String file) {
		if(mediaPlayer == null) {
			mediaPlayer = new MediaPlayer();
		}
		
		AssetFileDescriptor afd = null;
		try {
			afd = act.getAssets().openFd("sound/"+file+".ogg");
		} catch (Exception e) { 
			e.printStackTrace();
			Logger.log("Tried creating Music with missing asset ... " + file);
			System.exit(0);
			return;
		}
		try {
			mediaPlayer.reset();
			mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
			mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			afd.close();
		} catch (IOException e) {
			e.printStackTrace();
			Logger.log("Error setting data source in Music.play, IO exception");
			System.exit(0);
			return;
		} catch (IllegalStateException e) {
			e.printStackTrace();
			Logger.log("Error setting data source in Music.play, fail ...");
			return;
		}
		try {
			mediaPlayer.prepare();	
		} catch (Exception e) { 
			e.printStackTrace();
			Logger.log("Error preparing MediaPlayer");
			System.exit(0);
			return;
		}
	}
	
	
	public static void play(boolean loop) {
		
		if(mediaPlayer == null) {
			Logger.log("error:MediaPlayer hasn't prepared.");
			return;
		}
		mediaPlayer.setLooping(loop);
		mediaPlayer.start();
	}
	
	
	public static void stop() {
		if(mediaPlayer == null) {
			Logger.log("error:No mediaPlayer is playing.");
			return;
		}
		mediaPlayer.stop();
	}
	
	
	public static void pause() {
		if(mediaPlayer == null) {
			Logger.log("error:No mediaPlayer is playing.");
			return;
		}
		mediaPlayer.pause();
	}
	public static void start(){
		if(mediaPlayer == null) {
			Logger.log("error:No mediaPlayer is prepared.");
			return;
		}
		mediaPlayer.start();
	}
	
	public static void onPause() {
		if(mediaPlayer == null) {
			Logger.log("error:No mediaPlayer is playing.");
			return;
		}
		if(mediaPlayer.isPlaying()) {
			mediaPlayer.pause();
			mustResume = true;
		}
	}
	
	
	public static void onResume() {
		if(mediaPlayer == null) {
			Logger.log("error:No mediaPlayer is playing.");
			return;
		}
		if(mustResume) {
			mediaPlayer.start();
			mustResume = false;
		}
	}
	
	public static MediaPlayer getMediaPlayer() {
		return mediaPlayer;
	}
}

对了有一点要注意了,我有用到JPCT这个引擎,所以想用的这些类的话需要把该引擎中的方法删掉,这并不影响其中功能的实现。

以上是自己写的类似于MediaPlayer功能的类,使用的方法与MediaPlayer相近。

首先要实例化一个对象,构造时要传入Activity对象,这样做主要是为了后面获取资源。

然后是准备,即

prepareMediaPlayer(String file)
这个用来加载音频文件的

afd = act.getAssets().openFd("sound/"+file+".ogg");
这个地方要改成你存放音频文件的文件夹和文件类型。

剩下的一些处理也不用管他了。

最后就是放音了

public static void play(boolean loop)
loop用来控制是否循环播放。




下面讲下SoundPool的方法。

首先要先认识什么是SoundPool,我个人理解就是一个声音池,你可以在里面放一定数量的音频,这些音频是用数字表示的,也就是他们都有一个ID,这个ID是1、2、3.。。。一直往上排的,然后这个SoundPool还提供播放、暂停等功能。下面是我写的两个类。

package my.Game.audio;

public class MySound {
	
	protected int ID;
	static public int volumn;
	public MySound(int volumn){
		ID=0;
		MySound.volumn=volumn;
	}
	
	
	
	//播放音效,不循环//
	public void play(){
		MySoundPool.getInstance().soundPool.play(ID, volumn, volumn, 1, 0, 1f);
	}
	
	//释放音效资源/
	public void unLoad(){
		MySoundPool.getInstance().soundPool.unload(ID);
	}
	
	//设置音量///
	public void setVolumn(int vol){
		volumn=vol;
	}
	//获得音量//
	public int getVolumn(){
		return volumn;
	}
	
}

这个类很简单吧,你可以认为他就是一个音频。然后把SoundPool里面的播放功能赋予它,这样更好理解。


package my.Game.audio;

import java.io.IOException;

import com.threed.jpct.Logger;

import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.SoundPool;
import android.util.Log;

public class MySoundPool {
	/最大存10音效资源///
	private final int MaxNumOfSound=10;
	private MySound[] soundArr=new MySound[MaxNumOfSound];
	protected SoundPool soundPool;
	private int top=-1;	///soundArr栈顶指针
	static private MySoundPool Instance;
	public MySoundPool(){
		MySoundPool.Instance=this;
		//最多4个音效同时播放,0为音质,该参数无效
		soundPool=new SoundPool(4,AudioManager.STREAM_MUSIC, 0);
	}
	
	/getInstance常见用法,^_^//
	static public MySoundPool getInstance(){
		return Instance;
	}
	//生成音效资源,需要用SoundPool来加载
	public MySound create(Resources res,String filename) {
		MySound sound=new MySound(MySound.volumn);
		AssetFileDescriptor afd = null;
		try {
			afd=res.getAssets().openFd("sound/"+filename+".ogg");
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			Logger.log("error:Load soundfile with failing assets");
		}
		sound.ID=MySoundPool.getInstance().soundPool.load(afd,1); 
		Log.v("SoundID","SoundID="+sound.ID);
		/load的第二个参数0代表优先级,现在是无效的//
		addSound(sound);
		return sound;
	}
	
	添加音效资源//
	public void addSound(MySound sound){
		top++;
		soundArr[top]=sound;
		if(top==MaxNumOfSound){
			Logger.log("warning:SoundArray is already full");
		}
	}
	
	释放音效资源//
	public void releasePool(){
		while(top!=-1){
			soundArr[top].unLoad();
			top--;
		}
		soundPool.release();
	}
	//清空soundPool///
	public void emptyPool(){
		while(top!=-1){
			soundArr[top]=null;
			top--;
		}
	}
}

这个就是类似于SoundPool的类了,不过他可以存放多个音频,即之前创建的MySound类的对象。


先讲下实现,再说使用方法。

soundPool=new SoundPool(4,AudioManager.STREAM_MUSIC, 0);
这个是实例一个SoundPool,方便其他类调用SoundPool中的方法,我们看到这个构造函数有3个参数,第一个是允许同时播放的音频数量,第二个是音频类型,第三个是音质,第三个参数现在还没有效果,是为了以后扩展用的。好像其他的也没啥好说的。

那讲下使用方法吧:

首先要创建一个MySoundPool对象,它用来管理你的所有的音频文件,这是一对多的关系,不要试图去创建多个SoundPool,很容易有问题的。

然后创建MySound对象

MySound(int volumn)
就是这个方法,参数是你想要的音量,当然这里为了实现对游戏音量的控制,所以把volumn设置为静态的,这样所有音效是同一个音量,另外值得说的是Android手机音量最大值是15,大家可以试一下。


然后用MySoundPool对象加载音频文件,将返回值赋给MySound对象,只有这样才能放音的

create(Resources res,String filename)
与MediaPlayer的prepare差不多了。不在解释了。


最后就是放音了

 play()
这是在MySound类中实现的。其根源是

play(ID, volumn, volumn, 1, 0, 1f)
第一个参数就是你音频的ID,第二、三个参数是音量左右线,不懂有啥区别,也没试验过,又兴趣的朋友可以试验一下,第四个是优先级,现在是无效的,待扩展。第五个是是否循环,第六个是rate,不懂啥意思。


好了这样两个类,以后使用声音的时候就更加简单了。




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值