您的当前位置:游戏狗 > 保卫萝卜2 > 正文

从保卫萝卜2看Cocos2d-x循环播放音效的问题

2014-02-09 11:25:11来源:游戏狗整理编辑:NiCo

魔法球这种塔,很有意思。这种塔的攻击力虽然低,但是攻击速度快啊,而且升级后还能攻击多个目标,用在对付血少速度快的怪物再适合不过了.玩了挺久发现这个塔的音效有些问题:屏幕中有多个魔法球塔时,卖掉其中一个可能会导致所有魔法球塔的音效停止.

有时候卖掉所有的魔法球塔,但是声音还在播放!

一般情况下我是不会mind这种细节的,但由于保卫萝卜是用cocos2d-x制作的,所以我稍微多想了一下:

猜想1:由于攻击速度十分快,所以我假设魔法球这个塔的音效播放和其他的塔不太一样,可能是这个样子的:切换为攻击模式时循环播放音效,切换为待机模式时停止音效!

猜想2. 如果假设成立,这个音效由于会循环播放,如果声音太吵的话,会十分的吵,萝卜显然注意到了这点.

猜想3. 所有的魔法球塔会公用一个特效声音,要不造的塔多了就根本没法开声音玩了!

其实这座塔的音效播放逻辑十分的复杂!

验证

下面让我验证下我的猜想,看看能否帮萝卜解决这个问题!

验证1:循环播放音效

这个十分简单,我在保卫萝卜2的资源中找到了CarrotFantasy.app\Music\Towers\Ball.mp3,看了时长1s左右,但是魔法球塔的攻击速度绝对大于2次,开2倍速的会大于4次,1s播放4次音效,没有人会这么做!所以魔法球塔是循环播放音效的!

验证2:音效的特性

这个大家听一下就会知道了,魔法球的塔混在其他塔的音效里实在是太弱了!为此,我还假装很专业的用GoldWave查看了一下:

图中上面的声音是瓶子炮的声音,下面是魔法球的声音,从图上可以看出,虽然魔法球的声音很长,但是只有在0.65s时声音较大,其他时候声音都很小!

验证3.公用一个音效

开启循环播放音效十分简单,只需在playEffect("1.ogg",true)时第二个参数填true即可,这时playEffect会返回一个unsigned int类型的id,这个id会用于stopEffect(id),如下:

这样看起来似乎很简单嘛,攻击的时候播,顺带记下ID,待机的时候停,这么简单,萝卜的程序太差了吧,这都能写错!其实不然,这只是场景中只有一座塔时的情况!

下面我们来试一下如果我们连续调用多次playEffect,会发生什么问题?我做了测试项目,将每次playEffect的返回ID打在屏幕上,win32截图如下:

额,你没有看错,win32下播放同一个音效返回的id都是一样的,只要点击一下停止就全部都停了,为什么呢?让我们看一下win32 下声音的id是怎么生成的吧,在SimpleAudioEngine中我们可以看到这段代码:

这下明白了吧,win32下的id是根据音效的路径pszFilePath算出来的,这一点确实比较坑,大家以后要注意一下!下面我看一下在android上的效果吧!

Adnroid版是正常的,每次playEffect返回的id会递增,可以明显的听出又多了一个音效,当我音效叠了5层之后已经很乱了,但是萝卜的显然不是如此,所以所有的魔法球共用一个音效是正确的!

注意:这里一定要提前preloadEffect,不然第一次返回的id是0,这样那个音效就永远停不下来了!

分析

基于以上猜想,我们来分析下魔法球塔的逻辑:

1.对于单个的魔法球塔,由于多目标,所以要监听目标数量的变化,当target_count>0时,开始播放音效,当target_count=0时,停止播放音效.

2.卖掉塔时,如果处于攻击状态,应该调用停止播放音效.

3.对于所有的魔法球塔,音效应该采用类此引用计数的方法,每调用一次++m_uReference;,每停止一次--m_uReference;,当m_uReference==0时调用真正的停止音效方法.

总结

综上所述,我们在编写游戏音效逻辑的代码时,要注意:

1.循环音效多次播放在windows上有问题,可以考虑在android或ios端调试.

2.音效一定要preloadEffect.

相关新闻

©游戏狗 Gamedog.cn 北京手游天下数字娱乐科技股份有限公司 版权所有
安全百店 ANVA自律组
游戏狗微信关注游戏狗订阅号