I’ve been trying to encapsulate Senoculars brilliant PerlinNoise Flag Wave example into a self contained AS2 class.
The original Fla example is here:
http://www.senocular.com/flash/source.php?id=0.188
I’ve tried to remove the need for having displacement Maps and bounding boxes in the target movieClip, by dynamically drawing them within the class itself.
I have so far succeeded and the effect works almost perfectly. However, the original example uses the alpha values of the displacement map to determine where, and how much displacement should take place. In my version though, I can’t seem to tie the alpha values to the displacement. The noise happens uniformly across the displacement map, no matter how much alpha there is. (Should be none from the left edge where there is 100% alpha).
My Class is contained below, and still needs a lot of refactoring and openness to dynamic values, but if anyone can help me figure out why the displacement seems uniform, I’d very much appreciate it.
[AS]
/**
-
@author d.robert hall
*/
import com.bourre.commands.Delegate;
import com.bourre.log.PixlibStringifier;
import com.bourre.transitions.FPSBeacon;
import com.bourre.transitions.IFrameListener;
import flash.display.BitmapData;
import flash.filters.DisplacementMapFilter;
import flash.geom.Matrix;
import flash.geom.Point;
class com.skivecreative.effects.FlagRipple
implements IFrameListener
{
private var speed:Number;
private var channel:Number;
private var baseX:Number;
private var baseY:Number;
private var octs:Number;
private var seed:Number;
private var stitch:Boolean;
private var fractal:Boolean;
private var gray:Boolean;
private var flapX:Number;
private var flapY:Number;
private var mode:String;
private var offset:Point;
private var displaceBitmap:BitmapData;
private var displaceFilter:DisplacementMapFilter;
private var ramp:MovieClip;
private var noiseBitmap:BitmapData;
private var shift:Matrix;
private var onEnterFrameHandler:Function;
private var target:MovieClip;
private var displace:MovieClip;
private var perlin:MovieClip;
private var ripple:MovieClip;
private var maxWidth:Number;
private var maxHeight:Number;
private var clampBox:MovieClip;
/* CONSTRUCTOR ********************************************************************************/
public function FlagRipple( target:MovieClip, maxWidth:Number, maxHeight:Number ) {
this.target = target;
this.maxWidth = maxWidth;
this.maxHeight = maxHeight;
speed = 3; // speed at which noise is shifted (causes flap)
channel = 1; // red - red used to displace pixels along
baseX = 80; // size of noise in x axis
baseY = 0; // size of noise in y axis
octs = 1; // noise functions for noise (smaller = faster)
seed = 20; // random seed for noise
stitch = true; // stitching makes the noise wrap making it easy to repeat
fractal = true; // use fractal noise
gray = false; // grayscale is not used because the red channel is
flapX = 0; // power of pixel displacement along x axis
flapY = 20; // power of pixel displacement along y axis
mode = "clamp"; // clamp the image so none of the original is seen
offset = new Point( 0, 0 ); // displacment map offset
init();
}
/* PUBLIC METHODS *****************************************************************************/
public function init()
{
ripple = target.ripple_mc;
drawDisplacementMap();
setClampBox();
displaceFilter = new DisplacementMapFilter(
displaceBitmap, offset, channel, channel, flapX, flapY, mode );
shift = new Matrix();
noiseBitmap = new BitmapData( 500, 1 );
noiseBitmap.perlinNoise( baseX, baseY, octs, seed, stitch, fractal, channel, gray );
FPSBeacon.getInstance().addFrameListener( this );
onEnterFrameHandler = Delegate.create( this, update );
}
public function onEnterFrame () : Void
{
onEnterFrameHandler();
}
public function flush () : Void
{
ripple.removeMovieClip();
ripple = target.ripple_mc;
ripple.swapDepths( target.getNextHighestDepth() );
setClampBox();
}
/* PRIVATE METHODS ****************************************************************************/
private function setClampBox () : Void
{
clampBox = ripple.createEmptyMovieClip( "clampBox", ripple.getNextHighestDepth() );
clampBox._x = -( maxWidth / 2 );
clampBox._y = -( maxHeight / 2 );
clampBox.moveTo( 0, 0 );
clampBox.lineStyle( 1, 0xFF0000, 0 );
clampBox.lineTo( 0, maxHeight );
clampBox.lineTo( maxWidth, maxHeight );
}
private function drawDisplacementMap () : Void
{
displace = target.createEmptyMovieClip( "displace_mc", target.getNextHighestDepth() );
ramp = displace.createEmptyMovieClip( "ramp", displace.getNextHighestDepth() );
displace._x = -60;
displace._y = -25;
var dFillType:String = "linear";
var dColors:Array = [0x800000, 0x800000];
var dAlphas:Array = [100, 0];
var dRatios:Array = [255, 0];
var dMatrix:Object = {matrixType:"box", x:0, y:0, w:180, h:50, r:0/180*Math.PI};
ramp.lineStyle(1, 0x000000, 0);
ramp.beginGradientFill( dFillType, dColors, dAlphas, dRatios, dMatrix );
ramp.moveTo( 0, 0 );
ramp.lineTo( 180, 0 );
ramp.lineTo( 180, 50 );
ramp.lineTo( 0, 50 );
ramp.lineTo( 0, 0 );
ramp.endFill();
perlin = displace.createEmptyMovieClip( "perlin", 1 );
displaceBitmap = new BitmapData( ramp._width, ramp._height );
displace._visible = false;
}
private function update () : Void
{
shift.translate( speed, 0 );
perlin.clear();
perlin.beginBitmapFill( noiseBitmap, shift );
perlin.moveTo( 0, 0 );
perlin.lineTo( ramp._width, 0 );
perlin.lineTo( ramp._width, ramp._height );
perlin.lineTo( 0, ramp._height );
perlin.lineTo( 0, 0 );
perlin.endFill();
displaceBitmap.draw( displace );
ripple.filters = [displaceFilter];
}
/* DEFAULT ************************************************************************************/
public function toString() : String
{
return PixlibStringifier.stringify( this );
}
public function destroy() : Void
{
FPSBeacon.getInstance().removeFrameListener( this );
}
}
[/AS]