Windows shell 微软 Firefox 编程 云计算 linux google Python mysql apache java 开源 centos Ubuntu wordpress Android 程序员 nginx php

【讀書筆記《Android遊戲編程之從零開始》】19.遊戲開發基礎(遊戲音樂與音效)

在一款遊戲中,除了華麗的界面 UI 直接吸引玩家外,另外重要的就是遊戲的背景音樂與音效;合適的背景音樂以及精彩的音效搭配會令整個遊戲上升一個檔次。

在 Android 中。常用於播放遊戲背景音樂的類是 MediaPlayer, 而用於遊戲音效的則是 SoundPool 類。

1. MediaPlayer

MediaPlayer 實例化不是 new 出來的,而是通過調用靜態方法得到的,這裏有幾種靜態方法:

create(Context context, Uri uri) 
作用:通過Uri創建一個多媒體播放器。
create(Context context, int resid)
作用:通過資源ID創建一個多媒體播放器
create(Context context, Uri uri, SurfaceHolder holder)
作用:通過Uri和指定 SurfaceHolder 【抽象類】 創建一個多媒體播放器

MediaPlayer 類常用的函數如下:

prepare()

作用:為同步播放音樂文件做準備

start()

作用:播放音樂

pause()

作用:暫停音樂播放

stop()

作用:停止音樂播放

getCurrentPosition()
作用:返回 Int, 得到當前播放音樂的時間點

 getDuration()
作用:返回 Int,獲取播放的音樂文件總時間長度

getVideoHeight()
作用:返回 Int ,得到視頻的高度

getVideoWidth()
作用:返回 Int,得到視頻的寬度

isLooping()
作用:返回 boolean ,是否循環播放

isPlaying()
作用:返回 boolean,是否正在播放

prepareAsync()

作用:無返回值,準備異步

release()
作用:無返回值,釋放 MediaPlayer  對象

reset()
作用:無返回值,重置 MediaPlayer  對象

seekTo(int msec)
作用:無返回值,指定音樂文件播放的位置(以毫秒為單位的時間)

參數:跳轉時間(以毫秒為單位)


setAudioStreamType(int streamtype)
作用:無返回值,指定流媒體的類型

setDataSource(String path)
作用:無返回值,設置多媒體數據來源【根據路徑】

setDataSource(FileDescriptor fd, long offset, long length)
作用:無返回值,設置多媒體數據來源【根據 FileDescriptor】

setDataSource(FileDescriptor fd)
作用:無返回值,設置多媒體數據來源【根據 FileDescriptor】

setDataSource(Context context, Uri uri)
作用:無返回值,設置多媒體數據來源【根據 Uri】

setDisplay(SurfaceHolder sh)
作用:無返回值,設置用 SurfaceHolder 來顯示多媒體

setLooping(boolean looping)
作用:無返回值,設置音樂是否循環播放
參數 :true 表示循環播放,false 表示不循環播放

setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener)
作用:監聽事件,網絡流媒體的緩沖監聽

setOnCompletionListener(MediaPlayer.OnCompletionListener listener)
作用:監聽事件,網絡流媒體播放結束監聽

setOnErrorListener(MediaPlayer.OnErrorListener listener)
作用:監聽事件,設置錯誤信息監聽

setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener)
作用:監聽事件,視頻尺寸監聽

setScreenOnWhilePlaying(boolean screenOn)
作用:無返回值,設置是否使用 SurfaceHolder 顯示

setVolume(float leftVolume, float rightVolume)
作用:無返回值,設置音量

除此之外,音樂管理類 AutoManager 提供了獲取當前音樂大小以及最大音量等,其常用函數如下:

setStreamVolume(int streamType,int index,int flags)

作用:設置音量大小

第一個參數:音量類型(音樂的常量:AudioManager.STREAM_MUSIC)

第二個參數:音量大小

第三個參數:設置一個或多個標識

getStreamVolume(int streamType)

作用:獲取當前音量大小

參數:獲取音量大小的類型

 
getStreamMaxVolume(int streamType)
作用:獲取當前音量最大值
參數:獲取音量大小的類型

Android OS 中,如果去按手機上調節音量的按鈕,會遇到兩種情況,一種是調整手機本身的鈴聲音量,另外一種是調整遊戲、軟件的音樂播放的音量。

在遊戲中的時候,默認調整的是手機的鈴聲音量,只有在遊戲中有聲音播放的時候,才能去調整遊戲的音量。因此往遊戲中添加音樂時,需要使用如下函數:

Activity.setVolumeControlStream(int streamType)

作用:設置控制音量的類型

參數:音量類型(AudioManager.STREAM_MUSIC:媒體音量)

下面用一個簡單實例進行說明,先看下效果圖:

 

新建項目,遊戲框架為 SurfaceView 遊戲框架,修改 MySurfaceView 類如下:

 View Code

MainActivity 類修改如下:

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

    public static MainActivity instance;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        instance = this;
        //顯示自定義的SurfaceView視圖
        setContentView(new MySurfaceView(this));
    }
}


2.SoundPool

SoundPool也能播放一些音樂文件,它和MediaPlayer 之間最大的區別是SoundPool 只能播放小的文件。
Sound 類的構造函數如下:

SoundPool(int maxStreams,int streamType,int srcQuality)
作用:實例化一個SoundPool 實例
第一個參數:允許同時播放的聲音最大值
第二個參數:聲音類型
第三個參數:聲音的品質

SoundPool 類中常用的函數如下:

int load(Context context,int resId,int priority)
作用:加載音樂文件,返回音樂ID(音樂流文件數據)
第一個參數:Context 實例
第二個參數:音樂文件 Id
第三個參數:標識優先考慮的聲音。目前使用沒有任何效果,只是具備了兼容性價值

int paly(int soundID,float leftVolume,float rightVolume,int priority,int loop,float rate)
作用:音樂播放,播放失敗返回0,正常返回非0值
第一個參數:加載後得到音樂文件ID
第二個參數:音量的左聲道,範圍:0.0 ~ 1.0
第三個參數:音量的右聲道,範圍:0.0 ~ 1.0
第四個參數:音樂流的優先級,0是最低優先級
第五個參數:音樂的播放次數,-1表示無限循環,0表示正常一次,大於0則表示循環次數
第六個參數:播放速率,取值範圍:0.5 ~ 2.0,1.0 表示正常播放

pause(int streamID)
作用:暫停音樂播放
參數:音樂文件加載後的流ID

stop(int streamID)
作用:結束音樂播放
參數:音樂文件加載後的流ID

release()
作用:釋放SoundPool 的資源

setLoop(int streamID,int loop)
作用:設置循環次數
第一個參數:音樂文件加載後的流ID
第二個參數:循環次數

setRate(int streamID,float rate)
作用:設置播放速率
第一個參數:音樂文件加載後的流ID
第二個參數:速率值

setVolume(int streamID,float leftVolume,float rightVolume)
作用:設置音量大小
第一個參數:音樂文件加載後的流ID
第二個參數:左聲道音量
第三個參數:右聲道音量

setPriority(int streamID,int priority)
作用:設置流的優先級
第一個參數:音樂文件加載後的流ID
第二個參數:優先級值

照例通過實例來詳細講解如何使用 SoundPool 。

加載的音樂文件:

新建項目,遊戲框架為 SurfaceView 遊戲框架,修改 MySurfaceView 類如下:

 View Code

整個項目的流程很簡單,通過判斷用戶的按鍵,播放不同的音樂;但是如果音樂文件過大,但是運行項目時會報出如下錯誤:

錯誤對應的程序代碼是加載長音樂文件生成其數據ID的一行,出現此錯誤的原因如下:

利用 SoundPool 播放音樂文件,首先都會對需要播放的音樂文件通過函數 int load(Context context,int resId,int priority) 進行加載,並且生成對應的音樂數據ID;其生成的數據 ID(int 值)就是整個音樂文件的所有數據,而如果音樂文件過大,其中的音樂流數據文件也遠遠超過了int 的最大值,所以當程序加載此音樂文件生成對應的數據ID時,會報超過最大值的異常。

3.MediaPlayer 與 SoundPool 優劣分析

 

3.1 使用MediaPlayer 的優缺點

(1)缺點

資源占用量較高、延遲時間較長、不支持多個音頻同時播放等。

除此之外使用 MediaPlayer 進行播放音樂時,尤其是在快速連續播放聲音(比如連續猛點按鈕)時,會非常明顯的出現1~3秒左右的延遲;當然此問題可以使用MediaPlayer.seekTo() 這個方法來解決。

(2)優點

支持很大的音樂文件播放,而且不會同 SoundPool 一樣需要加載準備一段時間,MediaPlayer 能及時播放音樂。

3.2 使用SoundPool 的優缺點

(1)缺點

①最大只能申請1M的內存空間,這就意味著用戶只能使用一些很短的聲音片段,而不能用它來播放歌曲或者遊戲背景音樂。

②SoundPool 提供了 pause 和 stop 方法,但建議最好不要輕易使用這些方法,因為它們可能會導致莫名其妙的終止。

③使用SoundPool 時音頻格式建議使用OGG格式。如果使用WAV格式的音頻文件,在播放的情況下有時會出現異常關閉的情況。

④在使用SoundPool 播放音樂文件的時候,如果在構造中就調用播放函數進行播放音樂,其效果則是沒有聲音!不是因為函數沒有執行,而是SoundPool 需要加載準備時間!當然這個準備時間也很短,不會影響使用,只是程序一運行播放剛開始會沒有聲音罷了。

(2)優點

支持多個音樂文件同時播放。

通過以上分析可以明顯知道,在Android 遊戲開發中,遊戲背景音樂使用MediaPlayer 肯定比使用SoundPool 要合適;而遊戲音效的播放采用SoundPool 則更好,畢竟遊戲中肯定會出現多個音效同時進行播放額情況。

延伸阅读

    评论