Inspired by Andrés
fur-experiments and the
perlin-particles by Joa this
little Webcam idea crossed my mind.
It uses a perlin noise force to position the particles. The particles save their position, have a lifespan and color
information.
The code for the particle effect is fairly simple. First there is the Particle class:
public class Particle
{
public var next: Particle;
public var posX: Number;
public var posY: Number;
public var velocityX: Number;
public var velocityY: Number;
public var livespan: int;
public var age: int;
public var color: int;
}
Then the actual force and rendering class. First setup the input and output:
private function init():void
{
var cam:Camera = Camera.getCamera();
cam.setMode( 640, 480, 30 );
_video = new Video( cam.width, cam.height );
_video.attachCamera( cam );
_input = new BitmapData( _dim.width, _dim.height, true, 0 );
_output = new BitmapData( _dim.width, _dim.height, true, 0 );
_outputBlur = new BitmapData( _dim.width, _dim.height, false, 0 );
addChild( new Bitmap( _output ) );
var scale: Number = 4;
_noise = new BitmapData( _dim.width / scale, _dim.height / scale, false, 0 );
_force = new BitmapData( _dim.width, _dim.height, true, 0 );
_scaleMatrix = new Matrix();
_scaleMatrix.scale( scale, scale );
}
Then the setup the particles:
private function setupParticles(): void
{
var p: Particle;
var n: int = NUM_PARTICLES;
p = _particles = new Particle();
while( --n > -1)
{
p = p.next = new Particle();
p.posX = Math.random( ) * _dim.width;
p.posY = Math.random() * _dim.height;
p.velocityX = Math.random();
p.velocityY = Math.random();
p.livespan = Math.random() * 20;
p.age = 0;
}
}
The last part is a render-loop / enterframe handler:
private function render( e: Event ): void
{
_input.draw( _video );
_p0.x += SPEED;
_p0.y -= SPEED;
_p1.x -= SPEED;
_p1.y += SPEED;
_noise.perlinNoise( 10.0, 10.0, 2, 2, false, true, BitmapDataChannel.GREEN | BitmapDataChannel.BLUE, false, _octaves );
_force.draw( _noise, _scaleMatrix );
var particle: Particle = _particles.next;
do
{
force = _force.getPixel( particle.posX, particle.posY );
++particle.age;
if( particle.age > particle.livespan )
{
particle.posX = Math.random() * _dim.width;
particle.posY = Math.random() * _dim.height;
particle.color = _input.getPixel( particle.posX, particle.posY );
particle.age = 0;
}
else
{
if( ( force >> 8 & 0xff ) > 0x80 )
++particle.posX;
else
--particle.posX;
if( ( force & 0xff ) > 0x80 )
++particle.posY;
else
--particle.posY;
particle.posX += particle.velocityX;
particle.posY += particle.velocityY;
a = 0xff * ( particle.age / particle.livespan ) >> 24;
r = particle.color >> 16;
g = particle.color >> 8;
b = particle.color ;
_outputBlur.setPixel( particle.posX, particle.posY, ( a << 24 | r << 16 | g << 8 | b ) );
}
particle = particle.next;
}
while( particle );
_output.copyPixels( _outputBlur, _outputBlur.rect, origin );
_outputBlur.applyFilter( _outputBlur, _outputBlur.rect, origin, filter );
}