我们知道Cocos2d-x的粒子系统是通过加载plist生成的。plist包含两部分内容:粒子系统属性和粒子纹理。但是每次调用create都会对plist进行读取解析,如果重复地使用同一个粒子效果,这样的调用明显是低效冗余的。怎么样对这个过程进行优化呢,我们要做的是,将粒子系统属性和粒子纹理分别抽出。
(1)将粒子系统属性预加载并全局保存,避免每次进行读取。
(2)粒子纹理可视且可以进行纹理打包,加载粒子纹理就和加载普通的图片一样。
本文通过增加ParticleSystemQuad的接口实现对粒子系统属性和纹理帧的直接载入,来提高粒子系统的加载效率和实现内存纹理的优化。

1.ParticleSystemQuad

首先先看下ParticleSystemQuad,ParticleSystemQuad继承于ParticleSystem,拥有后者的所有特性,并且增加了一些新的特性:
(1)粒子大小支持浮点数
(2)支持缩放
(3)支持选择
(4)支持subrect
(5)支持批渲染

ParticleSystemQuad同时也是其他特效的父类,创建一个粒子系统的函数调用顺序为:
?
1
Create→initWithFile→initWithDictionary
在initWithDictionary中对粒子数据和纹理进行了读取和解析(这部分有兴趣的可以直接看源码)。

2.如何优化?

参考initWithDictionary的函参
?
1
staticbool initWithDictionary(ValueMap& dictionary, const std::string& dirname)
设计如下接口,当然你要传入文件名也可以:
?
1
2
staticParticleSystemQuad * create(ValueMap& valueMap, SpriteFrame *frame);
boolinitWithValueMap(ValueMap &valueMap, SpriteFrame* frame);
源码如下:
?
1
2
3
4
5
6
7
8
9
10
11
ParticleSystemQuad * ParticleSystemQuad::create( ValueMap& map, SpriteFrame *frame)
 {
     ParticleSystemQuad *ret =newParticleSystemQuad();
     if(ret && ret->initWithValueMap(map, frame))
     {
         ret->autorelease();
         returnret;
     }
     CC_SAFE_DELETE(ret);
     returnret;
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
boolParticleSystemQuad::initWithValueMap(ValueMap &valueMap, SpriteFrame* frame)
 {
     std::string dirname ="";
     boolret =false;
     unsignedchar*buffer =nullptr;
     unsignedchar*deflated =nullptr;
  
     do
     {
         intmaxParticles = valueMap["maxParticles"].asInt();
         // self, not super
         if(this->initWithTotalParticles(maxParticles))
         {
             // Emitter name in particle designer 2.0
             _configName = valueMap["configName"].asString();
  
             // angle
             _angle = valueMap["angle"].asFloat();
             _angleVar = valueMap["angleVariance"].asFloat();
  
             // duration
             _duration = valueMap["duration"].asFloat();
  
             // blend function
             if(_configName.length()>0)
             {
                 _blendFunc.src = valueMap["blendFuncSource"].asFloat();
0