/** * Hilo * Copyright 2015 alibaba.com * Licensed under the MIT License */ /** * *
* @class ParticleSystem A particle system. * @augments Container * @module hilo/game/ParticleSystem * @requires hilo/core/Hilo * @requires hilo/core/Class * @requires hilo/view/View * @requires hilo/view/Container * @requires hilo/view/Drawable * @property {Number} [emitTime=0.2] Emit time interval(in second). * @property {Number} [emitTimeVar=0] Emit time interval variances. * @property {Number} [emitNum=10] Emit number. * @property {Number} [emitNumVar=0] Emit number variances. * @property {Number} [emitterX=0] The emitter x position. * @property {Number} [emitterY=0] The emitter y position. * @property {Number} [totalTime=Infinity] Total time. * @property {Number} [gx=0] The gravity x value. * @property {Number} [gy=0] The gravity y value. * @param {Object} properties properties The properties to create a view object, contains all writeable props of this class * @param {Object} properties.particle The config of particle. * @param {Number} [properties.particle.x=0] The x position. * @param {Number} [properties.particle.y=0] The y position * @param {Number} [properties.particle.vx=0] The x velocity. * @param {Number} [properties.particle.vy=0] The y velocity. * @param {Number} [properties.particle.ax=0] The x acceleration. * @param {Number} [properties.particle.ay=0] The y acceleration. * @param {Number} [properties.particle.life=1] The time particle lives(in second). * @param {Number} [properties.particle.alpha=1] The alpha. * @param {Number} [properties.particle.alphaV=0] The alpha decline rate. * @param {Number} [properties.particle.scale=1] The scale. * @param {Number} [properties.particle.scaleV=0] The scale decline rate. */ var ParticleSystem = (function(){ //粒子属性 var props = ['x', 'y', 'vx', 'vy', 'ax', 'ay', 'rotation', 'rotationV', 'scale', 'scaleV', 'alpha', 'alphaV', 'life']; var PROPS = []; for(var i = 0, l = props.length;i < l;i ++){ var p = props[i]; PROPS.push(p); PROPS.push(p + "Var"); } //粒子默认值 var PROPS_DEFAULT = { x: 0, y: 0, vx: 0, vy: 0, ax: 0, ay: 0, scale:1, scaleV:0, alpha:1, alphaV:0, rotation: 0, rotationV: 0, life: 1 }; var diedParticles = []; var ParticleSystem = Class.create(/** @lends ParticleSystem.prototype */{ Extends:Container, constructor:function ParticleSystem(properties){ this.id = this.id || properties.id || Hilo.getUid("ParticleSystem"); this.emitterX = 0; this.emitterY = 0; this.gx = 0; this.gy = 0; this.totalTime = Infinity; this.emitNum = 10; this.emitNumVar = 0; this.emitTime = .2; this.emitTimeVar = 0; this.particle = {}; ParticleSystem.superclass.constructor.call(this, properties); this.reset(properties); }, Statics:{ PROPS:PROPS, PROPS_DEFAULT:PROPS_DEFAULT, diedParticles:diedParticles }, /** * Reset the properties. * @param {Object} cfg */ reset: function(cfg) { Hilo.copy(this, cfg); this.particle.system = this; if(this.totalTime <= 0){ this.totalTime = Infinity; } }, /** * 更新 * @param {Number} dt delta time(in milliseconds) */ onUpdate: function(dt) { dt *= .001; if (this._isRun) { this._totalRunTime += dt; this._currentRunTime += dt; if (this._currentRunTime >= this._emitTime) { this._currentRunTime = 0; this._emitTime = getRandomValue(this.emitTime, this.emitTimeVar); this._emit(); } if (this._totalRunTime >= this.totalTime) { this.stop(); } } }, /** * Emit particles. */ _emit: function() { var num = getRandomValue(this.emitNum, this.emitNumVar)>>0; for (var i = 0; i < num; i++) { this.addChild(Particle.create(this.particle)); } }, /** * Start emit particles. */ start: function() { this.stop(true); this._currentRunTime = 0; this._totalRunTime = 0; this._isRun = true; this._emitTime = getRandomValue(this.emitTime, this.emitTimeVar); }, /** * Stop emit particles. * @param {Boolean} clear Whether or not clear all the particles. */ stop: function(clear) { this._isRun = false; if (clear) { for (var i = this.children.length - 1; i >= 0; i--) { this.children[i].destroy(); } } } }); /** * @class 粒子 * @inner * @param {Number} vx The x velocity. * @param {Number} vy The y velocity. * @param {Number} ax The x acceleration. * @param {Number} ay The y acceleration. * @param {Number} scaleV The scale decline rate. * @param {Number} alphaV The alpha decline rate. * @param {Number} rotationV The rotate speed. * @param {Number} life The time particle lives(in seconds) */ var Particle = Class.create({ Extends:View, constructor:function Particle(properties){ this.id = this.id || properties.id || Hilo.getUid("Particle"); Particle.superclass.constructor.call(this, properties); this.init(properties); }, /** * Update the particle. */ onUpdate: function(dt) { dt *= .001; if(this._died){ return false; } var ax = this.ax + this.system.gx; var ay = this.ay + this.system.gy; this.vx += ax * dt; this.vy += ay * dt; this.x += this.vx * dt; this.y += this.vy * dt; this.rotation += this.rotationV; if (this._time > .1) { this.alpha += this.alphaV; } this.scale += this.scaleV; this.scaleX = this.scaleY = this.scale; this._time += dt; if (this._time >= this.life || this.alpha <= 0) { this.destroy(); return false; } }, /** * Set the image of particle. */ setImage: function(img, frame) { this.drawable = this.drawable||new Drawable(); frame = frame || [0, 0, img.width, img.height]; this.width = frame[2]; this.height = frame[3]; this.drawable.rect = frame; this.drawable.image = img; }, /** * Destroy the particle. */ destroy: function() { this._died = true; this.alpha = 0; this.removeFromParent(); diedParticles.push(this); }, /** * Init the particle. */ init: function(cfg) { this.system = cfg.system; this._died = false; this._time = 0; this.alpha = 1; for (var i = 0, l = PROPS.length; i < l; i++) { var p = PROPS[i]; var v = cfg[p] === undefined ? PROPS_DEFAULT[p] : cfg[p]; this[p] = getRandomValue(v, cfg[p + 'Var']); } this.x += this.system.emitterX; this.y += this.system.emitterY; if (cfg.image) { var frame = cfg.frame; if(frame && frame[0].length){ frame = frame[(Math.random() * frame.length) >> 0]; } this.setImage(cfg.image, frame); if(cfg.pivotX !== undefined){ this.pivotX = cfg.pivotX * frame[2]; } if(cfg.pivotY !== undefined){ this.pivotY = cfg.pivotY * frame[3]; } } }, Statics:{ /** * Create the particle. * @param {Object} cfg The config of particle. */ create:function(cfg) { if (diedParticles.length > 0) { var particle = diedParticles.pop(); particle.init(cfg); return particle; } else { return new Particle(cfg); } } } }); /** * Get the random value. * @private * @param {Number} value The value. * @param {Number} variances The variances. * @return {Number} */ function getRandomValue(value, variances){ return variances ? value + (Math.random() - .5) * 2 * variances : value; } return ParticleSystem; })();