zoukankan      html  css  js  c++  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);
                }
            });
        }
    }
  • 相关阅读:
    AddTransient、AddSingleton、AddScoped的区别
    ASP.NET Core Linux下为 dotnet 创建守护进程(必备知识)
    DotNetCore 结合 Nginx 将网站部署到阿里云
    centos7安装配置mysql8
    centos7安装nginx
    ASP.NET Core搭建多层网站架构【0-前言】
    .Net Core3.0 WebApi 二:API 文档神器 Swagger
    .Net Core3.0 WebApi 三:读取appsettings.json
    .Net Core3.0 WebApi 四:JWT权限验证
    vue动态配置参数,避免重复打包
  • 原文地址:https://www.cnblogs.com/feiruo/p/5001778.html
Copyright © 2011-2022 走看看