魔法球這種塔,很有意思。這種塔的攻擊力雖然低,但是攻擊速度快啊,而且升級(jí)后還能攻擊多個(gè)目標(biāo),用在對(duì)付血少速度快的怪物再適合不過了.玩了挺久發(fā)現(xiàn)這個(gè)塔的音效有些問題:屏幕中有多個(gè)魔法球塔時(shí),賣掉其中一個(gè)可能會(huì)導(dǎo)致所有魔法球塔的音效停止.
有時(shí)候賣掉所有的魔法球塔,但是聲音還在播放!
一般情況下我是不會(huì)mind這種細(xì)節(jié)的,但由于保衛(wèi)蘿卜是用cocos2d-x制作的,所以我稍微多想了一下:
猜想1:由于攻擊速度十分快,所以我假設(shè)魔法球這個(gè)塔的音效播放和其他的塔不太一樣,可能是這個(gè)樣子的:切換為攻擊模式時(shí)循環(huán)播放音效,切換為待機(jī)模式時(shí)停止音效!
猜想2. 如果假設(shè)成立,這個(gè)音效由于會(huì)循環(huán)播放,如果聲音太吵的話,會(huì)十分的吵,蘿卜顯然注意到了這點(diǎn).
猜想3. 所有的魔法球塔會(huì)公用一個(gè)特效聲音,要不造的塔多了就根本沒法開聲音玩了!
其實(shí)這座塔的音效播放邏輯十分的復(fù)雜!
驗(yàn)證
下面讓我驗(yàn)證下我的猜想,看看能否幫蘿卜解決這個(gè)問題!
驗(yàn)證1:循環(huán)播放音效
這個(gè)十分簡(jiǎn)單,我在保衛(wèi)蘿卜2的資源中找到了CarrotFantasy.app\Music\Towers\Ball.mp3,看了時(shí)長(zhǎng)1s左右,但是魔法球塔的攻擊速度絕對(duì)大于2次,開2倍速的會(huì)大于4次,1s播放4次音效,沒有人會(huì)這么做!所以魔法球塔是循環(huán)播放音效的!
驗(yàn)證2:音效的特性
這個(gè)大家聽一下就會(huì)知道了,魔法球的塔混在其他塔的音效里實(shí)在是太弱了!為此,我還假裝很專業(yè)的用GoldWave查看了一下:
圖中上面的聲音是瓶子炮的聲音,下面是魔法球的聲音,從圖上可以看出,雖然魔法球的聲音很長(zhǎng),但是只有在0.65s時(shí)聲音較大,其他時(shí)候聲音都很小!
驗(yàn)證3.公用一個(gè)音效
開啟循環(huán)播放音效十分簡(jiǎn)單,只需在playEffect("1.ogg",true)時(shí)第二個(gè)參數(shù)填true即可,這時(shí)playEffect會(huì)返回一個(gè)unsigned int類型的id,這個(gè)id會(huì)用于stopEffect(id),如下:
這樣看起來似乎很簡(jiǎn)單嘛,攻擊的時(shí)候播,順帶記下ID,待機(jī)的時(shí)候停,這么簡(jiǎn)單,蘿卜的程序太差了吧,這都能寫錯(cuò)!其實(shí)不然,這只是場(chǎng)景中只有一座塔時(shí)的情況!
下面我們來試一下如果我們連續(xù)調(diào)用多次playEffect,會(huì)發(fā)生什么問題?我做了測(cè)試項(xiàng)目,將每次playEffect的返回ID打在屏幕上,win32截圖如下:
額,你沒有看錯(cuò),win32下播放同一個(gè)音效返回的id都是一樣的,只要點(diǎn)擊一下停止就全部都停了,為什么呢?讓我們看一下win32 下聲音的id是怎么生成的吧,在SimpleAudioEngine中我們可以看到這段代碼:
這下明白了吧,win32下的id是根據(jù)音效的路徑pszFilePath算出來的,這一點(diǎn)確實(shí)比較坑,大家以后要注意一下!下面我看一下在android上的效果吧!
Adnroid版是正常的,每次playEffect返回的id會(huì)遞增,可以明顯的聽出又多了一個(gè)音效,當(dāng)我音效疊了5層之后已經(jīng)很亂了,但是蘿卜的顯然不是如此,所以所有的魔法球共用一個(gè)音效是正確的!
注意:這里一定要提前preloadEffect,不然第一次返回的id是0,這樣那個(gè)音效就永遠(yuǎn)停不下來了!
分析
基于以上猜想,我們來分析下魔法球塔的邏輯:
1.對(duì)于單個(gè)的魔法球塔,由于多目標(biāo),所以要監(jiān)聽目標(biāo)數(shù)量的變化,當(dāng)target_count>0時(shí),開始播放音效,當(dāng)target_count=0時(shí),停止播放音效.
2.賣掉塔時(shí),如果處于攻擊狀態(tài),應(yīng)該調(diào)用停止播放音效.
3.對(duì)于所有的魔法球塔,音效應(yīng)該采用類此引用計(jì)數(shù)的方法,每調(diào)用一次++m_uReference;,每停止一次--m_uReference;,當(dāng)m_uReference==0時(shí)調(diào)用真正的停止音效方法.
總結(jié)
綜上所述,我們?cè)诰帉懹螒蛞粜н壿嫷拇a時(shí),要注意:
1.循環(huán)音效多次播放在windows上有問題,可以考慮在android或ios端調(diào)試.
2.音效一定要preloadEffect.