CocosCreator实现粒子特效播放序列帧动画
本文基于CocosCreator2.2.0,主要是通过修改粒子系统定制引擎实现粒子特效播放序列帧动画的效果。
对于粒子特效播放序列帧动画目前来将引擎是不支持的,不过引擎已经完成了基础的粒子系统,剩下的我们在粒子系统的基础上稍做修改即可实现。
主要的思路就是:将序列帧资源合并到一张大图内,在每个粒子进行更新的时候,根据粒子的frameIndex去计算出正确的UV
自定义引擎设置
首先将引擎的js代码复制出来,然后在项目设置中,设置自定义引擎的javascript代码的位置
关于这一部分的设置,请参考官方文档:引擎定制流程
定制CCParticleSystem
接下来将我们复制出来的javascript引擎文件夹在vscode中打开
找到CCParticleSystem.js文件,打开并编辑
CCParticleSystem是RenderCompoent的子类,它的主要用途就是去储存粒子的renderData,以及选用什么样的assembler去组装我们的renderData,同时还有粒子使用什么样的Material。
关于这块可以参考官方文档:自定义渲染
当你搞清楚了RenderComponent和Assembler,再来做这些定制的工作就会很快速,写起来得心应手。
在ParticleSystem的properies下添加这些属性:
/**
* !#zh 是否启用粒子动画
* @property {boolean} enableAnimation
* @default false
*/
enableAnimation: false,
/**
* !#zh 帧动画贴图的列数
* @property {Number} sizeX
* @default 0
*/
sizeX: 0,
/**
* !#zh 帧动画贴图的行数
* @property {Number} sizeY
* @default 0
*/
sizeY: 0,
/**
* !#zh 帧动画贴图,每一张序列帧图的宽度(需要等宽)
* @property {Number} uv_deltaX
* @default 0
*/
uv_deltaX: 0,
/**
* !#zh 帧动画贴图,每一张序列帧图的高度(需要等高)
* @property {Number} uv_deltaY
* @default 0
*/
uv_deltaY: 0,
/**
* !#zh 帧动画贴图,序列帧动画的帧率(默认60帧)
* @property {Number} uv_deltaY
* @default 0
*/
animationRate: 60
enableAnimation
属性主要用来控制这里粒子是否启用序列帧动画模式。
sizeX
和sizeY
是贴图资源,也就是我们的序列帧大图中,小图的行列数
例如我这里使用的资源的行列数就是2行4列
uv_deltaX
和uv_deltaY
是小图的宽高大小,这里需要每一张小图都是同样的尺寸。方便我们进行计算
ps:其实这里的行列数可以优化掉,当我们的小图尺寸相同的情况下,通过大图的宽高尺寸和小图的宽高尺寸,我们可以计算出行列数,不过我这边不想再去计算了,所以干脆拿出来进行配置
animationRate
是我们这个序列帧动画播放的帧率,默认我们设置为60
CCParticledSystem的修改到这里就完了。我们这里主要是需要通过CCParticleSystem来收集序列帧动画的配置信息。
再进一步,你可以修改CCParticleSystem中的_initWithDictionary
方法,将这几个需要配置的属性的读取也进行改造,这样我们就可以在粒子的plist文件中增加对应字段,方便我们进行配置和管理。这里就不细说了。
particle-simulator.js
particle-simulator,顾名思义,就是粒子的模拟器,它负责了每个粒子的发射,位置更新,颜色更新,旋转度计算,粒子的回收,等等。
文件的一开头,我们就可以看到引擎对于单个粒子的定义:
let Particle = function () {
this.pos = cc.v2(0, 0);
this.startPos = cc.v2(0, 0);
this.color = cc.color(0, 0, 0, 255);
this.deltaColor = {
r: 0, g: 0, b: 0, a: 255};
this.size = 0;
this.deltaSize = 0;
this.rotation = 0;
this.deltaRotation = 0;
this.timeToLive = 0;
this.drawPos = cc.v2(0, 0);
// Mode A
this.dir = cc.v2(0, 0);
this.radialAccel =