Marc Hughes


Home
Blog
Twitter
LinkedIn
GitHub
about
I am a developer from a bit west of Boston.

Pulse Particles + BitmapData

13 Feb 2008

Did a little work with getting the Pulse Particle system working with a BitmapData object.  Now you can do fun things like get particle trails, apply blur filters, etc.  Below are two examples of using that.




This first example shows a very simple particle system with some particle trails.  We're also using a new rule called the "ColorTransformRule" which causes a color transformation to happen over time.




package
{
import com.roguedevelopment.pulse.PulseEngine;
import com.roguedevelopment.pulse.emitter.BitmapEmitter;
import com.roguedevelopment.pulse.simple.SimpleParticles;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageScaleMode;

[SWF(backgroundColor="#000000", frameRate="30", width="500", height="350")]
public class BitmapExample extends Sprite
{
[Embed(source="exampleassets/spark.png")]
protected var spark:Class;


public function BitmapExample()
{
stage.scaleMode = StageScaleMode.NO
SCALE;
super();
PulseEngine.instance.root = this;
var bmd:BitmapData = new BitmapData( 500, 350, false, 0 );
var bm:Bitmap = new Bitmap(bmd);
addChild(bm);
var emitter:BitmapEmitter = new BitmapEmitter(20, bmd );
SimpleParticles.configureEmitterByObject(emitter, {bound:[0,0,500,350],colorTransform:[300,3000,0,0,0,200,200,0], pps:23,x:250, y:40, width:1, height:1,image:spark, movement:true, minSpeed:80, maxSpeed:100, minAngle:0, maxAngle:360, minScale:0.4, maxScale:0.75, gravity:6, fade:2350, lifespan:2340} );
}
}
}





The second example takes the StarPower example from before and adds the same sort of effect.

Source code follows...






/
This examples creates three particle emitters.

Each of those emitters is on a container sprite which is not in the display list.

We have an ENTER_FRAME event handler which copies the image from those containers to a BitmapData object which is displayed on screen. Every
frame we also apply a color transformation to cause previous draws to fade out. This leaves a pleasing trail.

Finally, we use Tweener to rotate, scale, and position the containers randomly giving some fairly interesting visual behavior.
/
package
{
import caurina.transitions.Tweener;

import com.roguedevelopment.pulse.emitter.GenericEmitter;
import com.roguedevelopment.pulse.simple.SimpleParticles;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.filters.BitmapFilter;
import flash.filters.ColorMatrixFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.Timer;

[SWF(backgroundColor="#000000", frameRate="30", width="500", height="350")]
public class StarPower extends Sprite
{
protected var containers:Array = [];
protected var timer:Timer;
protected var ease:int = 0;

[Embed(source="exampleassets/star.png")]
protected var star:Class;
[Embed(source="example
assets/spark.png")]
protected var spark:Class;
[Embed(source="exampleassets/snowflake.png")]
protected var snow:Class;

protected var bmd:BitmapData;
protected var bm:Bitmap;
protected var fullRect:Rectangle = new Rectangle(0,0,500,350);
protected var origin:Point = new Point(0,0);

protected var filterz:Array = [ //new BlurFilter( 1, 1, 1 ) ,
new ColorMatrixFilter( [ 1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0.85,0 ] ) ];


public function StarPower()
{
super();

addEmitter(star,10);
addEmitter(snow,5);
addEmitter(spark,15);

bmd = new BitmapData(500,350,false,0x000000);
bm = new Bitmap( bmd );
addChild(bm);

stage.scaleMode = "noScale";
onTimer(null);
timer = new Timer(5000);
timer.addEventListener(TimerEvent.TIMER, onTimer );
timer.start();
addEventListener(Event.ENTER
FRAME, onEnterFrame );
}



protected function onEnterFrame(event:Event) : void
{
// First, apply any filters we set up, in this example it's just the one color transform
for each (var filter:BitmapFilter in filterz )
{
bmd.applyFilter( bmd, fullRect, origin, filter );
}

// Then, for each of our particle containers, copy that to the bitmap with the appropriate transformations.
for each ( var container:Sprite in containers )
{
var m:Matrix = new Matrix();// container.x, container.y);
m.rotate( container.rotation * Math.PI / 180);
m.translate( container.x, container.y );
m.scale( container.scaleX, container.scaleY );
bmd.draw(container,m);
}
}

/
* This creates a simple emitter that was configured using the particle explorer.
/
protected function addEmitter( image:Class, pps:Number ) : void
{
var container:Sprite = new Sprite();
var emitter:GenericEmitter = SimpleParticles.createEmitter({pps:pps,x:100, image:image, y:100, width:1, height:1,size:15, color:2588900, movement:true, minSpeed:63.3, maxSpeed:353.6, minAngle:0, maxAngle:360, minScale:0.2, maxScale:1, lifespan:3140} ) as GenericEmitter;
emitter.root = container;
emitter.start();
containers.push(container);
}

// Every 5 seconds we cause the containers to go through a new random tweening
protected function onTimer(e:Event) : void
{
for each( var container:Sprite in containers )
{
animateContainer( container );
}
}

protected function animateContainer(container:Sprite) : void
{
var eases:Array = ["easeinoutsine","easeoutcirc","easeoutback","easeoutbounce","easeoutelastic"];
var scale:Number = Math.random() + 0.05;
ease++; ease %= 5;
Tweener.addTween( container, { y:Math.random() * 350, x:Math.random()*500, scaleX:scale, scaleY:scale, time:5, transition:eases[ease] });
Tweener.addTween(container, {rotation: Math.random() * 360, time:5, transition:eases[ease] }) ;
}
}
}