1 /**
  2  * The Render Engine
  3  * Emitter
  4  *
  5  * @fileoverview A particle emitter class
  6  *
  7  * @author: Brett Fattori (brettf@renderengine.com)
  8  *
  9  * @author: $Author: bfattori $
 10  * @version: $Revision: 1555 $
 11  *
 12  * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com)
 13  *
 14  * Permission is hereby granted, free of charge, to any person obtaining a copy
 15  * of this software and associated documentation files (the "Software"), to deal
 16  * in the Software without restriction, including without limitation the rights
 17  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 18  * copies of the Software, and to permit persons to whom the Software is
 19  * furnished to do so, subject to the following conditions:
 20  *
 21  * The above copyright notice and this permission notice shall be included in
 22  * all copies or substantial portions of the Software.
 23  *
 24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 27  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 29  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 30  * THE SOFTWARE.
 31  *
 32  */
 33 
 34 // The class this file defines and its required classes
 35 R.Engine.define({
 36     "class":"R.particles.Emitter",
 37     "requires":[
 38         "R.engine.PooledObject"
 39     ]
 40 });
 41 
 42 /**
 43  * @class Particle emitter class.  Emits particles at a regular
 44  *    interval as long as it is active.  The function that is passed to generate
 45  *    the particles will be called with three arguments: an offset position, the
 46  *    current world time, and the delta from when the last frame was drawn.  The function
 47  *    can either return a single particle or an <code>Array</code> of particles.
 48  *    Within the scope of the function, "this" refers to the {@link R.particles.Emitter}
 49  *    object.
 50  *    <pre>
 51  *       // Create the particle emitter which returns the type of particle
 52  *       // we want to emit.  5 is the delay between particle emissions and
 53  *       // 350 is the life of the particle (both in milliseconds)
 54  *       var emitter = R.particles.Emitter.create(function(offset) {
 55  *          // Create a particle
 56  *          return FuseParticle.create(offset, 350);
 57  *       }, 5);
 58  *
 59  *       // Assign the emitter to the particle engine which will draw it
 60  *       emitter.setParticleEngine(Tutorial13.pEngine);
 61  *    </pre>
 62  *
 63  * @param emitFunc {Function} A function that emits new particles.
 64  * @param interval {Number} The time between emissions
 65  * @param [active] {Boolean} A flag indicating whether the emitter should emit particles
 66  * @extends R.engine.PooledObject
 67  * @constructor
 68  * @description Create a particle emitter
 69  */
 70 R.particles.Emitter = function () {
 71     return R.engine.PooledObject.extend(/** @scope R.particles.Emitter.prototype */{
 72 
 73         active:true,
 74         emitFn:null,
 75         interval:null,
 76         nextEmit:0,
 77         engine:null,
 78 
 79         /** @private */
 80         constructor:function (emitFunc, interval, active) {
 81             this.base("ParticleEmitter");
 82             this.emitFn = emitFunc;
 83             this.interval = interval;
 84             this.active = active === undefined ? true : active;
 85             this.nextEmit = 0;
 86             this.engine = null;
 87         },
 88 
 89         /**
 90          * Release the particle back into the pool.
 91          */
 92         release:function () {
 93             this.base();
 94             this.interval = null;
 95             this.emitFn = null;
 96             this.active = true;
 97             this.nextEmit = 0;
 98             this.engine = null;
 99         },
100 
101         /**
102          * Set the active state of the particle emitter
103          * @param state {Boolean} <code>true</code> to enable emission of particles, <code>false</code> to
104          *    disable emission.
105          */
106         setActive:function (state) {
107             this.active = state;
108         },
109 
110         /**
111          * Method to check if the emitter is active.
112          * @return {Boolean}
113          */
114         isActive:function () {
115             return this.active;
116         },
117 
118         /**
119          * Set the interval at which particles are emitted.
120          * @param interval {Number} The number of milliseconds between emissions
121          */
122         setInterval:function (interval) {
123             this.interval = interval;
124         },
125 
126         /**
127          * Return the interval at which particles are emitted.
128          * @return {Number}
129          */
130         getInterval:function () {
131             return this.interval;
132         },
133 
134         /**
135          * Set the particle engine the particle emitter should emit particles to.
136          * @param particleEngine {R.particles.ParticleEngine}
137          */
138         setParticleEngine:function (particleEngine) {
139             this.engine = particleEngine;
140         },
141 
142         /**
143          * Emit a particle to the particle engine, if the emitter is active.
144          * @param offset {R.math.Point2D} Offset from the particle's position to render at
145          * @param time {Number} The world time, in milliseconds
146          * @param dt {Number} The delta between the world time and the last time the world was updated
147          *          in milliseconds.
148          * @private
149          */
150         emit:function (offset, time, dt) {
151             if (this.active && time > this.nextEmit) {
152                 this.nextEmit = time + this.interval;
153                 var particles = this.emitFn.call(this, offset, time, dt);
154                 if (particles.length) {
155                     this.engine.addParticles(particles);
156                 } else {
157                     this.engine.addParticle(particles);
158                 }
159             }
160         }
161 
162     }, /** @scope R.particles.Emitter.prototype */ {
163         /**
164          * Get the class name of this object
165          *
166          * @return {String} "R.particles.Emitter"
167          */
168         getClassName:function () {
169             return "R.particles.Emitter";
170         }
171     });
172 
173 }