DOMException: play() can only be initiated by a user gesture(Cocos2d-JS HTML5)

Cocos2d-x目前一直在力推Cocos Creator,流程上Creator和Unity已经很像了(再来个编辑器状态可视化运行就完美了),其实Cocos还有一个纯JS版:http://www.cocos2d-x.org/filecenter/jsbuilder,而且还是可以自助选择所需组件的,最精简版是可以只有几百k的单js文件,使用此版本引擎的应用开发流程和Creator前的Cocos一样,代码为主!所以个人认为更适合做一些简单的小游戏或移植原有C++ Lua Obj-C项目。
由于对H5游戏开发接触的不多,大部分认知还停留在早期的canvas 2d状态,简单试了下这个纯JS版本,发现目前webgl的绘图效率已经可以在移动端和PC端(最新chrome)均达到很不错的效果了。不过这次要记录的问题和图形方面没关系,而是和声音有关,具体一点说是通过cc.audioEngine.playMusic播放游戏背景音乐产生的问题,错误现象直接写在标题中了。
其实在遇到标题中的错误之前还有一个问题,也算是关联问题,即H5游戏在移动端上不能以js代码形式主动触发音乐的播放,必须在用户操作后才可以播放,这个百度一下就可以查到,一开始在PC端还是按照原来做游戏的逻辑,loading完后splash,然后main menu直接播放bgm,PC浏览器下一切正常,但到了移动端却发现bgm根本没有播放,于是直接根据百度到的资料将初始bgm改为用户点击后才播放,本以为这样就可以了,但是后来又遇到了标题的问题,具体触发代码如下:

// JS版没有这个,照抄lua实现
cc.Node.prototype.performWithDelay = function (callback, delay) {
    this.runAction(cc.Sequence.create(
        cc.DelayTime.create(delay),
        cc.CallFunc.create(callback)
    ));
}
...
// 这样会触发标题的错误 playMusic是对cc.audioEngine.playMusic的封装
sound.playMusic(res.tofight_mp3);
this.performWithDelay(function () {
    sound.playMusic(res.fight_mp3);
}, 1);

本意是想在玩家操作后,先播放一段进战斗bgm,然后1s后自动切换到战斗bgm,实际测试PC上效果如预期,移动端上战斗bgm却没有播放,莫名其妙之后搜索get到了chrome移动端调试神技:chrome://inspect(突然感觉web开发实在是太幸福了),顺利看到了移动端chrome的错误log,便是标题那个,这下好办了直接查到了问题根源,原来移动端上不止不能程序主动触发播放声音逻辑,而且在用户操作后必须马上播放,晚了也不行(大概就是1s内)。但是想了想,封面bgm可以等到用户操作后才开始播放,但这个自动过度战斗bgm的逻辑可就不好改成用户操作触发了,要不就得把2段bgm合成1段一次性播放…最后发现,其实只要先playMusic一次,然后再延迟后播放就没问题了,即代码改为这样:

sound.playMusic(res.fight_mp3);
sound.playMusic(res.tofight_mp3);
this.performWithDelay(function () {
    sound.playMusic(res.fight_mp3);
}, 1);

算是暂时绕开了这个限制,但还不清楚这样有没有什么弊端,以后有空具体研究下。

博主友情提示:

如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。