欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

游戏中的音效

程序员文章站 2024-03-25 23:03:22
...

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);
            }
        });
    }
}