文章目录
好了,书接上回,继续完善我们的拼图游戏。
上一篇地址:【Cocos Creator 实战】01 - 如何做一款简单的拼图游戏
概览
主要内容
来看看今天要做的内容:
- Cocos Creator 如何添加背景音乐
- Cocos Creator 如何添加音效
先来说说什么是音乐,什么是音效。
我们一般所说的音乐都是背景音乐,音效就是给用户某些特定反馈的声音。
还有个更笼统点的说法:音乐就是长的,音效就是短的。虽然不太严谨,但基本也就是那么个意思。
在 Cocos Creator 中,也是区分音乐(music)和音效(effect)的,但其实他们的界限越来越模糊,而且一般情况下也没什么意义。比如我看最近的文档里面已经建议大家使用 audioEngine.play
接口来统一播放音频。反正就是为了发出来声音嘛,何必搞那么麻烦。
项目资源
推荐大家先把项目 clone 到本地,然后参考着代码来看本篇文章。
我的每篇文章会对应一个分支,大家直接看对应的分支就可以,master 对应的是最新的内容,会整合各个分支。
演示地址也是对应每篇文章独立部署的。
开搞
使用 AudioSource 播放(静态)
使用 AudioSource 播放的话,我们可以做到一行代码都不写,直接在 Cocos Creator 编辑器中就可以完成。
针对我们的拼图游戏,我们把背景音乐通过这种方式来播放。
1、先添加一个空节点:
2、给这个节点添加一个 AudioSource 组件
3、然后把我们准备好的 bgm.mp3
文件拖拽到 Clip 属性上,再设置下面的属性就OK了。
我是个追求中庸的油腻中年大叔,所以音量(Volume)设置成 0.8
;因为是背景音乐,所以需要循环播放(Loop)+ 加载完成后直接播放(Play On Load)+ 预加载(Preload)。
当然,也可以通过脚本控制 AudioSource 播放,不过我们暂时不需要,这里就先不讲了。
使用 AudioEngine 播放(静态 + 动态)
静态播放
所谓的静态播放,就是必须要先在脚本的属性中指定 AudioClip
资源对象。
比如:
cc.Class({
extends: cc.Component,
properties: {
audio: {
default: null,
type: cc.AudioClip
}
},
onLoad: function () {
this.current = cc.audioEngine.play(this.audio, false, 1);
},
onDestroy: function () {
cc.audioEngine.stop(this.current);
}
});
动态播放
那动态播放相对来讲就灵活一些了,我们可以通过类似上一篇文章讲到的那种方式,先加载 AudioClip 资源,然后再播放。
比如:
cc.loader.loadRes('sound/drop', cc.AudioClip, function (err, clip) {
cc.audioEngine.playEffect(clip, false);
});
AudioSource 和 AudioEngine 的区别
AudioEngine
和 AudioSource
最大的区别就是,AudioEngine
只能在脚本中进行调用,而 AudioSource
既可以在脚本中调用,也可以在编辑器中调用。
那是不是说 AudioSource
比 AudioEngine
屌呢?
非也。
其实 AudioEngine
更灵活一些,因为它提供了动态调用的方式。试想一下,如果你有几百上千个音效,你是想通过写代码的方式来播放,还是想通过编辑器,把每个文件都拖拽一次到对应的属性上。
尤其是遇到一些有规律的音频文件。
比如下面这样:
上面就是一个棋牌游戏的部分音效文件,男女各5套配音,每套配音对应一大堆音效。
你想拖拽,你拖吧,累死你,还有就是,后面有可能这个音效文件会修改,那修改完了的话,修改的文件你还得重新拖。这个活,谁干谁知道。对,我干过。
好了,言归正传,说说一般的用法。
我现在基本都不用 AudioSource
了,太不灵活,除了个别页面的 BGM。而 AudioEngine
,既然可以动态播放,为什么不动态播放呢?我还是觉得写代码省事。
这个大家自行取舍哈,黑猫白猫,抓到耗子就是好狗。
设置回调
因为我们是想在用户开始拖动的时候给一个音效,拖动结束的时候再给一个音效,所以我们需要知道什么时候拖动已经开始,什么时候拖动结束的。
在 item.js
文件中,我们先修改一下初始化小图片的方法,增加两个属性值。
initPic(cfg, moveStartCb, moveEndCb) {
this.cfg = cfg;
// 这里是修改内容 - start
this.moveStartCb = moveStartCb;
this.moveEndCb = moveEndCb;
// 这里是修改内容 - end
this.__initNode();
this.__initSprite();
this.__initFrame();
this.__initTouch();
}
在点击事件中,回调这两个方法。
__initTouch() {
let self = this;
this.node.on(cc.Node.EventType.TOUCH_START, function (event) {
//这里回调开始拖拽
self.moveStartCb = self.moveStartCb || function () {
};
self.moveStartCb();
}, this.node);
this.node.on(cc.Node.EventType.TOUCH_MOVE, function (event) {
this.opacity = 100;
let delta = event.touch.getDelta();
this.x += delta.x;
this.y += delta.y;
}, this.node);
this.node.on(cc.Node.EventType.TOUCH_END, function () {
this.opacity = 255;
//这里回调结束拖拽
self.moveEndCb = self.moveEndCb || function () {
};
self.moveEndCb();
}, this.node);
},
在我们的 item-manager.js
文件中,我们在初始化小图片的时候,先把回调方法传递过去。
item.initPic({
texture: self.curTexture,
x: itemWidth * r,
y: itemHeight * l,
w: itemWidth,
h: itemHeight,
posX: posX,
posY: posY,
index: itemIndex
}, self.__moveStart, self.__moveEnd);
回调方法中,我们要播放对应的音效。
__moveStart() {
console.info('start');
cc.loader.loadRes('sound/pick', cc.AudioClip, function (err, clip) {
cc.audioEngine.playEffect(clip, false);
});
},
__moveEnd() {
console.info('end');
cc.loader.loadRes('sound/drop', cc.AudioClip, function (err, clip) {
cc.audioEngine.playEffect(clip, false);
});
}
有的同学会说了,我直接在开始拖拽和结束拖拽那里播放音效不就可以了嘛,为什么还要写回调方法呢?
这是个好问题,大家想想看。
总结
知识点
我们今天学习了如何给咱们的拼图游戏设置背景音乐和点击音效。
主要使用的技术就是 AudioSource
和 AudioEngine
。
我们还分析了 AudioSource
和 AudioEngine
的主要区别及主要使用场景。
这节课很简单,大家试一下就清楚了。
工具就是这么简单,至于怎么用,就看大家的道行了。
下一步
看起来距离我们打造全球最好的拼图游戏又近了一步,但是不得不承认,我们现在还是存在很多问题。
大问题先放一放,我们先处理几个小问题。
PS:第一次写这种系列的教程文章,节奏掌握的不太好,第一篇的内容搞的比较多,讲的也不是很细。感觉第二篇这种就很悠哉。知识点也集中,讲解的也可以做到足够的细。
PPS:所以说,步子还是不要迈的太大,容易扯到蛋。