hybrid-brush-07
...
@author bouze
// forked from bouze's hybrid-brush-06
// forked from bouze's hybrid-brush-05
// forked from bouze's hybrid-brush-04
// forked from bouze's hybrid-brush-03
// forked from bouze's hybrid-brush-02
// forked from bouze's hybrid-brush-01
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.filters.BlurFilter;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
/**
* ...
* @author bouze
*/
[SWF(frameRate="60", backgroundColor="#BBCC99")]
public class Main extends Sprite
{
private var drawLayer:Sprite;
private var particles:Array = new Array();
private var pNum:int = 10;
private var maxDistance:Number = 30;
private var friction:Number = 0.90;
private var gravity:Number = 0.01;
private var hardness:Number = 0.2;
private var joinPointNum:int = 5;
private var canvas:BitmapData;
private var refreshRate:int = 1;
private var blurRate:int = 5;
private var counter:int = 0;
public function Main()
{
init();
}
private function init():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.LOW;
drawLayer = new Sprite();
addChild( drawLayer );
initCanvas();
initParticles();
addEventListener( Event.ENTER_FRAME, update );
stage.addEventListener( Event.RESIZE, setupCanvas );
}
private function update(e:Event):void
{
move();
draw();
capture();
}
private function initParticles():void
{
var i:int;
for (i = 0; i < pNum; i++)
{
var sp:Sprite = new Sprite();
//sp.blendMode = BlendMode.OVERLAY;
drawLayer.addChild( sp );
particles[ i ] =
{
x: mouseX,
y: mouseY,
ref: sp,
vx: 0,
vy: 0
};
}
}
private function initCanvas():void
{
if ( canvas )
{
canvas.dispose();
}
canvas = new BitmapData( stage.stageWidth - 1, stage.stageHeight, true, 0x000000 );
var bm:Bitmap = new Bitmap( canvas );
addChild( bm );
}
private function setupCanvas(e:Event):void
{
initCanvas();
}
private function capture():void
{
if ( counter % refreshRate == 0 )
{
canvas.lock();
canvas.draw( drawLayer );
var ct:ColorTransform = new ColorTransform();
if ( counter % blurRate == 0 )
{
//canvas.applyFilter( canvas, canvas.rect, new Point(), new BlurFilter( 1.1, 1.1, 1 ) );
ct = new ColorTransform( 1.0, 0.99, 1.0, 0.99, 0, 0, 0, 0 );
}
canvas.colorTransform( canvas.rect, ct );
canvas.unlock();
}
counter++;
}
private function move():void
{
particles[ 0 ].x = stage.mouseX;
particles[ 0 ].y = stage.mouseY;
var c:Number;
for ( c = 1; c < pNum; c++)
{
var p:Object = particles[ c ];
var pp:Object = particles[ c - 1 ];
p.vx *= friction;
p.vy *= friction;
//尻の方が重たくなるように
p.vy += gravity * c * 0.3;
p.x += p.vx;
p.y += p.vy;
var X:Number = p.x - pp.x;
var Y:Number = p.y - pp.y;
var distance:Number = Math.sqrt( X * X + Y * Y );
var angle:Number = Math.atan2( Y, X );
if ( distance > maxDistance )
{
var ox:Number = p.x;
var oy:Number = p.y;
//強く引っ張ったら伸びるように
var tx:Number = pp.x + maxDistance * Math.cos( angle );
var ty:Number = pp.y + maxDistance * Math.sin( angle );
p.x += ( tx - p.x ) * hardness;
p.y += ( ty - p.y ) * hardness;
//p.x = pp.x + maxDistance * Math.cos( angle );
//p.y = pp.y + maxDistance * Math.sin( angle );
p.vx += ( p.x - ox ) * 0.1;
p.vy += ( p.y - oy ) * 0.1;
}
}
}
private function draw():void
{
var i:int;
for (i = 0; i < pNum - joinPointNum; i++)
{
var p:Array = particles;
var mtrx:Matrix = new Matrix();
mtrx = createLinearGradientMatrix( p[ i ].x, p[ i ].y, p[ i + joinPointNum ].x, p[ i + joinPointNum ].y)
var g:Graphics = p[ i ].ref.graphics;
g.clear();
g.beginGradientFill(GradientType.LINEAR, [ 0xFF00AA, 0x00DDDD ], [ 0.3, 0.1 ], [ 96, 255 ], mtrx);
//g.moveTo( p[ i ].x, p[ i ].y );
//curveThrough3Pts(g, p[ i ].x, p[ i ].y, p[ i + 1 ].x, p[ i + 1 ].y, p[ i + 2 ].x, p[ i + 2 ].y );
//curveThrough3Pts(g, p[ i + 2 ].x, p[ i + 2 ].y, p[ i + 3 ].x, p[ i + 3 ].y, p[ i + 4 ].x, p[ i + 4 ].y );
g.moveTo( p[ i ].x, p[ i ].y );
var n:int
for ( n = 1; n <= joinPointNum; n++ )
{
g.lineTo( p[ i + n ].x, p[ i + n ].y );
}
g.lineTo( p[ i ].x, p[ i ].y );
g.endFill();
}
}
/**
* 三点を通る二次元曲線
* via 詳説ActionScript 3.0(p.700)
*/
/*
private function curveThrough3Pts
(
g:Graphics,
startX:Number,
startY:Number,
throughX:Number,
throughY:Number,
endX:Number,
endY:Number
):void
{
var controlX:Number = ( 2 * throughX ) - 0.5 * ( startX + endX );
var controlY:Number = ( 2 * throughY ) - 0.5 * ( startY + endY );
g.moveTo( startX, startY );
g.curveTo( controlX, controlY, endX, endY );
}
*/
/**
* Make matrix for linear gradient
* via http://nutsu.com/blog/2009/020921_as_gradient_matrix.html
*/
private function createLinearGradientMatrix( x0:Number, y0:Number, x1:Number, y1:Number ):Matrix
{
var mtrx:Matrix = new Matrix();
mtrx.createGradientBox( 1, 1, 0, -0.5, -0.5 );
var vx:Number = x1 - x0;
var vy:Number = y1 - y0;
var w:Number = Math.sqrt( vx * vx + vy * vy );
var r:Number = Math.atan2( vy, vx );
var cx:Number = ( x0 + x1 ) / 2;
var cy:Number = ( y0 + y1 ) / 2;
mtrx.scale( w, 1 );
mtrx.rotate( r );
mtrx.translate( cx, cy );
return mtrx;
}
}
}