你的位置:首页 > Java教程

[Java教程]游戏中的音效


1. 游戏中的即时音效:

在游戏中,根据情况播放的即时音效较为短暂、可以重复、也可以同时播放。由于Android中提供的MediaPlayer会占用大量的系统资源,而且播放时还会进行缓冲,有较大的延时,因此使用MediaPlayer无法实现即时音效的播放。而在Android中专门提供的SoundPool类主要用于管理和播放应用程序中的声音资源,使用该类时首先需要通过该类将声音资源加载到内存中,然后在需要的即时音效的地方播放即可,几乎没有延时现象。【由于SoundPool设计的初衷是用于无延时地播放游戏中的即时音效,因此实际开发中应该只讲长度小于7s的声音资源放进soundPool,否则可能会加载失败或内存占用过大】

SoundPool类:

public SoundPool (int maxSreams, int streamType, int srcQuality):创建SoundPool对象:maxStreams[该参数用于设置最多同时播放多少个音效]streamType[该参数设置音频类型,在游戏中通常设置为STREAM_MUSIC]srcQuality[该参数设置音频文件的质量,目前还没有具体的作用,设置为0(默认值)]

public int load(Context context, int resId, int priority):架子啊音频文件:context[该参数为应用程序的上下文]resId[该参数为要加载的音效资源的ID]priority[优先级]

public final int play (int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate):播放音效:soundID[该参数为要播放的音效ID]leftVolume[用来控制左声道音量]rightVolume[用来控制右声道音量]priority[该参数为优先级,0为最低]loop[该参数为音效的循环次数,0为不循环,-1为永远循环]rate[该参数为音效的回放速率,该值在0.5~2.0f,1.0f为正常速度]

public final void pause(int streamID):暂停音效的播放:streamID[要暂停音效的ID]

public final void stop(int streamID):停止播放音效:streamID[要停止播放音效的ID]

实例:

//初始化声音池的方法    public void initialsnd()    {        //初始化SoundPool对象		sp=new SoundPool(4,AudioManager.STREAM_MUSIC,0);        //初始化hashMap		hm=new HashMap<Integer,Integer>();        //加载音效文件ff,并设置为1号声音放入到hm中		hm.put(1,sp.load(this,R.raw.ff,1));	}//音效播放	public void playSound(int sound,int loop)   {        //获取AudioManager引用		AudioManager am=(AudioManager)this.getSystemService(Context.AUDIO_SERVICE);        //获取当前系统音量		float v1=am.getStreamVolume(AudioManager.STREAM_MUSIC);        //获取系统的最大音量		float v2=am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);        //计算得到播放音量		float v=v1/v2;        //调用SoundPool的play方法播放文件		currentId=sp.play(hm.get(sound),v,v,1,loop,1.0f);	}

2.背景音乐播放:

在游戏中,背景音乐可以使用不大于7s的一小节音乐将SoundPool的loop设置为-1即可;但在实际开发中,背景音效对延时并不是特别敏感,因此较长音效可以使用MediaPlayer进行播放。

2.1MediaPlayer的声明周期:MediaPlayer的生命周期包括10种状态,每种状态下可以调用相应的方法来实现音/视频文件的管理或播放。

<1>Idle状态:使用new方法创建一个MediaPlayer对象或者调用了其reset方法时,该MediaPlayer对象处于idle状态。在此状态下调用getDuration等方法,reset方法进入idle状态的话会触发OnErrorListener.onError,同时MediaPlayer对象进入Error状态,当然new方法不会。

<2>End状态:通过release方法可以进入End状态,只要MediaPlayer对象不再被使用,就应当尽快将其通过release方法释放掉,以释放占用的软、硬件资源,这其中有些资源是互斥的。如果MediaPlayer进入到End状态就不会再进行其他任何状态。

<3>Initialized状态:MediaPlayer调用setDataSource方法就进入了Initialized状态,表示此时要播放的文件已经装备好了。

<4>Prepared状态:初始化完成之后还需要调用prepare或prepareAsync方法进行准备,这两种方法一种是同步的,一种是异步的。只有进入了Prepared状态,才表明MediaPlayer到目前为止都工作正常,可以进行音乐文件的播放。

<5>Preparing状态:主要是与prepareAsync异步准备方法配合,如果异步准备完成,会触发OnPreparedListener.onPrepared,进而进入Prepared状态。

<6>Started状态:MediaPlayer准备完成之后,通过调用start方法,将进入Started状态。所谓Started状态,也就是播放中的状态,开发中可以使用isPlaying方法测试MediaPlayer是否处于Started状态。

<7>Paused状态:Started状态下调用paused方法可以暂停播放,从而进入Paused状态。暂停状态时可以调用seekTo方法,这时此MediaPlayer的状态是不变的。

<8>Stop状态:Started状态和Paused状态下均可调用stop方法并进入Stop状态,如果处于Stop状态的MediaPlayer要想重新播放,需要通过调用prepareAsync或prepare方法返回到先前的Prepared状态重新开始才可以。

<9>PlaybackCompleted状态:文件正常播放完毕,而又没有设置循环播放的话就进入该状态,并会触发OnCompletionListener接口中的OnCompletion方法。此时可以调用start方法重新从头开始播放文件呢,也可以调用stop方法停止播放,或者调用seekTo方法来重新定位播放位置。

<10>Error状态:由于某种原因MediaPlayer出现了错误,就会触发OnErrorListener.onError回调方法,此时MediaPlayer将会进入Error状态。及时捕捉并妥善处理这些错误可以释放相关的软、硬件资源,也可以改善用户体验。如果MediaPlayer进入了Error状态,可以通过调用reset方法来恢复,使得MediaPlayer重新返回Idle状态。

2.2MediaPlayer类:

首首先需要调用Activity对象的getSystemService(Context.AUDIO_SERVICE)方法获取AudioManager对象。然后调用MediaPlayer类中的相关方法进行音量控制。

public void adjustVolume(int direction, int flags):调用该方法可以调节音量大小。参数direction为调节的方向,ADJUST_LOWER减小音量、ADJUST_RAISE增大音量、ADJUST_SAME保持音量不变;参数flags为标记,通常设置为0。

public int getStreamMaxVolume(int streamtype):获取系统最大音量。

public int getStreamVolume(int StreamType):获取系统当前音量。

void android.media.AudioManager.setStreamVolume(int streamType, int index, int flags):调用该方法可以设置音量的大小,参数streamType为声音的类型,index为要设置的音频的索引值,参数flags为标记,通常设置为AudioManager.FLAG_PLAY_SOUND。

package com.mycompany.myapp;import android.app.*;import android.os.*;import android.view.*;import android.widget.*;import android.media.*;import android.content.*;import android.view.View.*;public class MainActivity extends Activity{  MediaPlayer mp;  AudioManager am;  private int maxvolume;  private int curvolume;  private int stpvolume;  /** Called when the activity is first created. */  @Override  public void onCreate(Bundle savedInstanceState)  {    super.onCreate(savedInstanceState);    setContentView(R.layout.main);    mp=new MediaPlayer();    try{      mp.setDataSource("sdcard/kgmusic/download/One T - The Magic Key.mp3");      mp.prepare();    }catch(Exception e){      e.printStackTrace();        }    am=(AudioManager)this.getSystemService(Context.AUDIO_SERVICE);    maxvolume=am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);    stpvolume=maxvolume/6;    Button bstart=(Button)this.findViewById(R.id.playbtn);    Button bpause=(Button)this.findViewById(R.id.pausebtn);    Button bstop=(Button)this.findViewById(R.id.stopbtn);    Button bincrease=(Button)this.findViewById(R.id.increasevolumebtn);    Button breduce= (Button)this.findViewById(R.id.reducevolumebtn);        bstart.setOnClickListener(new OnClickListener(){      public void onClick(View v){        mp.start();        Toast.makeText(getBaseContext(),"开始播放",Toast.LENGTH_LONG).show();      }    });    bpause.setOnClickListener(new OnClickListener(){      public void onClick(View v){        mp.pause();        Toast.makeText(getBaseContext(),"暂停播放",Toast.LENGTH_LONG).show();      }    });    bstop.setOnClickListener(new OnClickListener(){      public void onClick(View v){        mp.stop();        Toast.makeText(getBaseContext(),"停止播放",Toast.LENGTH_LONG).show();      }    });    bincrease.setOnClickListener(new OnClickListener(){      public void onClick(View v){        curvolume=am.getStreamVolume(AudioManager.STREAM_MUSIC);        int tmpvolume=curvolume+stpvolume;        am.setStreamVolume(AudioManager.STREAM_MUSIC,curvolume,AudioManager.FLAG_PLAY_SOUND);        Toast.makeText(getBaseContext(),"音量增加",Toast.LENGTH_LONG).show();      }    });    breduce.setOnClickListener(new OnClickListener(){      public void onClick(View v){        curvolume=am.getStreamVolume(AudioManager.STREAM_MUSIC);        int tmpvolume=curvolume-stpvolume;        curvolume=tmpvolume>0?tmpvolume:0;        am.setStreamVolume(AudioManager.STREAM_MUSIC,curvolume,AudioManager.FLAG_PLAY_SOUND);        Toast.makeText(getBaseContext(),"音量减小",Toast.LENGTH_LONG);      }    });  }}