Particle and ParticleEmitter with collisions

Got a question? Need help? Post here!

Particle and ParticleEmitter with collisions

Postby srikanth » Sat Sep 14, 2013 2:01 am

I was having trouble with particles today morning, so made two separate classes. One called Partikil and the other called PartikilEmiter(borrowed some code from flixel). This way particles can collide. I haven't experimented with a large number of particles!
This might not be the most efficient way either. Please let me know and feel free to make changes to the code.
The following is the particle class, you can add animations and effects to it.
Code: Select all
package
{
   import org.axgl.*;
   public class Partikil extends AxSprite
   {
      public var lifespan:Number;
      public var bbox:AxRect;
      public function Partikil():void
      {
         super(0, 0);
         bbox = new AxRect;         
         exists = false;
      }
      override public function update():void
      {
         if (lifespan <= 0) return;
         if (lifespan > 0) lifespan -= Ax.dt;
         if (lifespan <= 0) exists = false;
         if (x > bbox.x && x < bbox.x+bbox.width && y > bbox.y && y < bbox.y+bbox.height)
         {
            
         }
         else exists = false
         super.update();
      }
      
      public function onEmit():void
      {
         
      }
   }
}


The following is the emitter class:
Code: Select all
package 
{
   import org.axgl.*;
   import org.axgl.input.AxKey;
   public class PartikilEmiter extends AxGroup
   {
      public var minParticleSpeed:AxPoint;
      /**
       * The maximum possible velocity of a particle.
       * The default value is (100,100).
       */
      public var maxParticleSpeed:AxPoint;
      /**
       * The X and Y drag component of particles launched from the emitter.
       */
      public var particleDrag:AxPoint;
      /**
       * The minimum possible angular velocity of a particle.  The default value is -360.
       * NOTE: rotating particles are more expensive to draw than non-rotating ones!
       */
      public var minRotation:Number;
      /**
       * The maximum possible angular velocity of a particle.  The default value is 360.
       * NOTE: rotating particles are more expensive to draw than non-rotating ones!
       */
      public var maxRotation:Number;
      /**
       * Sets the <code>acceleration.y</code> member of each particle to this value on launch.
       */
      public var gravity:Number;
      /**
       * Determines whether the emitter is currently emitting particles.
       * It is totally safe to directly toggle this.
       */
      public var on:Boolean;
      /**
       * How often a particle is emitted (if emitter is started with Explode == false).
       */
      public var frequency:Number;
      /**
       * How long each particle lives once it is emitted.
       * Set lifespan to 'zero' for particles to live forever.
       */
      public var lifespan:Number;
      /**
       * How much each particle should bounce.  1 = full bounce, 0 = no bounce.
       */
      public var bounce:Number;
      /**
       * Internal helper for the style of particle emission (all at once, or one at a time).
       */
      protected var _explode:Boolean;
      /**
       * Internal helper for deciding when to launch particles or kill them.
       */
      protected var _timer:Number;
      /**
       * Internal counter for figuring out how many particles to launch.
       */
      protected var _counter:uint;
      
      /**
       * Bounding box of the area the particle system should cover
       */
      protected var _bbox:AxRect;
      
      // dummy x
      public var _x:Number = 0;
      // dummy y
      public var _y:Number = 0;
      // counter
      private var i:int = 0;
      /**
       *
       * @param   X   
       * @param   Y
       */
      public function PartikilEmiter(X:Number, Y:Number):void
      {
         _timer = 0;         
         minParticleSpeed = new AxPoint(-100,-100);
         maxParticleSpeed = new AxPoint(100,100);
         minRotation = -360;
         maxRotation = 360;
         gravity = 0;
         particleDrag = new AxPoint();
         _bbox = new AxRect;
         _explode = false;
         on = false;
         
         super();
         _x = X;
         _y = Y;
         
      }
      
      /**
       *  update block
       */
      override public function update():void
      {
         if (on)
         {
            if (_explode)
            {
               for (i = 0; i < members.length; i++)
                  emitt();
               on = false;
            }
            else
            {
               _timer += Ax.dt;
               if (_timer >= frequency && frequency >0)
               {
                  _timer = 0;
                  emitt();
               }
            }
         }
         super.update();
      }
      
      /**
       * Destroy
       */
      override public function destroy():void
      {
         on = false;
         super.destroy();
      }
      
      /**
       * Dispose
       */
      override public function dispose():void
      {
         minParticleSpeed = null;
         maxParticleSpeed = null;
         particleDrag = null;
         super.dispose();
      }
      
      /**
       *
       * @param   Explode      Should be set to true for explosion and false if you want to emit particles one by one
       * @param   Lifespan   How long a particle should live
       * @param   Frequency   Ignored if Explode is set to true. Frequency is how often to emit a particle. 0 = never emit, 0.1 = 1 particle every 0.1 seconds, 5 = 1 particle every 5 seconds.
       */
      public function start(Explode:Boolean=false,Lifespan:Number=0,Frequency:Number=0.1):void
      {
         on = true;
         _explode = Explode;
         
         frequency = Frequency;
         lifespan = Lifespan;
      }
      
      /**
       * Stop the emitter
       */
      public function stopp():void
      {
         on = false;
      }
      
      /**
       * Internal emit function
       */
      protected function emitt():void
      {
         var particle:Partikil = Partikil(recycle());
         particle.x = _x + Math.random() * width;
         particle.y = _y +Math.random() * height;
         particle.lifespan = lifespan;
         particle.onEmit();
         
         if(minParticleSpeed.x != maxParticleSpeed.x)
            particle.velocity.x = minParticleSpeed.x + Math.random()*(maxParticleSpeed.x-minParticleSpeed.x);
         else
            particle.velocity.x = minParticleSpeed.x;
         if(minParticleSpeed.y != maxParticleSpeed.y)
            particle.velocity.y = minParticleSpeed.y + Math.random()*(maxParticleSpeed.y-minParticleSpeed.y);
         else
            particle.velocity.y = minParticleSpeed.y;
         particle.acceleration.y = gravity;
         
         if(minRotation != maxRotation)
            particle.velocity.a = minRotation + Math.random() * (maxRotation - minRotation);
         else
            particle.velocity.a = minRotation;
         if(particle.velocity.a != 0)
            particle.angle = Math.random()*360-180;
         
         particle.drag.x = particleDrag.x;
         particle.drag.y = particleDrag.y;
         
         particle.bbox = _bbox;
      }
      
      /**
       * A more compact way of setting the width and height of the emitter.
       *
       * @param   Width   The desired width of the emitter (particles are spawned randomly within these dimensions).
       * @param   Height   The desired height of the emitter.
       */
      public function setSize(Width:uint,Height:uint):void
      {
         width = Width;
         height = Height;
      }
      
      /**
       * A more compact way of setting the X velocity range of the emitter.
       *
       * @param   Min      The minimum value for this range.
       * @param   Max      The maximum value for this range.
       */
      public function setXSpeed(Min:Number=0,Max:Number=0):void
      {
         minParticleSpeed.x = Min;
         maxParticleSpeed.x = Max;
      }
      
      /**
       * A more compact way of setting the Y velocity range of the emitter.
       *
       * @param   Min      The minimum value for this range.
       * @param   Max      The maximum value for this range.
       */
      public function setYSpeed(Min:Number=0,Max:Number=0):void
      {
         minParticleSpeed.y = Min;
         maxParticleSpeed.y = Max;
      }
      
      /**
       * A more compact way of setting the angular velocity constraints of the emitter.
       *
       * @param   Min      The minimum value for this range.
       * @param   Max      The maximum value for this range.
       */
      public function setRotation(Min:Number=0,Max:Number=0):void
      {
         minRotation = Min;
         maxRotation = Max;
      }
      
      /**
       * Bounding box
       */
      public function setBoundingBox(X:Number, Y:Number, Width:Number, Height:Number):void
      {
         _bbox = new AxRect(X, Y, Width, Height);
      }
   }
}


While defining the emitter in your main game state, initialize it like this:

Code: Select all
emitr = new PartikilEmiter(50,400);
add(emitr);
emitr.setXSpeed( 0, 0);
emitr.setYSpeed( 0, 0);
emitr.setSize(1, 1);
emitr.setRotation(0, 0);
emitr.gravity = 00;
emitr.setBoundingBox(0, 0, Ax.width, Ax.height);
for (i = 0; i < 30; i++)
   emitr.add(new Tt(0, 0, i+10)); // Tt is an extended Partikil class


In the update state, if you want to move the emitter according to the mouse you can do:
Code: Select all
emitr._x = Ax.mouse.x;
emitr._y = Ax.mouse.y;


Collisions are easy too:
Code: Select all
Ax.collide(emitr, Tiles);
srikanth
Sergeant
 
Posts: 25
Joined: Wed Jul 31, 2013 3:19 am

Return to Help

Who is online

Users browsing this forum: No registered users and 1 guest

cron