CCParticleSystem.js 101 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862
  1. /****************************************************************************
  2. Copyright (c) 2008-2010 Ricardo Quesada
  3. Copyright (c) 2011-2012 cocos2d-x.org
  4. Copyright (c) 2013-2014 Chukong Technologies Inc.
  5. http://www.cocos2d-x.org
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. ****************************************************************************/
  22. // ideas taken from:
  23. // . The ocean spray in your face [Jeff Lander]
  24. // http://www.double.co.nz/dust/col0798.pdf
  25. // . Building an Advanced Particle System [John van der Burg]
  26. // http://www.gamasutra.com/features/20000623/vanderburg_01.htm
  27. // . LOVE game engine
  28. // http://love2d.org/
  29. //
  30. //
  31. // Radius mode support, from 71 squared
  32. // http://particledesigner.71squared.com/
  33. //
  34. // IMPORTANT: Particle Designer is supported by cocos2d, but
  35. // 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d,
  36. // cocos2d uses a another approach, but the results are almost identical.
  37. //
  38. // tCCPositionType
  39. // possible types of particle positions
  40. /**
  41. * Structure that contains the values of each particle
  42. * @Class
  43. * @Construct
  44. * @param {cc.Point} [pos=cc.p(0,0)] Position of particle
  45. * @param {cc.Point} [startPos=cc.p(0,0)]
  46. * @param {cc.Color} [color= cc.color(0, 0, 0, 255)]
  47. * @param {cc.Color} [deltaColor=cc.color(0, 0, 0, 255)]
  48. * @param {cc.Size} [size=0]
  49. * @param {cc.Size} [deltaSize=0]
  50. * @param {Number} [rotation=0]
  51. * @param {Number} [deltaRotation=0]
  52. * @param {Number} [timeToLive=0]
  53. * @param {Number} [atlasIndex=0]
  54. * @param {cc.Particle.ModeA} [modeA=]
  55. * @param {cc.Particle.ModeA} [modeB=]
  56. */
  57. cc.Particle = function (pos, startPos, color, deltaColor, size, deltaSize, rotation, deltaRotation, timeToLive, atlasIndex, modeA, modeB) {
  58. this.pos = pos ? pos : cc.p(0,0);
  59. this.startPos = startPos ? startPos : cc.p(0,0);
  60. this.color = color ? color : {r:0, g: 0, b:0, a:255};
  61. this.deltaColor = deltaColor ? deltaColor : {r:0, g: 0, b:0, a:255} ;
  62. this.size = size || 0;
  63. this.deltaSize = deltaSize || 0;
  64. this.rotation = rotation || 0;
  65. this.deltaRotation = deltaRotation || 0;
  66. this.timeToLive = timeToLive || 0;
  67. this.atlasIndex = atlasIndex || 0;
  68. this.modeA = modeA ? modeA : new cc.Particle.ModeA();
  69. this.modeB = modeB ? modeB : new cc.Particle.ModeB();
  70. this.isChangeColor = false;
  71. this.drawPos = cc.p(0, 0);
  72. };
  73. /**
  74. * Mode A: gravity, direction, radial accel, tangential accel
  75. * @Class
  76. * @Construct
  77. * @param {cc.Point} dir direction of particle
  78. * @param {Number} radialAccel
  79. * @param {Number} tangentialAccel
  80. */
  81. cc.Particle.ModeA = function (dir, radialAccel, tangentialAccel) {
  82. this.dir = dir ? dir : cc.p(0,0);
  83. this.radialAccel = radialAccel || 0;
  84. this.tangentialAccel = tangentialAccel || 0;
  85. };
  86. /**
  87. * Mode B: radius mode
  88. * @Class
  89. * @Construct
  90. * @param {Number} angle
  91. * @param {Number} degreesPerSecond
  92. * @param {Number} radius
  93. * @param {Number} deltaRadius
  94. */
  95. cc.Particle.ModeB = function (angle, degreesPerSecond, radius, deltaRadius) {
  96. this.angle = angle || 0;
  97. this.degreesPerSecond = degreesPerSecond || 0;
  98. this.radius = radius || 0;
  99. this.deltaRadius = deltaRadius || 0;
  100. };
  101. /**
  102. * Array of Point instances used to optimize particle updates
  103. */
  104. cc.Particle.TemporaryPoints = [
  105. cc.p(),
  106. cc.p(),
  107. cc.p(),
  108. cc.p()
  109. ];
  110. /**
  111. * <p>
  112. * Particle System base class. <br/>
  113. * Attributes of a Particle System:<br/>
  114. * - emmision rate of the particles<br/>
  115. * - Gravity Mode (Mode A): <br/>
  116. * - gravity <br/>
  117. * - direction <br/>
  118. * - speed +- variance <br/>
  119. * - tangential acceleration +- variance<br/>
  120. * - radial acceleration +- variance<br/>
  121. * - Radius Mode (Mode B): <br/>
  122. * - startRadius +- variance <br/>
  123. * - endRadius +- variance <br/>
  124. * - rotate +- variance <br/>
  125. * - Properties common to all modes: <br/>
  126. * - life +- life variance <br/>
  127. * - start spin +- variance <br/>
  128. * - end spin +- variance <br/>
  129. * - start size +- variance <br/>
  130. * - end size +- variance <br/>
  131. * - start color +- variance <br/>
  132. * - end color +- variance <br/>
  133. * - life +- variance <br/>
  134. * - blending function <br/>
  135. * - texture <br/>
  136. * <br/>
  137. * cocos2d also supports particles generated by Particle Designer (http://particledesigner.71squared.com/).<br/>
  138. * 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d, <br/>
  139. * cocos2d uses a another approach, but the results are almost identical.<br/>
  140. * cocos2d supports all the variables used by Particle Designer plus a bit more: <br/>
  141. * - spinning particles (supported when using ParticleSystem) <br/>
  142. * - tangential acceleration (Gravity mode) <br/>
  143. * - radial acceleration (Gravity mode) <br/>
  144. * - radius direction (Radius mode) (Particle Designer supports outwards to inwards direction only) <br/>
  145. * It is possible to customize any of the above mentioned properties in runtime. Example: <br/>
  146. * </p>
  147. * @class
  148. * @extends cc.Node
  149. *
  150. * @property {Boolean} opacityModifyRGB - Indicate whether the alpha value modify color.
  151. * @property {cc.SpriteBatchNode} batchNode - Weak reference to the sprite batch node.
  152. * @property {Boolean} active - <@readonly> Indicate whether the particle system is activated.
  153. * @property {Number} shapeType - ShapeType of ParticleSystem : cc.ParticleSystem.BALL_SHAPE | cc.ParticleSystem.STAR_SHAPE.
  154. * @property {Number} atlasIndex - Index of system in batch node array.
  155. * @property {Number} particleCount - Current quantity of particles that are being simulated.
  156. * @property {Number} duration - How many seconds the emitter wil run. -1 means 'forever'
  157. * @property {cc.Point} sourcePos - Source position of the emitter.
  158. * @property {cc.Point} posVar - Variation of source position.
  159. * @property {Number} life - Life of each particle setter.
  160. * @property {Number} lifeVar - Variation of life.
  161. * @property {Number} angle - Angle of each particle setter.
  162. * @property {Number} angleVar - Variation of angle of each particle setter.
  163. * @property {Number} startSize - Start size in pixels of each particle.
  164. * @property {Number} startSizeVar - Variation of start size in pixels.
  165. * @property {Number} endSize - End size in pixels of each particle.
  166. * @property {Number} endSizeVar - Variation of end size in pixels.
  167. * @property {Number} startSpin - Start angle of each particle.
  168. * @property {Number} startSpinVar - Variation of start angle.
  169. * @property {Number} endSpin - End angle of each particle.
  170. * @property {Number} endSpinVar - Variation of end angle.
  171. * @property {cc.Point} gravity - Gravity of the emitter.
  172. * @property {cc.Point} speed - Speed of the emitter.
  173. * @property {cc.Point} speedVar - Variation of the speed.
  174. * @property {Number} tangentialAccel - Tangential acceleration of each particle. Only available in 'Gravity' mode.
  175. * @property {Number} tangentialAccelVar - Variation of the tangential acceleration.
  176. * @property {Number} tangentialAccel - Radial acceleration of each particle. Only available in 'Gravity' mode.
  177. * @property {Number} tangentialAccelVar - Variation of the radial acceleration.
  178. * @property {Boolean} rotationIsDir - Indicate whether the rotation of each particle equals to its direction. Only available in 'Gravity' mode.
  179. * @property {Number} startRadius - Starting radius of the particles. Only available in 'Radius' mode.
  180. * @property {Number} startRadiusVar - Variation of the starting radius.
  181. * @property {Number} endRadius - Ending radius of the particles. Only available in 'Radius' mode.
  182. * @property {Number} endRadiusVar - Variation of the ending radius.
  183. * @property {Number} rotatePerS - Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode.
  184. * @property {Number} rotatePerSVar - Variation of the degress to rotate a particle around the source pos per second.
  185. * @property {cc.Color} startColor - Start color of each particle.
  186. * @property {cc.Color} startColorVar - Variation of the start color.
  187. * @property {cc.Color} endColor - Ending color of each particle.
  188. * @property {cc.Color} endColorVar - Variation of the end color.
  189. * @property {Number} emissionRate - Emission rate of the particles.
  190. * @property {Number} emitterMode - Emitter modes: CCParticleSystem.MODE_GRAVITY: uses gravity, speed, radial and tangential acceleration; CCParticleSystem.MODE_RADIUS: uses radius movement + rotation.
  191. * @property {Number} positionType - Particles movement type: cc.ParticleSystem.TYPE_FREE | cc.ParticleSystem.TYPE_GROUPED.
  192. * @property {Number} totalParticles - Maximum particles of the system.
  193. * @property {Boolean} autoRemoveOnFinish - Indicate whether the node will be auto-removed when it has no particles left.
  194. * @property {cc.Texture2D} texture - Texture of Particle System.
  195. *
  196. * @example
  197. * emitter.radialAccel = 15;
  198. * emitter.startSpin = 0;
  199. */
  200. cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{
  201. //***********variables*************
  202. _plistFile: "",
  203. //! time elapsed since the start of the system (in seconds)
  204. _elapsed: 0,
  205. _dontTint: false,
  206. // Different modes
  207. //! Mode A:Gravity + Tangential Accel + Radial Accel
  208. modeA: null,
  209. //! Mode B: circular movement (gravity, radial accel and tangential accel don't are not used in this mode)
  210. modeB: null,
  211. _className:"ParticleSystem",
  212. //private POINTZERO for ParticleSystem
  213. _pointZeroForParticle: cc.p(0, 0),
  214. //! Array of particles
  215. _particles: null,
  216. // color modulate
  217. // BOOL colorModulate;
  218. //! How many particles can be emitted per second
  219. _emitCounter: 0,
  220. //! particle idx
  221. _particleIdx: 0,
  222. _batchNode: null,
  223. atlasIndex: 0,
  224. //true if scaled or rotated
  225. _transformSystemDirty: false,
  226. _allocatedParticles: 0,
  227. //drawMode
  228. drawMode: null,
  229. //shape type
  230. shapeType: null,
  231. _isActive: false,
  232. particleCount: 0,
  233. duration: 0,
  234. _sourcePosition: null,
  235. _posVar: null,
  236. life: 0,
  237. lifeVar: 0,
  238. angle: 0,
  239. angleVar: 0,
  240. startSize: 0,
  241. startSizeVar: 0,
  242. endSize: 0,
  243. endSizeVar: 0,
  244. _startColor: null,
  245. _startColorVar: null,
  246. _endColor: null,
  247. _endColorVar: null,
  248. startSpin: 0,
  249. startSpinVar: 0,
  250. endSpin: 0,
  251. endSpinVar: 0,
  252. emissionRate: 0,
  253. _totalParticles: 0,
  254. _texture: null,
  255. _blendFunc: null,
  256. _opacityModifyRGB: false,
  257. positionType: null,
  258. autoRemoveOnFinish: false,
  259. emitterMode: 0,
  260. // quads to be rendered
  261. _quads:null,
  262. // indices
  263. _indices:null,
  264. //_VAOname:0,
  265. //0: vertex 1: indices
  266. _buffersVBO:null,
  267. _pointRect:null,
  268. _textureLoaded: null,
  269. _quadsArrayBuffer:null,
  270. /**
  271. * <p> return the string found by key in dict. <br/>
  272. * This plist files can be create manually or with Particle Designer:<br/>
  273. * http://particledesigner.71squared.com/<br/>
  274. * </p>
  275. * Constructor of cc.ParticleSystem
  276. * @param {String|Number} plistFile
  277. */
  278. ctor:function (plistFile) {
  279. cc.Node.prototype.ctor.call(this);
  280. this.emitterMode = cc.ParticleSystem.MODE_GRAVITY;
  281. this.modeA = new cc.ParticleSystem.ModeA();
  282. this.modeB = new cc.ParticleSystem.ModeB();
  283. this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST};
  284. this._particles = [];
  285. this._sourcePosition = cc.p(0, 0);
  286. this._posVar = cc.p(0, 0);
  287. this._startColor = cc.color(255, 255, 255, 255);
  288. this._startColorVar = cc.color(255, 255, 255, 255);
  289. this._endColor = cc.color(255, 255, 255, 255);
  290. this._endColorVar = cc.color(255, 255, 255, 255);
  291. this._plistFile = "";
  292. this._elapsed = 0;
  293. this._dontTint = false;
  294. this._pointZeroForParticle = cc.p(0, 0);
  295. this._emitCounter = 0;
  296. this._particleIdx = 0;
  297. this._batchNode = null;
  298. this.atlasIndex = 0;
  299. this._transformSystemDirty = false;
  300. this._allocatedParticles = 0;
  301. this.drawMode = cc.ParticleSystem.SHAPE_MODE;
  302. this.shapeType = cc.ParticleSystem.BALL_SHAPE;
  303. this._isActive = false;
  304. this.particleCount = 0;
  305. this.duration = 0;
  306. this.life = 0;
  307. this.lifeVar = 0;
  308. this.angle = 0;
  309. this.angleVar = 0;
  310. this.startSize = 0;
  311. this.startSizeVar = 0;
  312. this.endSize = 0;
  313. this.endSizeVar = 0;
  314. this.startSpin = 0;
  315. this.startSpinVar = 0;
  316. this.endSpin = 0;
  317. this.endSpinVar = 0;
  318. this.emissionRate = 0;
  319. this._totalParticles = 0;
  320. this._texture = null;
  321. this._opacityModifyRGB = false;
  322. this.positionType = cc.ParticleSystem.TYPE_FREE;
  323. this.autoRemoveOnFinish = false;
  324. this._buffersVBO = [0, 0];
  325. this._quads = [];
  326. this._indices = [];
  327. this._pointRect = cc.rect(0, 0, 0, 0);
  328. this._textureLoaded = true;
  329. if (cc._renderType === cc._RENDER_TYPE_WEBGL) {
  330. this._quadsArrayBuffer = null;
  331. }
  332. if (!plistFile || typeof(plistFile) === "number") {
  333. var ton = plistFile || 100;
  334. this.setDrawMode(cc.ParticleSystem.TEXTURE_MODE);
  335. this.initWithTotalParticles(ton);
  336. } else if (plistFile) {
  337. this.initWithFile(plistFile);
  338. }
  339. },
  340. /**
  341. * initializes the indices for the vertices
  342. */
  343. initIndices:function () {
  344. var locIndices = this._indices;
  345. for (var i = 0, len = this._totalParticles; i < len; ++i) {
  346. var i6 = i * 6;
  347. var i4 = i * 4;
  348. locIndices[i6 + 0] = i4 + 0;
  349. locIndices[i6 + 1] = i4 + 1;
  350. locIndices[i6 + 2] = i4 + 2;
  351. locIndices[i6 + 5] = i4 + 1;
  352. locIndices[i6 + 4] = i4 + 2;
  353. locIndices[i6 + 3] = i4 + 3;
  354. }
  355. },
  356. /**
  357. * <p> initializes the texture with a rectangle measured Points<br/>
  358. * pointRect should be in Texture coordinates, not pixel coordinates
  359. * </p>
  360. * @param {cc.Rect} pointRect
  361. */
  362. initTexCoordsWithRect:function (pointRect) {
  363. var scaleFactor = cc.contentScaleFactor();
  364. // convert to pixels coords
  365. var rect = cc.rect(
  366. pointRect.x * scaleFactor,
  367. pointRect.y * scaleFactor,
  368. pointRect.width * scaleFactor,
  369. pointRect.height * scaleFactor);
  370. var wide = pointRect.width;
  371. var high = pointRect.height;
  372. if (this._texture) {
  373. wide = this._texture.pixelsWidth;
  374. high = this._texture.pixelsHeight;
  375. }
  376. if(cc._renderType === cc._RENDER_TYPE_CANVAS)
  377. return;
  378. var left, bottom, right, top;
  379. if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
  380. left = (rect.x * 2 + 1) / (wide * 2);
  381. bottom = (rect.y * 2 + 1) / (high * 2);
  382. right = left + (rect.width * 2 - 2) / (wide * 2);
  383. top = bottom + (rect.height * 2 - 2) / (high * 2);
  384. } else {
  385. left = rect.x / wide;
  386. bottom = rect.y / high;
  387. right = left + rect.width / wide;
  388. top = bottom + rect.height / high;
  389. }
  390. // Important. Texture in cocos2d are inverted, so the Y component should be inverted
  391. var temp = top;
  392. top = bottom;
  393. bottom = temp;
  394. var quads;
  395. var start = 0, end = 0;
  396. if (this._batchNode) {
  397. quads = this._batchNode.textureAtlas.quads;
  398. start = this.atlasIndex;
  399. end = this.atlasIndex + this._totalParticles;
  400. } else {
  401. quads = this._quads;
  402. start = 0;
  403. end = this._totalParticles;
  404. }
  405. for (var i = start; i < end; i++) {
  406. if (!quads[i])
  407. quads[i] = cc.V3F_C4B_T2F_QuadZero();
  408. // bottom-left vertex:
  409. var selQuad = quads[i];
  410. selQuad.bl.texCoords.u = left;
  411. selQuad.bl.texCoords.v = bottom;
  412. // bottom-right vertex:
  413. selQuad.br.texCoords.u = right;
  414. selQuad.br.texCoords.v = bottom;
  415. // top-left vertex:
  416. selQuad.tl.texCoords.u = left;
  417. selQuad.tl.texCoords.v = top;
  418. // top-right vertex:
  419. selQuad.tr.texCoords.u = right;
  420. selQuad.tr.texCoords.v = top;
  421. }
  422. },
  423. /**
  424. * return weak reference to the cc.SpriteBatchNode that renders the cc.Sprite
  425. * @return {cc.ParticleBatchNode}
  426. */
  427. getBatchNode:function () {
  428. return this._batchNode;
  429. },
  430. /**
  431. * set weak reference to the cc.SpriteBatchNode that renders the cc.Sprite
  432. * @param {cc.ParticleBatchNode} batchNode
  433. */
  434. setBatchNode:function (batchNode) {
  435. if (this._batchNode != batchNode) {
  436. var oldBatch = this._batchNode;
  437. this._batchNode = batchNode; //weak reference
  438. if (batchNode) {
  439. var locParticles = this._particles;
  440. for (var i = 0; i < this._totalParticles; i++)
  441. locParticles[i].atlasIndex = i;
  442. }
  443. // NEW: is self render ?
  444. if (!batchNode) {
  445. this._allocMemory();
  446. this.initIndices();
  447. this.setTexture(oldBatch.getTexture());
  448. //if (cc.TEXTURE_ATLAS_USE_VAO)
  449. // this._setupVBOandVAO();
  450. //else
  451. this._setupVBO();
  452. } else if (!oldBatch) {
  453. // OLD: was it self render cleanup ?
  454. // copy current state to batch
  455. this._batchNode.textureAtlas._copyQuadsToTextureAtlas(this._quads, this.atlasIndex);
  456. //delete buffer
  457. cc._renderContext.deleteBuffer(this._buffersVBO[1]); //where is re-bindBuffer code?
  458. //if (cc.TEXTURE_ATLAS_USE_VAO)
  459. // glDeleteVertexArrays(1, this._VAOname);
  460. }
  461. }
  462. },
  463. /**
  464. * return index of system in batch node array
  465. * @return {Number}
  466. */
  467. getAtlasIndex:function () {
  468. return this.atlasIndex;
  469. },
  470. /**
  471. * set index of system in batch node array
  472. * @param {Number} atlasIndex
  473. */
  474. setAtlasIndex:function (atlasIndex) {
  475. this.atlasIndex = atlasIndex;
  476. },
  477. /**
  478. * Return DrawMode of ParticleSystem
  479. * @return {Number}
  480. */
  481. getDrawMode:function () {
  482. return this.drawMode;
  483. },
  484. /**
  485. * DrawMode of ParticleSystem setter
  486. * @param {Number} drawMode
  487. */
  488. setDrawMode:function (drawMode) {
  489. this.drawMode = drawMode;
  490. },
  491. /**
  492. * Return ShapeType of ParticleSystem
  493. * @return {Number}
  494. */
  495. getShapeType:function () {
  496. return this.shapeType;
  497. },
  498. /**
  499. * ShapeType of ParticleSystem setter
  500. * @param {Number} shapeType
  501. */
  502. setShapeType:function (shapeType) {
  503. this.shapeType = shapeType;
  504. },
  505. /**
  506. * Return ParticleSystem is active
  507. * @return {Boolean}
  508. */
  509. isActive:function () {
  510. return this._isActive;
  511. },
  512. /**
  513. * Quantity of particles that are being simulated at the moment
  514. * @return {Number}
  515. */
  516. getParticleCount:function () {
  517. return this.particleCount;
  518. },
  519. /**
  520. * Quantity of particles setter
  521. * @param {Number} particleCount
  522. */
  523. setParticleCount:function (particleCount) {
  524. this.particleCount = particleCount;
  525. },
  526. /**
  527. * How many seconds the emitter wil run. -1 means 'forever'
  528. * @return {Number}
  529. */
  530. getDuration:function () {
  531. return this.duration;
  532. },
  533. /**
  534. * set run seconds of the emitter
  535. * @param {Number} duration
  536. */
  537. setDuration:function (duration) {
  538. this.duration = duration;
  539. },
  540. /**
  541. * Return sourcePosition of the emitter
  542. * @return {cc.Point | Object}
  543. */
  544. getSourcePosition:function () {
  545. return {x:this._sourcePosition.x, y:this._sourcePosition.y};
  546. },
  547. /**
  548. * sourcePosition of the emitter setter
  549. * @param sourcePosition
  550. */
  551. setSourcePosition:function (sourcePosition) {
  552. this._sourcePosition = sourcePosition;
  553. },
  554. /**
  555. * Return Position variance of the emitter
  556. * @return {cc.Point | Object}
  557. */
  558. getPosVar:function () {
  559. return {x: this._posVar.x, y: this._posVar.y};
  560. },
  561. /**
  562. * Position variance of the emitter setter
  563. * @param {cc.Point} posVar
  564. */
  565. setPosVar:function (posVar) {
  566. this._posVar = posVar;
  567. },
  568. /**
  569. * Return life of each particle
  570. * @return {Number}
  571. */
  572. getLife:function () {
  573. return this.life;
  574. },
  575. /**
  576. * life of each particle setter
  577. * @param {Number} life
  578. */
  579. setLife:function (life) {
  580. this.life = life;
  581. },
  582. /**
  583. * Return life variance of each particle
  584. * @return {Number}
  585. */
  586. getLifeVar:function () {
  587. return this.lifeVar;
  588. },
  589. /**
  590. * life variance of each particle setter
  591. * @param {Number} lifeVar
  592. */
  593. setLifeVar:function (lifeVar) {
  594. this.lifeVar = lifeVar;
  595. },
  596. /**
  597. * Return angle of each particle
  598. * @return {Number}
  599. */
  600. getAngle:function () {
  601. return this.angle;
  602. },
  603. /**
  604. * angle of each particle setter
  605. * @param {Number} angle
  606. */
  607. setAngle:function (angle) {
  608. this.angle = angle;
  609. },
  610. /**
  611. * Return angle variance of each particle
  612. * @return {Number}
  613. */
  614. getAngleVar:function () {
  615. return this.angleVar;
  616. },
  617. /**
  618. * angle variance of each particle setter
  619. * @param angleVar
  620. */
  621. setAngleVar:function (angleVar) {
  622. this.angleVar = angleVar;
  623. },
  624. // mode A
  625. /**
  626. * Return Gravity of emitter
  627. * @return {cc.Point}
  628. */
  629. getGravity:function () {
  630. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  631. cc.log("cc.ParticleBatchNode.getGravity() : Particle Mode should be Gravity");
  632. var locGravity = this.modeA.gravity;
  633. return cc.p(locGravity.x, locGravity.y);
  634. },
  635. /**
  636. * Gravity of emitter setter
  637. * @param {cc.Point} gravity
  638. */
  639. setGravity:function (gravity) {
  640. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  641. cc.log("cc.ParticleBatchNode.setGravity() : Particle Mode should be Gravity");
  642. this.modeA.gravity = gravity;
  643. },
  644. /**
  645. * Return Speed of each particle
  646. * @return {Number}
  647. */
  648. getSpeed:function () {
  649. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  650. cc.log("cc.ParticleBatchNode.getSpeed() : Particle Mode should be Gravity");
  651. return this.modeA.speed;
  652. },
  653. /**
  654. * Speed of each particle setter
  655. * @param {Number} speed
  656. */
  657. setSpeed:function (speed) {
  658. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  659. cc.log("cc.ParticleBatchNode.setSpeed() : Particle Mode should be Gravity");
  660. this.modeA.speed = speed;
  661. },
  662. /**
  663. * return speed variance of each particle. Only available in 'Gravity' mode.
  664. * @return {Number}
  665. */
  666. getSpeedVar:function () {
  667. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  668. cc.log("cc.ParticleBatchNode.getSpeedVar() : Particle Mode should be Gravity");
  669. return this.modeA.speedVar;
  670. },
  671. /**
  672. * speed variance of each particle setter. Only available in 'Gravity' mode.
  673. * @param {Number} speedVar
  674. */
  675. setSpeedVar:function (speedVar) {
  676. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  677. cc.log("cc.ParticleBatchNode.setSpeedVar() : Particle Mode should be Gravity");
  678. this.modeA.speedVar = speedVar;
  679. },
  680. /**
  681. * Return tangential acceleration of each particle. Only available in 'Gravity' mode.
  682. * @return {Number}
  683. */
  684. getTangentialAccel:function () {
  685. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  686. cc.log("cc.ParticleBatchNode.getTangentialAccel() : Particle Mode should be Gravity");
  687. return this.modeA.tangentialAccel;
  688. },
  689. /**
  690. * Tangential acceleration of each particle setter. Only available in 'Gravity' mode.
  691. * @param {Number} tangentialAccel
  692. */
  693. setTangentialAccel:function (tangentialAccel) {
  694. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  695. cc.log("cc.ParticleBatchNode.setTangentialAccel() : Particle Mode should be Gravity");
  696. this.modeA.tangentialAccel = tangentialAccel;
  697. },
  698. /**
  699. * Return tangential acceleration variance of each particle. Only available in 'Gravity' mode.
  700. * @return {Number}
  701. */
  702. getTangentialAccelVar:function () {
  703. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  704. cc.log("cc.ParticleBatchNode.getTangentialAccelVar() : Particle Mode should be Gravity");
  705. return this.modeA.tangentialAccelVar;
  706. },
  707. /**
  708. * tangential acceleration variance of each particle setter. Only available in 'Gravity' mode.
  709. * @param {Number} tangentialAccelVar
  710. */
  711. setTangentialAccelVar:function (tangentialAccelVar) {
  712. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  713. cc.log("cc.ParticleBatchNode.setTangentialAccelVar() : Particle Mode should be Gravity");
  714. this.modeA.tangentialAccelVar = tangentialAccelVar;
  715. },
  716. /**
  717. * Return radial acceleration of each particle. Only available in 'Gravity' mode.
  718. * @return {Number}
  719. */
  720. getRadialAccel:function () {
  721. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  722. cc.log("cc.ParticleBatchNode.getRadialAccel() : Particle Mode should be Gravity");
  723. return this.modeA.radialAccel;
  724. },
  725. /**
  726. * radial acceleration of each particle setter. Only available in 'Gravity' mode.
  727. * @param {Number} radialAccel
  728. */
  729. setRadialAccel:function (radialAccel) {
  730. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  731. cc.log("cc.ParticleBatchNode.setRadialAccel() : Particle Mode should be Gravity");
  732. this.modeA.radialAccel = radialAccel;
  733. },
  734. /**
  735. * Return radial acceleration variance of each particle. Only available in 'Gravity' mode.
  736. * @return {Number}
  737. */
  738. getRadialAccelVar:function () {
  739. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  740. cc.log("cc.ParticleBatchNode.getRadialAccelVar() : Particle Mode should be Gravity");
  741. return this.modeA.radialAccelVar;
  742. },
  743. /**
  744. * radial acceleration variance of each particle setter. Only available in 'Gravity' mode.
  745. * @param {Number} radialAccelVar
  746. */
  747. setRadialAccelVar:function (radialAccelVar) {
  748. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  749. cc.log("cc.ParticleBatchNode.setRadialAccelVar() : Particle Mode should be Gravity");
  750. this.modeA.radialAccelVar = radialAccelVar;
  751. },
  752. /**
  753. * get the rotation of each particle to its direction Only available in 'Gravity' mode.
  754. * @returns {boolean}
  755. */
  756. getRotationIsDir: function(){
  757. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  758. cc.log("cc.ParticleBatchNode.getRotationIsDir() : Particle Mode should be Gravity");
  759. return this.modeA.rotationIsDir;
  760. },
  761. /**
  762. * set the rotation of each particle to its direction Only available in 'Gravity' mode.
  763. * @param {boolean} t
  764. */
  765. setRotationIsDir: function(t){
  766. if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
  767. cc.log("cc.ParticleBatchNode.setRotationIsDir() : Particle Mode should be Gravity");
  768. this.modeA.rotationIsDir = t;
  769. },
  770. // mode B
  771. /**
  772. * Return starting radius of the particles. Only available in 'Radius' mode.
  773. * @return {Number}
  774. */
  775. getStartRadius:function () {
  776. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  777. cc.log("cc.ParticleBatchNode.getStartRadius() : Particle Mode should be Radius");
  778. return this.modeB.startRadius;
  779. },
  780. /**
  781. * starting radius of the particles setter. Only available in 'Radius' mode.
  782. * @param {Number} startRadius
  783. */
  784. setStartRadius:function (startRadius) {
  785. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  786. cc.log("cc.ParticleBatchNode.setStartRadius() : Particle Mode should be Radius");
  787. this.modeB.startRadius = startRadius;
  788. },
  789. /**
  790. * Return starting radius variance of the particles. Only available in 'Radius' mode.
  791. * @return {Number}
  792. */
  793. getStartRadiusVar:function () {
  794. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  795. cc.log("cc.ParticleBatchNode.getStartRadiusVar() : Particle Mode should be Radius");
  796. return this.modeB.startRadiusVar;
  797. },
  798. /**
  799. * starting radius variance of the particles setter. Only available in 'Radius' mode.
  800. * @param {Number} startRadiusVar
  801. */
  802. setStartRadiusVar:function (startRadiusVar) {
  803. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  804. cc.log("cc.ParticleBatchNode.setStartRadiusVar() : Particle Mode should be Radius");
  805. this.modeB.startRadiusVar = startRadiusVar;
  806. },
  807. /**
  808. * Return ending radius of the particles. Only available in 'Radius' mode.
  809. * @return {Number}
  810. */
  811. getEndRadius:function () {
  812. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  813. cc.log("cc.ParticleBatchNode.getEndRadius() : Particle Mode should be Radius");
  814. return this.modeB.endRadius;
  815. },
  816. /**
  817. * ending radius of the particles setter. Only available in 'Radius' mode.
  818. * @param {Number} endRadius
  819. */
  820. setEndRadius:function (endRadius) {
  821. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  822. cc.log("cc.ParticleBatchNode.setEndRadius() : Particle Mode should be Radius");
  823. this.modeB.endRadius = endRadius;
  824. },
  825. /**
  826. * Return ending radius variance of the particles. Only available in 'Radius' mode.
  827. * @return {Number}
  828. */
  829. getEndRadiusVar:function () {
  830. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  831. cc.log("cc.ParticleBatchNode.getEndRadiusVar() : Particle Mode should be Radius");
  832. return this.modeB.endRadiusVar;
  833. },
  834. /**
  835. * ending radius variance of the particles setter. Only available in 'Radius' mode.
  836. * @param endRadiusVar
  837. */
  838. setEndRadiusVar:function (endRadiusVar) {
  839. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  840. cc.log("cc.ParticleBatchNode.setEndRadiusVar() : Particle Mode should be Radius");
  841. this.modeB.endRadiusVar = endRadiusVar;
  842. },
  843. /**
  844. * get Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode.
  845. * @return {Number}
  846. */
  847. getRotatePerSecond:function () {
  848. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  849. cc.log("cc.ParticleBatchNode.getRotatePerSecond() : Particle Mode should be Radius");
  850. return this.modeB.rotatePerSecond;
  851. },
  852. /**
  853. * set Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode.
  854. * @param {Number} degrees
  855. */
  856. setRotatePerSecond:function (degrees) {
  857. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  858. cc.log("cc.ParticleBatchNode.setRotatePerSecond() : Particle Mode should be Radius");
  859. this.modeB.rotatePerSecond = degrees;
  860. },
  861. /**
  862. * Return Variance in degrees for rotatePerSecond. Only available in 'Radius' mode.
  863. * @return {Number}
  864. */
  865. getRotatePerSecondVar:function () {
  866. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  867. cc.log("cc.ParticleBatchNode.getRotatePerSecondVar() : Particle Mode should be Radius");
  868. return this.modeB.rotatePerSecondVar;
  869. },
  870. /**
  871. * Variance in degrees for rotatePerSecond setter. Only available in 'Radius' mode.
  872. * @param degrees
  873. */
  874. setRotatePerSecondVar:function (degrees) {
  875. if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
  876. cc.log("cc.ParticleBatchNode.setRotatePerSecondVar() : Particle Mode should be Radius");
  877. this.modeB.rotatePerSecondVar = degrees;
  878. },
  879. //////////////////////////////////////////////////////////////////////////
  880. //don't use a transform matrix, this is faster
  881. setScale:function (scale, scaleY) {
  882. this._transformSystemDirty = true;
  883. cc.Node.prototype.setScale.call(this, scale, scaleY);
  884. },
  885. setRotation:function (newRotation) {
  886. this._transformSystemDirty = true;
  887. cc.Node.prototype.setRotation.call(this, newRotation);
  888. },
  889. setScaleX:function (newScaleX) {
  890. this._transformSystemDirty = true;
  891. cc.Node.prototype.setScaleX.call(this, newScaleX);
  892. },
  893. setScaleY:function (newScaleY) {
  894. this._transformSystemDirty = true;
  895. cc.Node.prototype.setScaleY.call(this, newScaleY);
  896. },
  897. /**
  898. * get start size in pixels of each particle
  899. * @return {Number}
  900. */
  901. getStartSize:function () {
  902. return this.startSize;
  903. },
  904. /**
  905. * set start size in pixels of each particle
  906. * @param {Number} startSize
  907. */
  908. setStartSize:function (startSize) {
  909. this.startSize = startSize;
  910. },
  911. /**
  912. * get size variance in pixels of each particle
  913. * @return {Number}
  914. */
  915. getStartSizeVar:function () {
  916. return this.startSizeVar;
  917. },
  918. /**
  919. * set size variance in pixels of each particle
  920. * @param {Number} startSizeVar
  921. */
  922. setStartSizeVar:function (startSizeVar) {
  923. this.startSizeVar = startSizeVar;
  924. },
  925. /**
  926. * get end size in pixels of each particle
  927. * @return {Number}
  928. */
  929. getEndSize:function () {
  930. return this.endSize;
  931. },
  932. /**
  933. * set end size in pixels of each particle
  934. * @param endSize
  935. */
  936. setEndSize:function (endSize) {
  937. this.endSize = endSize;
  938. },
  939. /**
  940. * get end size variance in pixels of each particle
  941. * @return {Number}
  942. */
  943. getEndSizeVar:function () {
  944. return this.endSizeVar;
  945. },
  946. /**
  947. * set end size variance in pixels of each particle
  948. * @param {Number} endSizeVar
  949. */
  950. setEndSizeVar:function (endSizeVar) {
  951. this.endSizeVar = endSizeVar;
  952. },
  953. /**
  954. * set start color of each particle
  955. * @return {cc.Color}
  956. */
  957. getStartColor:function () {
  958. return cc.color(this._startColor.r, this._startColor.g, this._startColor.b, this._startColor.a);
  959. },
  960. /**
  961. * get start color of each particle
  962. * @param {cc.Color} startColor
  963. */
  964. setStartColor:function (startColor) {
  965. this._startColor = cc.color(startColor);
  966. },
  967. /**
  968. * get start color variance of each particle
  969. * @return {cc.Color}
  970. */
  971. getStartColorVar:function () {
  972. return cc.color(this._startColorVar.r, this._startColorVar.g, this._startColorVar.b, this._startColorVar.a);
  973. },
  974. /**
  975. * set start color variance of each particle
  976. * @param {cc.Color} startColorVar
  977. */
  978. setStartColorVar:function (startColorVar) {
  979. this._startColorVar = cc.color(startColorVar);
  980. },
  981. /**
  982. * get end color and end color variation of each particle
  983. * @return {cc.Color}
  984. */
  985. getEndColor:function () {
  986. return cc.color(this._endColor.r, this._endColor.g, this._endColor.b, this._endColor.a);
  987. },
  988. /**
  989. * set end color and end color variation of each particle
  990. * @param {cc.Color} endColor
  991. */
  992. setEndColor:function (endColor) {
  993. this._endColor = cc.color(endColor);
  994. },
  995. /**
  996. * get end color variance of each particle
  997. * @return {cc.Color}
  998. */
  999. getEndColorVar:function () {
  1000. return cc.color(this._endColorVar.r, this._endColorVar.g, this._endColorVar.b, this._endColorVar.a);
  1001. },
  1002. /**
  1003. * set end color variance of each particle
  1004. * @param {cc.Color} endColorVar
  1005. */
  1006. setEndColorVar:function (endColorVar) {
  1007. this._endColorVar = cc.color(endColorVar);
  1008. },
  1009. /**
  1010. * get initial angle of each particle
  1011. * @return {Number}
  1012. */
  1013. getStartSpin:function () {
  1014. return this.startSpin;
  1015. },
  1016. /**
  1017. * set initial angle of each particle
  1018. * @param {Number} startSpin
  1019. */
  1020. setStartSpin:function (startSpin) {
  1021. this.startSpin = startSpin;
  1022. },
  1023. /**
  1024. * get initial angle variance of each particle
  1025. * @return {Number}
  1026. */
  1027. getStartSpinVar:function () {
  1028. return this.startSpinVar;
  1029. },
  1030. /**
  1031. * set initial angle variance of each particle
  1032. * @param {Number} startSpinVar
  1033. */
  1034. setStartSpinVar:function (startSpinVar) {
  1035. this.startSpinVar = startSpinVar;
  1036. },
  1037. /**
  1038. * get end angle of each particle
  1039. * @return {Number}
  1040. */
  1041. getEndSpin:function () {
  1042. return this.endSpin;
  1043. },
  1044. /**
  1045. * set end angle of each particle
  1046. * @param {Number} endSpin
  1047. */
  1048. setEndSpin:function (endSpin) {
  1049. this.endSpin = endSpin;
  1050. },
  1051. /**
  1052. * get end angle variance of each particle
  1053. * @return {Number}
  1054. */
  1055. getEndSpinVar:function () {
  1056. return this.endSpinVar;
  1057. },
  1058. /**
  1059. * set end angle variance of each particle
  1060. * @param {Number} endSpinVar
  1061. */
  1062. setEndSpinVar:function (endSpinVar) {
  1063. this.endSpinVar = endSpinVar;
  1064. },
  1065. /**
  1066. * get emission rate of the particles
  1067. * @return {Number}
  1068. */
  1069. getEmissionRate:function () {
  1070. return this.emissionRate;
  1071. },
  1072. /**
  1073. * set emission rate of the particles
  1074. * @param {Number} emissionRate
  1075. */
  1076. setEmissionRate:function (emissionRate) {
  1077. this.emissionRate = emissionRate;
  1078. },
  1079. /**
  1080. * get maximum particles of the system
  1081. * @return {Number}
  1082. */
  1083. getTotalParticles:function () {
  1084. return this._totalParticles;
  1085. },
  1086. /**
  1087. * set maximum particles of the system
  1088. * @param {Number} tp totalParticles
  1089. */
  1090. setTotalParticles:function (tp) {
  1091. //cc.assert(tp <= this._allocatedParticles, "Particle: resizing particle array only supported for quads");
  1092. if (cc._renderType === cc._RENDER_TYPE_CANVAS){
  1093. this._totalParticles = (tp < 200) ? tp : 200;
  1094. return;
  1095. }
  1096. // If we are setting the total numer of particles to a number higher
  1097. // than what is allocated, we need to allocate new arrays
  1098. if (tp > this._allocatedParticles) {
  1099. var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
  1100. // Allocate new memory
  1101. this._indices = new Uint16Array(tp * 6);
  1102. var locQuadsArrayBuffer = new ArrayBuffer(tp * quadSize);
  1103. //TODO need fix
  1104. // Assign pointers
  1105. var locParticles = this._particles;
  1106. locParticles.length = 0;
  1107. var locQuads = this._quads;
  1108. locQuads.length = 0;
  1109. for (var j = 0; j < tp; j++) {
  1110. locParticles[j] = new cc.Particle();
  1111. locQuads[j] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, j * quadSize);
  1112. }
  1113. this._allocatedParticles = tp;
  1114. this._totalParticles = tp;
  1115. // Init particles
  1116. if (this._batchNode) {
  1117. for (var i = 0; i < tp; i++)
  1118. locParticles[i].atlasIndex = i;
  1119. }
  1120. this._quadsArrayBuffer = locQuadsArrayBuffer;
  1121. this.initIndices();
  1122. //if (cc.TEXTURE_ATLAS_USE_VAO)
  1123. // this._setupVBOandVAO();
  1124. //else
  1125. this._setupVBO();
  1126. //set the texture coord
  1127. if(this._texture){
  1128. this.initTexCoordsWithRect(cc.rect(0, 0, this._texture.width, this._texture.height));
  1129. }
  1130. } else
  1131. this._totalParticles = tp;
  1132. this.resetSystem();
  1133. },
  1134. /**
  1135. * get Texture of Particle System
  1136. * @return {cc.Texture2D}
  1137. */
  1138. getTexture:function () {
  1139. return this._texture;
  1140. },
  1141. /**
  1142. * set Texture of Particle System
  1143. * @param {cc.Texture2D } texture
  1144. */
  1145. setTexture:function (texture) {
  1146. if(texture.isLoaded()){
  1147. this.setTextureWithRect(texture, cc.rect(0, 0, texture.width, texture.height));
  1148. } else {
  1149. this._textureLoaded = false;
  1150. texture.addLoadedEventListener(function(sender){
  1151. this._textureLoaded = true;
  1152. this.setTextureWithRect(sender, cc.rect(0, 0, sender.width, sender.height));
  1153. }, this);
  1154. }
  1155. },
  1156. /** conforms to CocosNodeTexture protocol */
  1157. /**
  1158. * get BlendFunc of Particle System
  1159. * @return {cc.BlendFunc}
  1160. */
  1161. getBlendFunc:function () {
  1162. return this._blendFunc;
  1163. },
  1164. /**
  1165. * set BlendFunc of Particle System
  1166. * @param {Number} src
  1167. * @param {Number} dst
  1168. */
  1169. setBlendFunc:function (src, dst) {
  1170. if (dst === undefined) {
  1171. if (this._blendFunc != src) {
  1172. this._blendFunc = src;
  1173. this._updateBlendFunc();
  1174. }
  1175. } else {
  1176. if (this._blendFunc.src != src || this._blendFunc.dst != dst) {
  1177. this._blendFunc = {src:src, dst:dst};
  1178. this._updateBlendFunc();
  1179. }
  1180. }
  1181. },
  1182. /**
  1183. * does the alpha value modify color getter
  1184. * @return {Boolean}
  1185. */
  1186. isOpacityModifyRGB:function () {
  1187. return this._opacityModifyRGB;
  1188. },
  1189. /**
  1190. * does the alpha value modify color setter
  1191. * @param newValue
  1192. */
  1193. setOpacityModifyRGB:function (newValue) {
  1194. this._opacityModifyRGB = newValue;
  1195. },
  1196. /**
  1197. * <p>whether or not the particles are using blend additive.<br/>
  1198. * If enabled, the following blending function will be used.<br/>
  1199. * </p>
  1200. * @return {Boolean}
  1201. * @example
  1202. * source blend function = GL_SRC_ALPHA;
  1203. * dest blend function = GL_ONE;
  1204. */
  1205. isBlendAdditive:function () {
  1206. return (( this._blendFunc.src == cc.SRC_ALPHA && this._blendFunc.dst == cc.ONE) || (this._blendFunc.src == cc.ONE && this._blendFunc.dst == cc.ONE));
  1207. },
  1208. /**
  1209. * <p>whether or not the particles are using blend additive.<br/>
  1210. * If enabled, the following blending function will be used.<br/>
  1211. * </p>
  1212. * @param {Boolean} isBlendAdditive
  1213. */
  1214. setBlendAdditive:function (isBlendAdditive) {
  1215. var locBlendFunc = this._blendFunc;
  1216. if (isBlendAdditive) {
  1217. locBlendFunc.src = cc.SRC_ALPHA;
  1218. locBlendFunc.dst = cc.ONE;
  1219. } else {
  1220. if (cc._renderType === cc._RENDER_TYPE_WEBGL) {
  1221. if (this._texture && !this._texture.hasPremultipliedAlpha()) {
  1222. locBlendFunc.src = cc.SRC_ALPHA;
  1223. locBlendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
  1224. } else {
  1225. locBlendFunc.src = cc.BLEND_SRC;
  1226. locBlendFunc.dst = cc.BLEND_DST;
  1227. }
  1228. } else {
  1229. locBlendFunc.src = cc.BLEND_SRC;
  1230. locBlendFunc.dst = cc.BLEND_DST;
  1231. }
  1232. }
  1233. },
  1234. /**
  1235. * get particles movement type: Free or Grouped
  1236. * @return {Number}
  1237. */
  1238. getPositionType:function () {
  1239. return this.positionType;
  1240. },
  1241. /**
  1242. * set particles movement type: Free or Grouped
  1243. * @param {Number} positionType
  1244. */
  1245. setPositionType:function (positionType) {
  1246. this.positionType = positionType;
  1247. },
  1248. /**
  1249. * <p> return whether or not the node will be auto-removed when it has no particles left.<br/>
  1250. * By default it is false.<br/>
  1251. * </p>
  1252. * @return {Boolean}
  1253. */
  1254. isAutoRemoveOnFinish:function () {
  1255. return this.autoRemoveOnFinish;
  1256. },
  1257. /**
  1258. * <p> set whether or not the node will be auto-removed when it has no particles left.<br/>
  1259. * By default it is false.<br/>
  1260. * </p>
  1261. * @param {Boolean} isAutoRemoveOnFinish
  1262. */
  1263. setAutoRemoveOnFinish:function (isAutoRemoveOnFinish) {
  1264. this.autoRemoveOnFinish = isAutoRemoveOnFinish;
  1265. },
  1266. /**
  1267. * return kind of emitter modes
  1268. * @return {Number}
  1269. */
  1270. getEmitterMode:function () {
  1271. return this.emitterMode;
  1272. },
  1273. /**
  1274. * <p>Switch between different kind of emitter modes:<br/>
  1275. * - CCParticleSystem.MODE_GRAVITY: uses gravity, speed, radial and tangential acceleration<br/>
  1276. * - CCParticleSystem.MODE_RADIUS: uses radius movement + rotation <br/>
  1277. * </p>
  1278. * @param {Number} emitterMode
  1279. */
  1280. setEmitterMode:function (emitterMode) {
  1281. this.emitterMode = emitterMode;
  1282. },
  1283. /**
  1284. * initializes a cc.ParticleSystem
  1285. */
  1286. init:function () {
  1287. return this.initWithTotalParticles(150);
  1288. },
  1289. /**
  1290. * <p>
  1291. * initializes a CCParticleSystem from a plist file. <br/>
  1292. * This plist files can be creted manually or with Particle Designer:<br/>
  1293. * http://particledesigner.71squared.com/
  1294. * </p>
  1295. * @param {String} plistFile
  1296. * @return {boolean}
  1297. */
  1298. initWithFile:function (plistFile) {
  1299. this._plistFile = plistFile;
  1300. var dict = cc.loader.getRes(plistFile);
  1301. if(!dict){
  1302. cc.log("cc.ParticleSystem.initWithFile(): Particles: file not found");
  1303. return false;
  1304. }
  1305. // XXX compute path from a path, should define a function somewhere to do it
  1306. return this.initWithDictionary(dict, "");
  1307. },
  1308. /**
  1309. * return bounding box of particle system in world space
  1310. * @return {cc.Rect}
  1311. */
  1312. getBoundingBoxToWorld:function () {
  1313. return cc.rect(0, 0, cc._canvas.width, cc._canvas.height);
  1314. },
  1315. /**
  1316. * initializes a particle system from a NSDictionary and the path from where to load the png
  1317. * @param {object} dictionary
  1318. * @param {String} dirname
  1319. * @return {Boolean}
  1320. */
  1321. initWithDictionary:function (dictionary, dirname) {
  1322. var ret = false;
  1323. var buffer = null;
  1324. var image = null;
  1325. var locValueForKey = this._valueForKey;
  1326. var maxParticles = parseInt(locValueForKey("maxParticles", dictionary));
  1327. // self, not super
  1328. if (this.initWithTotalParticles(maxParticles)) {
  1329. // angle
  1330. this.angle = parseFloat(locValueForKey("angle", dictionary));
  1331. this.angleVar = parseFloat(locValueForKey("angleVariance", dictionary));
  1332. // duration
  1333. this.duration = parseFloat(locValueForKey("duration", dictionary));
  1334. // blend function
  1335. this._blendFunc.src = parseInt(locValueForKey("blendFuncSource", dictionary));
  1336. this._blendFunc.dst = parseInt(locValueForKey("blendFuncDestination", dictionary));
  1337. // color
  1338. var locStartColor = this._startColor;
  1339. locStartColor.r = parseFloat(locValueForKey("startColorRed", dictionary)) * 255;
  1340. locStartColor.g = parseFloat(locValueForKey("startColorGreen", dictionary)) * 255;
  1341. locStartColor.b = parseFloat(locValueForKey("startColorBlue", dictionary)) * 255;
  1342. locStartColor.a = parseFloat(locValueForKey("startColorAlpha", dictionary)) * 255;
  1343. var locStartColorVar = this._startColorVar;
  1344. locStartColorVar.r = parseFloat(locValueForKey("startColorVarianceRed", dictionary)) * 255;
  1345. locStartColorVar.g = parseFloat(locValueForKey("startColorVarianceGreen", dictionary)) * 255;
  1346. locStartColorVar.b = parseFloat(locValueForKey("startColorVarianceBlue", dictionary)) * 255;
  1347. locStartColorVar.a = parseFloat(locValueForKey("startColorVarianceAlpha", dictionary)) * 255;
  1348. var locEndColor = this._endColor;
  1349. locEndColor.r = parseFloat(locValueForKey("finishColorRed", dictionary)) * 255;
  1350. locEndColor.g = parseFloat(locValueForKey("finishColorGreen", dictionary)) * 255;
  1351. locEndColor.b = parseFloat(locValueForKey("finishColorBlue", dictionary)) * 255;
  1352. locEndColor.a = parseFloat(locValueForKey("finishColorAlpha", dictionary)) * 255;
  1353. var locEndColorVar = this._endColorVar;
  1354. locEndColorVar.r = parseFloat(locValueForKey("finishColorVarianceRed", dictionary)) * 255;
  1355. locEndColorVar.g = parseFloat(locValueForKey("finishColorVarianceGreen", dictionary)) * 255;
  1356. locEndColorVar.b = parseFloat(locValueForKey("finishColorVarianceBlue", dictionary)) * 255;
  1357. locEndColorVar.a = parseFloat(locValueForKey("finishColorVarianceAlpha", dictionary)) * 255;
  1358. // particle size
  1359. this.startSize = parseFloat(locValueForKey("startParticleSize", dictionary));
  1360. this.startSizeVar = parseFloat(locValueForKey("startParticleSizeVariance", dictionary));
  1361. this.endSize = parseFloat(locValueForKey("finishParticleSize", dictionary));
  1362. this.endSizeVar = parseFloat(locValueForKey("finishParticleSizeVariance", dictionary));
  1363. // position
  1364. this.setPosition(parseFloat(locValueForKey("sourcePositionx", dictionary)),
  1365. parseFloat(locValueForKey("sourcePositiony", dictionary)));
  1366. this._posVar.x = parseFloat(locValueForKey("sourcePositionVariancex", dictionary));
  1367. this._posVar.y = parseFloat(locValueForKey("sourcePositionVariancey", dictionary));
  1368. // Spinning
  1369. this.startSpin = parseFloat(locValueForKey("rotationStart", dictionary));
  1370. this.startSpinVar = parseFloat(locValueForKey("rotationStartVariance", dictionary));
  1371. this.endSpin = parseFloat(locValueForKey("rotationEnd", dictionary));
  1372. this.endSpinVar = parseFloat(locValueForKey("rotationEndVariance", dictionary));
  1373. this.emitterMode = parseInt(locValueForKey("emitterType", dictionary));
  1374. // Mode A: Gravity + tangential accel + radial accel
  1375. if (this.emitterMode == cc.ParticleSystem.MODE_GRAVITY) {
  1376. var locModeA = this.modeA;
  1377. // gravity
  1378. locModeA.gravity.x = parseFloat(locValueForKey("gravityx", dictionary));
  1379. locModeA.gravity.y = parseFloat(locValueForKey("gravityy", dictionary));
  1380. // speed
  1381. locModeA.speed = parseFloat(locValueForKey("speed", dictionary));
  1382. locModeA.speedVar = parseFloat(locValueForKey("speedVariance", dictionary));
  1383. // radial acceleration
  1384. var pszTmp = locValueForKey("radialAcceleration", dictionary);
  1385. locModeA.radialAccel = (pszTmp) ? parseFloat(pszTmp) : 0;
  1386. pszTmp = locValueForKey("radialAccelVariance", dictionary);
  1387. locModeA.radialAccelVar = (pszTmp) ? parseFloat(pszTmp) : 0;
  1388. // tangential acceleration
  1389. pszTmp = locValueForKey("tangentialAcceleration", dictionary);
  1390. locModeA.tangentialAccel = (pszTmp) ? parseFloat(pszTmp) : 0;
  1391. pszTmp = locValueForKey("tangentialAccelVariance", dictionary);
  1392. locModeA.tangentialAccelVar = (pszTmp) ? parseFloat(pszTmp) : 0;
  1393. // rotation is dir
  1394. var locRotationIsDir = locValueForKey("rotationIsDir", dictionary).toLowerCase();
  1395. locModeA.rotationIsDir = (locRotationIsDir != null && (locRotationIsDir === "true" || locRotationIsDir === "1"));
  1396. } else if (this.emitterMode == cc.ParticleSystem.MODE_RADIUS) {
  1397. // or Mode B: radius movement
  1398. var locModeB = this.modeB;
  1399. locModeB.startRadius = parseFloat(locValueForKey("maxRadius", dictionary));
  1400. locModeB.startRadiusVar = parseFloat(locValueForKey("maxRadiusVariance", dictionary));
  1401. locModeB.endRadius = parseFloat(locValueForKey("minRadius", dictionary));
  1402. locModeB.endRadiusVar = 0;
  1403. locModeB.rotatePerSecond = parseFloat(locValueForKey("rotatePerSecond", dictionary));
  1404. locModeB.rotatePerSecondVar = parseFloat(locValueForKey("rotatePerSecondVariance", dictionary));
  1405. } else {
  1406. cc.log("cc.ParticleSystem.initWithDictionary(): Invalid emitterType in config file");
  1407. return false;
  1408. }
  1409. // life span
  1410. this.life = parseFloat(locValueForKey("particleLifespan", dictionary));
  1411. this.lifeVar = parseFloat(locValueForKey("particleLifespanVariance", dictionary));
  1412. // emission Rate
  1413. this.emissionRate = this._totalParticles / this.life;
  1414. //don't get the internal texture if a batchNode is used
  1415. if (!this._batchNode) {
  1416. // Set a compatible default for the alpha transfer
  1417. this._opacityModifyRGB = false;
  1418. // texture
  1419. // Try to get the texture from the cache
  1420. var textureName = locValueForKey("textureFileName", dictionary);
  1421. var imgPath = cc.path.changeBasename(this._plistFile, textureName);
  1422. var tex = cc.textureCache.getTextureForKey(imgPath);
  1423. if (tex) {
  1424. this.setTexture(tex);
  1425. } else {
  1426. var textureData = locValueForKey("textureImageData", dictionary);
  1427. if (!textureData || textureData.length === 0) {
  1428. tex = cc.textureCache.addImage(imgPath);
  1429. if (!tex)
  1430. return false;
  1431. this.setTexture(tex);
  1432. } else {
  1433. buffer = cc.unzipBase64AsArray(textureData, 1);
  1434. if (!buffer) {
  1435. cc.log("cc.ParticleSystem: error decoding or ungzipping textureImageData");
  1436. return false;
  1437. }
  1438. var imageFormat = cc.getImageFormatByData(buffer);
  1439. if(imageFormat !== cc.FMT_TIFF && imageFormat !== cc.FMT_PNG){
  1440. cc.log("cc.ParticleSystem: unknown image format with Data");
  1441. return false;
  1442. }
  1443. var canvasObj = cc.newElement("canvas");
  1444. if(imageFormat === cc.FMT_PNG){
  1445. var myPngObj = new cc.PNGReader(buffer);
  1446. myPngObj.render(canvasObj);
  1447. } else {
  1448. var myTIFFObj = cc.tiffReader;
  1449. myTIFFObj.parseTIFF(buffer,canvasObj);
  1450. }
  1451. cc.textureCache.cacheImage(imgPath, canvasObj);
  1452. var addTexture = cc.textureCache.getTextureForKey(imgPath);
  1453. if(!addTexture)
  1454. cc.log("cc.ParticleSystem.initWithDictionary() : error loading the texture");
  1455. this.setTexture(addTexture);
  1456. }
  1457. }
  1458. }
  1459. ret = true;
  1460. }
  1461. return ret;
  1462. },
  1463. /**
  1464. * Initializes a system with a fixed number of particles
  1465. * @param {Number} numberOfParticles
  1466. * @return {Boolean}
  1467. */
  1468. initWithTotalParticles:function (numberOfParticles) {
  1469. this._totalParticles = numberOfParticles;
  1470. var i, locParticles = this._particles;
  1471. locParticles.length = 0;
  1472. for(i = 0; i< numberOfParticles; i++){
  1473. locParticles[i] = new cc.Particle();
  1474. }
  1475. if (!locParticles) {
  1476. cc.log("Particle system: not enough memory");
  1477. return false;
  1478. }
  1479. this._allocatedParticles = numberOfParticles;
  1480. if (this._batchNode)
  1481. for (i = 0; i < this._totalParticles; i++)
  1482. locParticles[i].atlasIndex = i;
  1483. // default, active
  1484. this._isActive = true;
  1485. // default blend function
  1486. this._blendFunc.src = cc.BLEND_SRC;
  1487. this._blendFunc.dst = cc.BLEND_DST;
  1488. // default movement type;
  1489. this.positionType = cc.ParticleSystem.TYPE_FREE;
  1490. // by default be in mode A:
  1491. this.emitterMode = cc.ParticleSystem.MODE_GRAVITY;
  1492. // default: modulate
  1493. // XXX: not used
  1494. // colorModulate = YES;
  1495. this.autoRemoveOnFinish = false;
  1496. //for batchNode
  1497. this._transformSystemDirty = false;
  1498. // udpate after action in run!
  1499. this.scheduleUpdateWithPriority(1);
  1500. if(cc._renderType === cc._RENDER_TYPE_WEBGL){
  1501. // allocating data space
  1502. if (!this._allocMemory())
  1503. return false;
  1504. this.initIndices();
  1505. //if (cc.TEXTURE_ATLAS_USE_VAO)
  1506. // this._setupVBOandVAO();
  1507. //else
  1508. this._setupVBO();
  1509. this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
  1510. }
  1511. return true;
  1512. },
  1513. /**
  1514. * Unschedules the "update" method.
  1515. * @function
  1516. * @see scheduleUpdate();
  1517. */
  1518. destroyParticleSystem:function () {
  1519. this.unscheduleUpdate();
  1520. },
  1521. /**
  1522. * Add a particle to the emitter
  1523. * @return {Boolean}
  1524. */
  1525. addParticle: function () {
  1526. if (this.isFull())
  1527. return false;
  1528. var particle, particles = this._particles;
  1529. if (cc._renderType === cc._RENDER_TYPE_CANVAS) {
  1530. if (this.particleCount < particles.length) {
  1531. particle = particles[this.particleCount];
  1532. } else {
  1533. particle = new cc.Particle();
  1534. particles.push(particle);
  1535. }
  1536. } else {
  1537. particle = particles[this.particleCount];
  1538. }
  1539. this.initParticle(particle);
  1540. ++this.particleCount;
  1541. return true;
  1542. },
  1543. /**
  1544. * Initializes a particle
  1545. * @param {cc.Particle} particle
  1546. */
  1547. initParticle:function (particle) {
  1548. var locRandomMinus11 = cc.randomMinus1To1;
  1549. // timeToLive
  1550. // no negative life. prevent division by 0
  1551. particle.timeToLive = this.life + this.lifeVar * locRandomMinus11();
  1552. particle.timeToLive = Math.max(0, particle.timeToLive);
  1553. // position
  1554. particle.pos.x = this._sourcePosition.x + this._posVar.x * locRandomMinus11();
  1555. particle.pos.y = this._sourcePosition.y + this._posVar.y * locRandomMinus11();
  1556. // Color
  1557. var start, end;
  1558. var locStartColor = this._startColor, locStartColorVar = this._startColorVar;
  1559. var locEndColor = this._endColor, locEndColorVar = this._endColorVar;
  1560. if (cc._renderType === cc._RENDER_TYPE_CANVAS) {
  1561. start = cc.color(
  1562. cc.clampf(locStartColor.r + locStartColorVar.r * locRandomMinus11(), 0, 255),
  1563. cc.clampf(locStartColor.g + locStartColorVar.g * locRandomMinus11(), 0, 255),
  1564. cc.clampf(locStartColor.b + locStartColorVar.b * locRandomMinus11(), 0, 255),
  1565. cc.clampf(locStartColor.a + locStartColorVar.a * locRandomMinus11(), 0, 255)
  1566. );
  1567. end = cc.color(
  1568. cc.clampf(locEndColor.r + locEndColorVar.r * locRandomMinus11(), 0, 255),
  1569. cc.clampf(locEndColor.g + locEndColorVar.g * locRandomMinus11(), 0, 255),
  1570. cc.clampf(locEndColor.b + locEndColorVar.b * locRandomMinus11(), 0, 255),
  1571. cc.clampf(locEndColor.a + locEndColorVar.a * locRandomMinus11(), 0, 255)
  1572. );
  1573. } else {
  1574. start = {
  1575. r: cc.clampf(locStartColor.r + locStartColorVar.r * locRandomMinus11(), 0, 255),
  1576. g: cc.clampf(locStartColor.g + locStartColorVar.g * locRandomMinus11(), 0, 255),
  1577. b: cc.clampf(locStartColor.b + locStartColorVar.b * locRandomMinus11(), 0, 255),
  1578. a: cc.clampf(locStartColor.a + locStartColorVar.a * locRandomMinus11(), 0, 255)
  1579. };
  1580. end = {
  1581. r: cc.clampf(locEndColor.r + locEndColorVar.r * locRandomMinus11(), 0, 255),
  1582. g: cc.clampf(locEndColor.g + locEndColorVar.g * locRandomMinus11(), 0, 255),
  1583. b: cc.clampf(locEndColor.b + locEndColorVar.b * locRandomMinus11(), 0, 255),
  1584. a: cc.clampf(locEndColor.a + locEndColorVar.a * locRandomMinus11(), 0, 255)
  1585. };
  1586. }
  1587. particle.color = start;
  1588. var locParticleDeltaColor = particle.deltaColor, locParticleTimeToLive = particle.timeToLive;
  1589. locParticleDeltaColor.r = (end.r - start.r) / locParticleTimeToLive;
  1590. locParticleDeltaColor.g = (end.g - start.g) / locParticleTimeToLive;
  1591. locParticleDeltaColor.b = (end.b - start.b) / locParticleTimeToLive;
  1592. locParticleDeltaColor.a = (end.a - start.a) / locParticleTimeToLive;
  1593. // size
  1594. var startS = this.startSize + this.startSizeVar * locRandomMinus11();
  1595. startS = Math.max(0, startS); // No negative value
  1596. particle.size = startS;
  1597. if (this.endSize === cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE) {
  1598. particle.deltaSize = 0;
  1599. } else {
  1600. var endS = this.endSize + this.endSizeVar * locRandomMinus11();
  1601. endS = Math.max(0, endS); // No negative values
  1602. particle.deltaSize = (endS - startS) / locParticleTimeToLive;
  1603. }
  1604. // rotation
  1605. var startA = this.startSpin + this.startSpinVar * locRandomMinus11();
  1606. var endA = this.endSpin + this.endSpinVar * locRandomMinus11();
  1607. particle.rotation = startA;
  1608. particle.deltaRotation = (endA - startA) / locParticleTimeToLive;
  1609. // position
  1610. if (this.positionType == cc.ParticleSystem.TYPE_FREE)
  1611. particle.startPos = this.convertToWorldSpace(this._pointZeroForParticle);
  1612. else if (this.positionType == cc.ParticleSystem.TYPE_RELATIVE){
  1613. particle.startPos.x = this._position.x;
  1614. particle.startPos.y = this._position.y;
  1615. }
  1616. // direction
  1617. var a = cc.degreesToRadians(this.angle + this.angleVar * locRandomMinus11());
  1618. // Mode Gravity: A
  1619. if (this.emitterMode === cc.ParticleSystem.MODE_GRAVITY) {
  1620. var locModeA = this.modeA, locParticleModeA = particle.modeA;
  1621. var s = locModeA.speed + locModeA.speedVar * locRandomMinus11();
  1622. // direction
  1623. locParticleModeA.dir.x = Math.cos(a);
  1624. locParticleModeA.dir.y = Math.sin(a);
  1625. cc.pMultIn(locParticleModeA.dir, s);
  1626. // radial accel
  1627. locParticleModeA.radialAccel = locModeA.radialAccel + locModeA.radialAccelVar * locRandomMinus11();
  1628. // tangential accel
  1629. locParticleModeA.tangentialAccel = locModeA.tangentialAccel + locModeA.tangentialAccelVar * locRandomMinus11();
  1630. // rotation is dir
  1631. if(locModeA.rotationIsDir)
  1632. particle.rotation = -cc.radiansToDegrees(cc.pToAngle(locParticleModeA.dir));
  1633. } else {
  1634. // Mode Radius: B
  1635. var locModeB = this.modeB, locParitlceModeB = particle.modeB;
  1636. // Set the default diameter of the particle from the source position
  1637. var startRadius = locModeB.startRadius + locModeB.startRadiusVar * locRandomMinus11();
  1638. var endRadius = locModeB.endRadius + locModeB.endRadiusVar * locRandomMinus11();
  1639. locParitlceModeB.radius = startRadius;
  1640. locParitlceModeB.deltaRadius = (locModeB.endRadius === cc.ParticleSystem.START_RADIUS_EQUAL_TO_END_RADIUS) ? 0 : (endRadius - startRadius) / locParticleTimeToLive;
  1641. locParitlceModeB.angle = a;
  1642. locParitlceModeB.degreesPerSecond = cc.degreesToRadians(locModeB.rotatePerSecond + locModeB.rotatePerSecondVar * locRandomMinus11());
  1643. }
  1644. },
  1645. /**
  1646. * stop emitting particles. Running particles will continue to run until they die
  1647. */
  1648. stopSystem:function () {
  1649. this._isActive = false;
  1650. this._elapsed = this.duration;
  1651. this._emitCounter = 0;
  1652. },
  1653. /**
  1654. * Kill all living particles.
  1655. */
  1656. resetSystem:function () {
  1657. this._isActive = true;
  1658. this._elapsed = 0;
  1659. var locParticles = this._particles;
  1660. for (this._particleIdx = 0; this._particleIdx < this.particleCount; ++this._particleIdx)
  1661. locParticles[this._particleIdx].timeToLive = 0 ;
  1662. },
  1663. /**
  1664. * whether or not the system is full
  1665. * @return {Boolean}
  1666. */
  1667. isFull:function () {
  1668. return (this.particleCount >= this._totalParticles);
  1669. },
  1670. /**
  1671. * should be overridden by subclasses
  1672. * @param {cc.Particle} particle
  1673. * @param {cc.Point} newPosition
  1674. */
  1675. updateQuadWithParticle:function (particle, newPosition) {
  1676. var quad = null;
  1677. if (this._batchNode) {
  1678. var batchQuads = this._batchNode.textureAtlas.quads;
  1679. quad = batchQuads[this.atlasIndex + particle.atlasIndex];
  1680. this._batchNode.textureAtlas.dirty = true;
  1681. } else
  1682. quad = this._quads[this._particleIdx];
  1683. var r, g, b, a;
  1684. if (this._opacityModifyRGB) {
  1685. r = 0 | (particle.color.r * particle.color.a/255);
  1686. g = 0 | (particle.color.g * particle.color.a/255);
  1687. b = 0 | (particle.color.b * particle.color.a/255);
  1688. } else {
  1689. r = 0 | (particle.color.r );
  1690. g = 0 | (particle.color.g );
  1691. b = 0 | (particle.color.b );
  1692. }
  1693. a = 0 | (particle.color.a );
  1694. var locColors = quad.bl.colors;
  1695. locColors.r = r;
  1696. locColors.g = g;
  1697. locColors.b = b;
  1698. locColors.a = a;
  1699. locColors = quad.br.colors;
  1700. locColors.r = r;
  1701. locColors.g = g;
  1702. locColors.b = b;
  1703. locColors.a = a;
  1704. locColors = quad.tl.colors;
  1705. locColors.r = r;
  1706. locColors.g = g;
  1707. locColors.b = b;
  1708. locColors.a = a;
  1709. locColors = quad.tr.colors;
  1710. locColors.r = r;
  1711. locColors.g = g;
  1712. locColors.b = b;
  1713. locColors.a = a;
  1714. // vertices
  1715. var size_2 = particle.size / 2;
  1716. if (particle.rotation) {
  1717. var x1 = -size_2;
  1718. var y1 = -size_2;
  1719. var x2 = size_2;
  1720. var y2 = size_2;
  1721. var x = newPosition.x;
  1722. var y = newPosition.y;
  1723. var rad = -cc.degreesToRadians(particle.rotation);
  1724. var cr = Math.cos(rad);
  1725. var sr = Math.sin(rad);
  1726. var ax = x1 * cr - y1 * sr + x;
  1727. var ay = x1 * sr + y1 * cr + y;
  1728. var bx = x2 * cr - y1 * sr + x;
  1729. var by = x2 * sr + y1 * cr + y;
  1730. var cx = x2 * cr - y2 * sr + x;
  1731. var cy = x2 * sr + y2 * cr + y;
  1732. var dx = x1 * cr - y2 * sr + x;
  1733. var dy = x1 * sr + y2 * cr + y;
  1734. // bottom-left
  1735. quad.bl.vertices.x = ax;
  1736. quad.bl.vertices.y = ay;
  1737. // bottom-right vertex:
  1738. quad.br.vertices.x = bx;
  1739. quad.br.vertices.y = by;
  1740. // top-left vertex:
  1741. quad.tl.vertices.x = dx;
  1742. quad.tl.vertices.y = dy;
  1743. // top-right vertex:
  1744. quad.tr.vertices.x = cx;
  1745. quad.tr.vertices.y = cy;
  1746. } else {
  1747. // bottom-left vertex:
  1748. quad.bl.vertices.x = newPosition.x - size_2;
  1749. quad.bl.vertices.y = newPosition.y - size_2;
  1750. // bottom-right vertex:
  1751. quad.br.vertices.x = newPosition.x + size_2;
  1752. quad.br.vertices.y = newPosition.y - size_2;
  1753. // top-left vertex:
  1754. quad.tl.vertices.x = newPosition.x - size_2;
  1755. quad.tl.vertices.y = newPosition.y + size_2;
  1756. // top-right vertex:
  1757. quad.tr.vertices.x = newPosition.x + size_2;
  1758. quad.tr.vertices.y = newPosition.y + size_2;
  1759. }
  1760. },
  1761. /**
  1762. * should be overridden by subclasses
  1763. */
  1764. postStep:function () {
  1765. if (cc._renderType === cc._RENDER_TYPE_WEBGL) {
  1766. var gl = cc._renderContext;
  1767. gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
  1768. gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW);
  1769. // Option 2: Data
  1770. // glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0]) * particleCount, quads_, GL_DYNAMIC_DRAW);
  1771. // Option 3: Orphaning + glMapBuffer
  1772. // glBufferData(GL_ARRAY_BUFFER, sizeof(m_pQuads[0])*m_uTotalParticles, NULL, GL_STREAM_DRAW);
  1773. // void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
  1774. // memcpy(buf, m_pQuads, sizeof(m_pQuads[0])*m_uTotalParticles);
  1775. // glUnmapBuffer(GL_ARRAY_BUFFER);
  1776. //cc.checkGLErrorDebug();
  1777. }
  1778. },
  1779. /**
  1780. * update emitter's status
  1781. * @override
  1782. * @param {Number} dt delta time
  1783. */
  1784. update:function (dt) {
  1785. if (this._isActive && this.emissionRate) {
  1786. var rate = 1.0 / this.emissionRate;
  1787. //issue #1201, prevent bursts of particles, due to too high emitCounter
  1788. if (this.particleCount < this._totalParticles)
  1789. this._emitCounter += dt;
  1790. while ((this.particleCount < this._totalParticles) && (this._emitCounter > rate)) {
  1791. this.addParticle();
  1792. this._emitCounter -= rate;
  1793. }
  1794. this._elapsed += dt;
  1795. if (this.duration != -1 && this.duration < this._elapsed)
  1796. this.stopSystem();
  1797. }
  1798. this._particleIdx = 0;
  1799. var currentPosition = cc.Particle.TemporaryPoints[0];
  1800. if (this.positionType == cc.ParticleSystem.TYPE_FREE) {
  1801. cc.pIn(currentPosition, this.convertToWorldSpace(this._pointZeroForParticle));
  1802. } else if (this.positionType == cc.ParticleSystem.TYPE_RELATIVE) {
  1803. currentPosition.x = this._position.x;
  1804. currentPosition.y = this._position.y;
  1805. }
  1806. if (this._visible) {
  1807. // Used to reduce memory allocation / creation within the loop
  1808. var tpa = cc.Particle.TemporaryPoints[1],
  1809. tpb = cc.Particle.TemporaryPoints[2],
  1810. tpc = cc.Particle.TemporaryPoints[3];
  1811. var locParticles = this._particles;
  1812. while (this._particleIdx < this.particleCount) {
  1813. // Reset the working particles
  1814. cc.pZeroIn(tpa);
  1815. cc.pZeroIn(tpb);
  1816. cc.pZeroIn(tpc);
  1817. var selParticle = locParticles[this._particleIdx];
  1818. // life
  1819. selParticle.timeToLive -= dt;
  1820. if (selParticle.timeToLive > 0) {
  1821. // Mode A: gravity, direction, tangential accel & radial accel
  1822. if (this.emitterMode == cc.ParticleSystem.MODE_GRAVITY) {
  1823. var tmp = tpc, radial = tpa, tangential = tpb;
  1824. // radial acceleration
  1825. if (selParticle.pos.x || selParticle.pos.y) {
  1826. cc.pIn(radial, selParticle.pos);
  1827. cc.pNormalizeIn(radial);
  1828. } else {
  1829. cc.pZeroIn(radial);
  1830. }
  1831. cc.pIn(tangential, radial);
  1832. cc.pMultIn(radial, selParticle.modeA.radialAccel);
  1833. // tangential acceleration
  1834. var newy = tangential.x;
  1835. tangential.x = -tangential.y;
  1836. tangential.y = newy;
  1837. cc.pMultIn(tangential, selParticle.modeA.tangentialAccel);
  1838. cc.pIn(tmp, radial);
  1839. cc.pAddIn(tmp, tangential);
  1840. cc.pAddIn(tmp, this.modeA.gravity);
  1841. cc.pMultIn(tmp, dt);
  1842. cc.pAddIn(selParticle.modeA.dir, tmp);
  1843. cc.pIn(tmp, selParticle.modeA.dir);
  1844. cc.pMultIn(tmp, dt);
  1845. cc.pAddIn(selParticle.pos, tmp);
  1846. } else {
  1847. // Mode B: radius movement
  1848. var selModeB = selParticle.modeB;
  1849. // Update the angle and radius of the particle.
  1850. selModeB.angle += selModeB.degreesPerSecond * dt;
  1851. selModeB.radius += selModeB.deltaRadius * dt;
  1852. selParticle.pos.x = -Math.cos(selModeB.angle) * selModeB.radius;
  1853. selParticle.pos.y = -Math.sin(selModeB.angle) * selModeB.radius;
  1854. }
  1855. // color
  1856. if (!this._dontTint || cc._renderType === cc._RENDER_TYPE_WEBGL) {
  1857. selParticle.color.r += selParticle.deltaColor.r * dt;
  1858. selParticle.color.g += selParticle.deltaColor.g * dt;
  1859. selParticle.color.b += selParticle.deltaColor.b * dt;
  1860. selParticle.color.a += selParticle.deltaColor.a * dt;
  1861. selParticle.isChangeColor = true;
  1862. }
  1863. // size
  1864. selParticle.size += (selParticle.deltaSize * dt);
  1865. selParticle.size = Math.max(0, selParticle.size);
  1866. // angle
  1867. selParticle.rotation += (selParticle.deltaRotation * dt);
  1868. //
  1869. // update values in quad
  1870. //
  1871. var newPos = tpa;
  1872. if (this.positionType == cc.ParticleSystem.TYPE_FREE || this.positionType == cc.ParticleSystem.TYPE_RELATIVE) {
  1873. var diff = tpb;
  1874. cc.pIn(diff, currentPosition);
  1875. cc.pSubIn(diff, selParticle.startPos);
  1876. cc.pIn(newPos, selParticle.pos);
  1877. cc.pSubIn(newPos, diff);
  1878. } else {
  1879. cc.pIn(newPos, selParticle.pos);
  1880. }
  1881. // translate newPos to correct position, since matrix transform isn't performed in batchnode
  1882. // don't update the particle with the new position information, it will interfere with the radius and tangential calculations
  1883. if (this._batchNode) {
  1884. newPos.x += this._position.x;
  1885. newPos.y += this._position.y;
  1886. }
  1887. if (cc._renderType == cc._RENDER_TYPE_WEBGL) {
  1888. // IMPORTANT: newPos may not be used as a reference here! (as it is just the temporary tpa point)
  1889. // the implementation of updateQuadWithParticle must use
  1890. // the x and y values directly
  1891. this.updateQuadWithParticle(selParticle, newPos);
  1892. } else {
  1893. cc.pIn(selParticle.drawPos, newPos);
  1894. }
  1895. //updateParticleImp(self, updateParticleSel, p, newPos);
  1896. // update particle counter
  1897. ++this._particleIdx;
  1898. } else {
  1899. // life < 0
  1900. var currentIndex = selParticle.atlasIndex;
  1901. if(this._particleIdx !== this.particleCount -1){
  1902. var deadParticle = locParticles[this._particleIdx];
  1903. locParticles[this._particleIdx] = locParticles[this.particleCount -1];
  1904. locParticles[this.particleCount -1] = deadParticle;
  1905. }
  1906. if (this._batchNode) {
  1907. //disable the switched particle
  1908. this._batchNode.disableParticle(this.atlasIndex + currentIndex);
  1909. //switch indexes
  1910. locParticles[this.particleCount - 1].atlasIndex = currentIndex;
  1911. }
  1912. --this.particleCount;
  1913. if (this.particleCount == 0 && this.autoRemoveOnFinish) {
  1914. this.unscheduleUpdate();
  1915. this._parent.removeChild(this, true);
  1916. return;
  1917. }
  1918. }
  1919. }
  1920. this._transformSystemDirty = false;
  1921. }
  1922. if (!this._batchNode)
  1923. this.postStep();
  1924. },
  1925. /**
  1926. * update emitter's status (dt = 0)
  1927. */
  1928. updateWithNoTime:function () {
  1929. this.update(0);
  1930. },
  1931. //
  1932. // return the string found by key in dict.
  1933. // @param {string} key
  1934. // @param {object} dict
  1935. // @return {String} "" if not found; return the string if found.
  1936. // @private
  1937. //
  1938. _valueForKey:function (key, dict) {
  1939. if (dict) {
  1940. var pString = dict[key];
  1941. return pString != null ? pString : "";
  1942. }
  1943. return "";
  1944. },
  1945. _updateBlendFunc:function () {
  1946. if(this._batchNode){
  1947. cc.log("Can't change blending functions when the particle is being batched");
  1948. return;
  1949. }
  1950. var locTexture = this._texture;
  1951. if (locTexture && locTexture instanceof cc.Texture2D) {
  1952. this._opacityModifyRGB = false;
  1953. var locBlendFunc = this._blendFunc;
  1954. if (locBlendFunc.src == cc.BLEND_SRC && locBlendFunc.dst == cc.BLEND_DST) {
  1955. if (locTexture.hasPremultipliedAlpha()) {
  1956. this._opacityModifyRGB = true;
  1957. } else {
  1958. locBlendFunc.src = cc.SRC_ALPHA;
  1959. locBlendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
  1960. }
  1961. }
  1962. }
  1963. },
  1964. /**
  1965. * to copy object with deep copy.
  1966. * returns a clone of action.
  1967. *
  1968. * @return {cc.ParticleSystem}
  1969. */
  1970. clone:function () {
  1971. var retParticle = new cc.ParticleSystem();
  1972. // self, not super
  1973. if (retParticle.initWithTotalParticles(this.getTotalParticles())) {
  1974. // angle
  1975. retParticle.setAngle(this.getAngle());
  1976. retParticle.setAngleVar(this.getAngleVar());
  1977. // duration
  1978. retParticle.setDuration(this.getDuration());
  1979. // blend function
  1980. var blend = this.getBlendFunc();
  1981. retParticle.setBlendFunc(blend.src,blend.dst);
  1982. // color
  1983. retParticle.setStartColor(this.getStartColor());
  1984. retParticle.setStartColorVar(this.getStartColorVar());
  1985. retParticle.setEndColor(this.getEndColor());
  1986. retParticle.setEndColorVar(this.getEndColorVar());
  1987. // this size
  1988. retParticle.setStartSize(this.getStartSize());
  1989. retParticle.setStartSizeVar(this.getStartSizeVar());
  1990. retParticle.setEndSize(this.getEndSize());
  1991. retParticle.setEndSizeVar(this.getEndSizeVar());
  1992. // position
  1993. retParticle.setPosition(cc.p(this.x, this.y));
  1994. retParticle.setPosVar(cc.p(this.getPosVar().x,this.getPosVar().y));
  1995. // Spinning
  1996. retParticle.setStartSpin(this.getStartSpin()||0);
  1997. retParticle.setStartSpinVar(this.getStartSpinVar()||0);
  1998. retParticle.setEndSpin(this.getEndSpin()||0);
  1999. retParticle.setEndSpinVar(this.getEndSpinVar()||0);
  2000. retParticle.setEmitterMode(this.getEmitterMode());
  2001. // Mode A: Gravity + tangential accel + radial accel
  2002. if (this.getEmitterMode() == cc.ParticleSystem.MODE_GRAVITY) {
  2003. // gravity
  2004. var gra = this.getGravity();
  2005. retParticle.setGravity(cc.p(gra.x,gra.y));
  2006. // speed
  2007. retParticle.setSpeed(this.getSpeed());
  2008. retParticle.setSpeedVar(this.getSpeedVar());
  2009. // radial acceleration
  2010. retParticle.setRadialAccel(this.getRadialAccel());
  2011. retParticle.setRadialAccelVar(this.getRadialAccelVar());
  2012. // tangential acceleration
  2013. retParticle.setTangentialAccel(this.getTangentialAccel());
  2014. retParticle.setTangentialAccelVar(this.getTangentialAccelVar());
  2015. } else if (this.getEmitterMode() == cc.ParticleSystem.MODE_RADIUS) {
  2016. // or Mode B: radius movement
  2017. retParticle.setStartRadius(this.getStartRadius());
  2018. retParticle.setStartRadiusVar(this.getStartRadiusVar());
  2019. retParticle.setEndRadius(this.getEndRadius());
  2020. retParticle.setEndRadiusVar(this.getEndRadiusVar());
  2021. retParticle.setRotatePerSecond(this.getRotatePerSecond());
  2022. retParticle.setRotatePerSecondVar(this.getRotatePerSecondVar());
  2023. }
  2024. // life span
  2025. retParticle.setLife(this.getLife());
  2026. retParticle.setLifeVar(this.getLifeVar());
  2027. // emission Rate
  2028. retParticle.setEmissionRate(this.getEmissionRate());
  2029. //don't get the internal texture if a batchNode is used
  2030. if (!this.getBatchNode()) {
  2031. // Set a compatible default for the alpha transfer
  2032. retParticle.setOpacityModifyRGB(this.isOpacityModifyRGB());
  2033. // texture
  2034. var texture = this.getTexture();
  2035. if(texture){
  2036. var size = texture.getContentSize();
  2037. retParticle.setTextureWithRect(texture, cc.rect(0, 0, size.width, size.height));
  2038. }
  2039. }
  2040. }
  2041. return retParticle;
  2042. },
  2043. /**
  2044. * <p> Sets a new CCSpriteFrame as particle.</br>
  2045. * WARNING: this method is experimental. Use setTextureWithRect instead.
  2046. * </p>
  2047. * @param {cc.SpriteFrame} spriteFrame
  2048. */
  2049. setDisplayFrame:function (spriteFrame) {
  2050. var locOffset = spriteFrame.getOffsetInPixels();
  2051. if(locOffset.x != 0 || locOffset.y != 0)
  2052. cc.log("cc.ParticleSystem.setDisplayFrame(): QuadParticle only supports SpriteFrames with no offsets");
  2053. // update texture before updating texture rect
  2054. if (cc._renderType === cc._RENDER_TYPE_WEBGL)
  2055. if (!this._texture || spriteFrame.getTexture()._webTextureObj != this._texture._webTextureObj)
  2056. this.setTexture(spriteFrame.getTexture());
  2057. },
  2058. /**
  2059. * Sets a new texture with a rect. The rect is in Points.
  2060. * @param {cc.Texture2D} texture
  2061. * @param {cc.Rect} rect
  2062. */
  2063. setTextureWithRect:function (texture, rect) {
  2064. var locTexture = this._texture;
  2065. if (cc._renderType === cc._RENDER_TYPE_WEBGL) {
  2066. // Only update the texture if is different from the current one
  2067. if ((!locTexture || texture._webTextureObj != locTexture._webTextureObj) && (locTexture != texture)) {
  2068. this._texture = texture;
  2069. this._updateBlendFunc();
  2070. }
  2071. } else {
  2072. if ((!locTexture || texture != locTexture) && (locTexture != texture)) {
  2073. this._texture = texture;
  2074. this._updateBlendFunc();
  2075. }
  2076. }
  2077. this._pointRect = rect;
  2078. this.initTexCoordsWithRect(rect);
  2079. },
  2080. /**
  2081. * draw particle
  2082. * @param {CanvasRenderingContext2D} ctx CanvasContext
  2083. * @override
  2084. */
  2085. draw:function (ctx) {
  2086. if(!this._textureLoaded || this._batchNode) // draw should not be called when added to a particleBatchNode
  2087. return;
  2088. if (cc._renderType === cc._RENDER_TYPE_CANVAS)
  2089. this._drawForCanvas(ctx);
  2090. else
  2091. this._drawForWebGL(ctx);
  2092. cc.g_NumberOfDraws++;
  2093. },
  2094. _drawForCanvas:function (ctx) {
  2095. var context = ctx || cc._renderContext;
  2096. context.save();
  2097. if (this.isBlendAdditive())
  2098. context.globalCompositeOperation = 'lighter';
  2099. else
  2100. context.globalCompositeOperation = 'source-over';
  2101. var element = this._texture.getHtmlElementObj();
  2102. for (var i = 0; i < this.particleCount; i++) {
  2103. var particle = this._particles[i];
  2104. var lpx = (0 | (particle.size * 0.5));
  2105. if (this.drawMode == cc.ParticleSystem.TEXTURE_MODE) {
  2106. // Delay drawing until the texture is fully loaded by the browser
  2107. if (!element.width || !element.height)
  2108. continue;
  2109. context.save();
  2110. context.globalAlpha = particle.color.a / 255;
  2111. context.translate((0 | particle.drawPos.x), -(0 | particle.drawPos.y));
  2112. var size = Math.floor(particle.size / 4) * 4;
  2113. var w = this._pointRect.width;
  2114. var h = this._pointRect.height;
  2115. context.scale(
  2116. Math.max((1 / w) * size, 0.000001),
  2117. Math.max((1 / h) * size, 0.000001)
  2118. );
  2119. if (particle.rotation)
  2120. context.rotate(cc.degreesToRadians(particle.rotation));
  2121. context.translate(-(0 | (w / 2)), -(0 | (h / 2)));
  2122. var drawElement = particle.isChangeColor ? this._changeTextureColor(element, particle.color, this._pointRect) : element;
  2123. if(drawElement)
  2124. context.drawImage(drawElement, 0, 0);
  2125. context.restore();
  2126. } else {
  2127. context.save();
  2128. context.globalAlpha = particle.color.a / 255;
  2129. context.translate(0 | particle.drawPos.x, -(0 | particle.drawPos.y));
  2130. if (this.shapeType == cc.ParticleSystem.STAR_SHAPE) {
  2131. if (particle.rotation)
  2132. context.rotate(cc.degreesToRadians(particle.rotation));
  2133. cc._drawingUtil.drawStar(context, lpx, particle.color);
  2134. } else
  2135. cc._drawingUtil.drawColorBall(context, lpx, particle.color);
  2136. context.restore();
  2137. }
  2138. }
  2139. context.restore();
  2140. },
  2141. _changeTextureColor: function(element, color, rect){
  2142. if (!element.tintCache) {
  2143. element.tintCache = document.createElement('canvas');
  2144. element.tintCache.width = element.width;
  2145. element.tintCache.height = element.height;
  2146. }
  2147. return cc.generateTintImageWithMultiply(element, color, rect, element.tintCache);
  2148. },
  2149. _drawForWebGL:function (ctx) {
  2150. if(!this._texture)
  2151. return;
  2152. var gl = ctx || cc._renderContext;
  2153. this._shaderProgram.use();
  2154. this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4();
  2155. cc.glBindTexture2D(this._texture);
  2156. cc.glBlendFuncForParticle(this._blendFunc.src, this._blendFunc.dst);
  2157. //cc.assert(this._particleIdx == this.particleCount, "Abnormal error in particle quad");
  2158. //
  2159. // Using VBO without VAO
  2160. //
  2161. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
  2162. gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
  2163. gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0); // vertices
  2164. gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12); // colors
  2165. gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16); // tex coords
  2166. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
  2167. gl.drawElements(gl.TRIANGLES, this._particleIdx * 6, gl.UNSIGNED_SHORT, 0);
  2168. },
  2169. /**
  2170. * listen the event that coming to foreground on Android
  2171. * @param {cc.Class} obj
  2172. */
  2173. listenBackToForeground:function (obj) {
  2174. if (cc.TEXTURE_ATLAS_USE_VAO)
  2175. this._setupVBOandVAO();
  2176. else
  2177. this._setupVBO();
  2178. },
  2179. _setupVBOandVAO:function () {
  2180. //Not support on WebGL
  2181. /*if (cc._renderType == cc._RENDER_TYPE_CANVAS) {
  2182. return;
  2183. }*/
  2184. //NOT SUPPORTED
  2185. /*glGenVertexArrays(1, this._VAOname);
  2186. glBindVertexArray(this._VAOname);
  2187. var kQuadSize = sizeof(m_pQuads[0].bl);
  2188. glGenBuffers(2, this._buffersVBO[0]);
  2189. glBindBuffer(GL_ARRAY_BUFFER, this._buffersVBO[0]);
  2190. glBufferData(GL_ARRAY_BUFFER, sizeof(this._quads[0]) * this._totalParticles, this._quads, GL_DYNAMIC_DRAW);
  2191. // vertices
  2192. glEnableVertexAttribArray(kCCVertexAttrib_Position);
  2193. glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, kQuadSize, offsetof(ccV3F_C4B_T2F, vertices));
  2194. // colors
  2195. glEnableVertexAttribArray(kCCVertexAttrib_Color);
  2196. glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, offsetof(ccV3F_C4B_T2F, colors));
  2197. // tex coords
  2198. glEnableVertexAttribArray(kCCVertexAttrib_TexCoords);
  2199. glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, offsetof(ccV3F_C4B_T2F, texCoords));
  2200. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
  2201. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m_pIndices[0]) * m_uTotalParticles * 6, m_pIndices, GL_STATIC_DRAW);
  2202. glBindVertexArray(0);
  2203. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  2204. glBindBuffer(GL_ARRAY_BUFFER, 0);
  2205. CHECK_GL_ERROR_DEBUG();*/
  2206. },
  2207. _setupVBO:function () {
  2208. if (cc._renderType == cc._RENDER_TYPE_CANVAS)
  2209. return;
  2210. var gl = cc._renderContext;
  2211. //gl.deleteBuffer(this._buffersVBO[0]);
  2212. this._buffersVBO[0] = gl.createBuffer();
  2213. gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
  2214. gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW);
  2215. this._buffersVBO[1] = gl.createBuffer();
  2216. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
  2217. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
  2218. //cc.checkGLErrorDebug();
  2219. },
  2220. _allocMemory:function () {
  2221. if (cc._renderType === cc._RENDER_TYPE_CANVAS)
  2222. return true;
  2223. //cc.assert((!this._quads && !this._indices), "Memory already allocated");
  2224. if(this._batchNode){
  2225. cc.log("cc.ParticleSystem._allocMemory(): Memory should not be allocated when not using batchNode");
  2226. return false;
  2227. }
  2228. var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
  2229. var totalParticles = this._totalParticles;
  2230. var locQuads = this._quads;
  2231. locQuads.length = 0;
  2232. this._indices = new Uint16Array(totalParticles * 6);
  2233. var locQuadsArrayBuffer = new ArrayBuffer(quadSize * totalParticles);
  2234. for (var i = 0; i < totalParticles; i++)
  2235. locQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, i * quadSize);
  2236. if (!locQuads || !this._indices) {
  2237. cc.log("cocos2d: Particle system: not enough memory");
  2238. return false;
  2239. }
  2240. this._quadsArrayBuffer = locQuadsArrayBuffer;
  2241. return true;
  2242. }
  2243. });
  2244. var _p = cc.ParticleSystem.prototype;
  2245. if(cc._renderType === cc._RENDER_TYPE_CANVAS && !cc.sys._supportCanvasNewBlendModes)
  2246. _p._changeTextureColor = function (element, color, rect) {
  2247. var cacheTextureForColor = cc.textureCache.getTextureColors(element);
  2248. if (cacheTextureForColor) {
  2249. // Create another cache for the tinted version
  2250. // This speeds up things by a fair bit
  2251. if (!cacheTextureForColor.tintCache) {
  2252. cacheTextureForColor.tintCache = document.createElement('canvas');
  2253. cacheTextureForColor.tintCache.width = element.width;
  2254. cacheTextureForColor.tintCache.height = element.height;
  2255. }
  2256. cc.generateTintImage(element, cacheTextureForColor, color, rect, cacheTextureForColor.tintCache);
  2257. return cacheTextureForColor.tintCache;
  2258. }
  2259. return null
  2260. };
  2261. // Extended properties
  2262. /** @expose */
  2263. _p.opacityModifyRGB;
  2264. cc.defineGetterSetter(_p, "opacityModifyRGB", _p.isOpacityModifyRGB, _p.setOpacityModifyRGB);
  2265. /** @expose */
  2266. _p.batchNode;
  2267. cc.defineGetterSetter(_p, "batchNode", _p.getBatchNode, _p.setBatchNode);
  2268. /** @expose */
  2269. _p.active;
  2270. cc.defineGetterSetter(_p, "active", _p.isActive);
  2271. /** @expose */
  2272. _p.sourcePos;
  2273. cc.defineGetterSetter(_p, "sourcePos", _p.getSourcePosition, _p.setSourcePosition);
  2274. /** @expose */
  2275. _p.posVar;
  2276. cc.defineGetterSetter(_p, "posVar", _p.getPosVar, _p.setPosVar);
  2277. /** @expose */
  2278. _p.gravity;
  2279. cc.defineGetterSetter(_p, "gravity", _p.getGravity, _p.setGravity);
  2280. /** @expose */
  2281. _p.speed;
  2282. cc.defineGetterSetter(_p, "speed", _p.getSpeed, _p.setSpeed);
  2283. /** @expose */
  2284. _p.speedVar;
  2285. cc.defineGetterSetter(_p, "speedVar", _p.getSpeedVar, _p.setSpeedVar);
  2286. /** @expose */
  2287. _p.tangentialAccel;
  2288. cc.defineGetterSetter(_p, "tangentialAccel", _p.getTangentialAccel, _p.setTangentialAccel);
  2289. /** @expose */
  2290. _p.tangentialAccelVar;
  2291. cc.defineGetterSetter(_p, "tangentialAccelVar", _p.getTangentialAccelVar, _p.setTangentialAccelVar);
  2292. /** @expose */
  2293. _p.radialAccel;
  2294. cc.defineGetterSetter(_p, "radialAccel", _p.getRadialAccel, _p.setRadialAccel);
  2295. /** @expose */
  2296. _p.radialAccelVar;
  2297. cc.defineGetterSetter(_p, "radialAccelVar", _p.getRadialAccelVar, _p.setRadialAccelVar);
  2298. /** @expose */
  2299. _p.rotationIsDir;
  2300. cc.defineGetterSetter(_p, "rotationIsDir", _p.getRotationIsDir, _p.setRotationIsDir);
  2301. /** @expose */
  2302. _p.startRadius;
  2303. cc.defineGetterSetter(_p, "startRadius", _p.getStartRadius, _p.setStartRadius);
  2304. /** @expose */
  2305. _p.startRadiusVar;
  2306. cc.defineGetterSetter(_p, "startRadiusVar", _p.getStartRadiusVar, _p.setStartRadiusVar);
  2307. /** @expose */
  2308. _p.endRadius;
  2309. cc.defineGetterSetter(_p, "endRadius", _p.getEndRadius, _p.setEndRadius);
  2310. /** @expose */
  2311. _p.endRadiusVar;
  2312. cc.defineGetterSetter(_p, "endRadiusVar", _p.getEndRadiusVar, _p.setEndRadiusVar);
  2313. /** @expose */
  2314. _p.rotatePerS;
  2315. cc.defineGetterSetter(_p, "rotatePerS", _p.getRotatePerSecond, _p.setRotatePerSecond);
  2316. /** @expose */
  2317. _p.rotatePerSVar;
  2318. cc.defineGetterSetter(_p, "rotatePerSVar", _p.getRotatePerSecondVar, _p.setRotatePerSecondVar);
  2319. /** @expose */
  2320. _p.startColor;
  2321. cc.defineGetterSetter(_p, "startColor", _p.getStartColor, _p.setStartColor);
  2322. /** @expose */
  2323. _p.startColorVar;
  2324. cc.defineGetterSetter(_p, "startColorVar", _p.getStartColorVar, _p.setStartColorVar);
  2325. /** @expose */
  2326. _p.endColor;
  2327. cc.defineGetterSetter(_p, "endColor", _p.getEndColor, _p.setEndColor);
  2328. /** @expose */
  2329. _p.endColorVar;
  2330. cc.defineGetterSetter(_p, "endColorVar", _p.getEndColorVar, _p.setEndColorVar);
  2331. /** @expose */
  2332. _p.totalParticles;
  2333. cc.defineGetterSetter(_p, "totalParticles", _p.getTotalParticles, _p.setTotalParticles);
  2334. /** @expose */
  2335. _p.texture;
  2336. cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
  2337. /**
  2338. * <p> return the string found by key in dict. <br/>
  2339. * This plist files can be create manually or with Particle Designer:<br/>
  2340. * http://particledesigner.71squared.com/<br/>
  2341. * </p>
  2342. * @deprecated since v3.0 please use new cc.ParticleSysytem(plistFile) instead.
  2343. * @param {String|Number} plistFile
  2344. * @return {cc.ParticleSystem}
  2345. */
  2346. cc.ParticleSystem.create = function (plistFile) {
  2347. return new cc.ParticleSystem(plistFile);
  2348. };
  2349. /**
  2350. * <p> return the string found by key in dict. <br/>
  2351. * This plist files can be create manually or with Particle Designer:<br/>
  2352. * http://particledesigner.71squared.com/<br/>
  2353. * </p>
  2354. * @deprecated since v3.0 please use new cc.ParticleSysytem(plistFile) instead.
  2355. * @function
  2356. * @param {String|Number} plistFile
  2357. * @return {cc.ParticleSystem}
  2358. */
  2359. cc.ParticleSystem.createWithTotalParticles = cc.ParticleSystem.create;
  2360. // Different modes
  2361. /**
  2362. * Mode A:Gravity + Tangential Accel + Radial Accel
  2363. * @Class
  2364. * @Construct
  2365. * @param {cc.Point} [gravity=] Gravity value.
  2366. * @param {Number} [speed=0] speed of each particle.
  2367. * @param {Number} [speedVar=0] speed variance of each particle.
  2368. * @param {Number} [tangentialAccel=0] tangential acceleration of each particle.
  2369. * @param {Number} [tangentialAccelVar=0] tangential acceleration variance of each particle.
  2370. * @param {Number} [radialAccel=0] radial acceleration of each particle.
  2371. * @param {Number} [radialAccelVar=0] radial acceleration variance of each particle.
  2372. * @param {boolean} [rotationIsDir=false]
  2373. */
  2374. cc.ParticleSystem.ModeA = function (gravity, speed, speedVar, tangentialAccel, tangentialAccelVar, radialAccel, radialAccelVar, rotationIsDir) {
  2375. /** Gravity value. Only available in 'Gravity' mode. */
  2376. this.gravity = gravity ? gravity : cc.p(0,0);
  2377. /** speed of each particle. Only available in 'Gravity' mode. */
  2378. this.speed = speed || 0;
  2379. /** speed variance of each particle. Only available in 'Gravity' mode. */
  2380. this.speedVar = speedVar || 0;
  2381. /** tangential acceleration of each particle. Only available in 'Gravity' mode. */
  2382. this.tangentialAccel = tangentialAccel || 0;
  2383. /** tangential acceleration variance of each particle. Only available in 'Gravity' mode. */
  2384. this.tangentialAccelVar = tangentialAccelVar || 0;
  2385. /** radial acceleration of each particle. Only available in 'Gravity' mode. */
  2386. this.radialAccel = radialAccel || 0;
  2387. /** radial acceleration variance of each particle. Only available in 'Gravity' mode. */
  2388. this.radialAccelVar = radialAccelVar || 0;
  2389. /** set the rotation of each particle to its direction Only available in 'Gravity' mode. */
  2390. this.rotationIsDir = rotationIsDir || false;
  2391. };
  2392. /**
  2393. * Mode B: circular movement (gravity, radial accel and tangential accel don't are not used in this mode)
  2394. * @Class
  2395. * @Construct
  2396. * @param {Number} startRadius The starting radius of the particles.
  2397. * @param {Number} startRadiusVar The starting radius variance of the particles.
  2398. * @param {Number} endRadius The ending radius of the particles.
  2399. * @param {Number} endRadiusVar The ending radius variance of the particles.
  2400. * @param {Number} rotatePerSecond Number of degress to rotate a particle around the source pos per second.
  2401. * @param {Number} rotatePerSecondVar Variance in degrees for rotatePerSecond.
  2402. */
  2403. cc.ParticleSystem.ModeB = function (startRadius, startRadiusVar, endRadius, endRadiusVar, rotatePerSecond, rotatePerSecondVar) {
  2404. /** The starting radius of the particles. Only available in 'Radius' mode. */
  2405. this.startRadius = startRadius || 0;
  2406. /** The starting radius variance of the particles. Only available in 'Radius' mode. */
  2407. this.startRadiusVar = startRadiusVar || 0;
  2408. /** The ending radius of the particles. Only available in 'Radius' mode. */
  2409. this.endRadius = endRadius || 0;
  2410. /** The ending radius variance of the particles. Only available in 'Radius' mode. */
  2411. this.endRadiusVar = endRadiusVar || 0;
  2412. /** Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode. */
  2413. this.rotatePerSecond = rotatePerSecond || 0;
  2414. /** Variance in degrees for rotatePerSecond. Only available in 'Radius' mode. */
  2415. this.rotatePerSecondVar = rotatePerSecondVar || 0;
  2416. };
  2417. /**
  2418. * Shape Mode of Particle Draw
  2419. * @constant
  2420. * @type Number
  2421. */
  2422. cc.ParticleSystem.SHAPE_MODE = 0;
  2423. /**
  2424. * Texture Mode of Particle Draw
  2425. * @constant
  2426. * @type Number
  2427. */
  2428. cc.ParticleSystem.TEXTURE_MODE = 1;
  2429. /**
  2430. * Star Shape for ShapeMode of Particle
  2431. * @constant
  2432. * @type Number
  2433. */
  2434. cc.ParticleSystem.STAR_SHAPE = 0;
  2435. /**
  2436. * Ball Shape for ShapeMode of Particle
  2437. * @constant
  2438. * @type Number
  2439. */
  2440. cc.ParticleSystem.BALL_SHAPE = 1;
  2441. /**
  2442. * The Particle emitter lives forever
  2443. * @constant
  2444. * @type Number
  2445. */
  2446. cc.ParticleSystem.DURATION_INFINITY = -1;
  2447. /**
  2448. * The starting size of the particle is equal to the ending size
  2449. * @constant
  2450. * @type Number
  2451. */
  2452. cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE = -1;
  2453. /**
  2454. * The starting radius of the particle is equal to the ending radius
  2455. * @constant
  2456. * @type Number
  2457. */
  2458. cc.ParticleSystem.START_RADIUS_EQUAL_TO_END_RADIUS = -1;
  2459. /**
  2460. * Gravity mode (A mode)
  2461. * @constant
  2462. * @type Number
  2463. */
  2464. cc.ParticleSystem.MODE_GRAVITY = 0;
  2465. /**
  2466. * Radius mode (B mode)
  2467. * @constant
  2468. * @type Number
  2469. */
  2470. cc.ParticleSystem.MODE_RADIUS = 1;
  2471. /**
  2472. * Living particles are attached to the world and are unaffected by emitter repositioning.
  2473. * @constant
  2474. * @type Number
  2475. */
  2476. cc.ParticleSystem.TYPE_FREE = 0;
  2477. /**
  2478. * Living particles are attached to the world but will follow the emitter repositioning.<br/>
  2479. * Use case: Attach an emitter to an sprite, and you want that the emitter follows the sprite.
  2480. * @constant
  2481. * @type Number
  2482. */
  2483. cc.ParticleSystem.TYPE_RELATIVE = 1;
  2484. /**
  2485. * Living particles are attached to the emitter and are translated along with it.
  2486. * @constant
  2487. * @type Number
  2488. */
  2489. cc.ParticleSystem.TYPE_GROUPED = 2;