水滴っぽいもの
// forked from nabe's カラフルな塗り
// forked from nabe's 変則的な塗り
// forked from nabe's 球面っぽい塗り
// forked from nabe's ソースの雛形
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.filters.*;
[SWF(width="465", height="465", backgroundColor="0xAABBCC", frameRate="1")];
public class BaseClass extends Sprite {
private var W_:uint;
private var H_:uint;
private var filter_:DisplacementMapFilter;
private var grid_:Shape;
private var radius_:Number;
private var point_:Point = new Point(0, 0);
private var highlight_:Shape;
public function BaseClass () {
//コンストラクタ。ここから全体の処理が開始する。
//1.初期化処理の呼び出しを仕込むに留める。
addEventListener(Event.ADDED_TO_STAGE, init_);
}
private function init_ (event_:Event):void {
//初期化処理。
//1.用済みのリスナ登録を解除する。
event_.target.removeEventListener(event_.type, arguments.callee);
//2.実際の処理を書き足す。
sample_();
}
private function sample_ ():void {
//サンプル処理。
//1.画面サイズを取得する。
W_ = stage.stageWidth;
H_ = stage.stageHeight;
//2.画面中央の位置を求める。
var cx_:uint = W_>>1;
var cy_:uint = H_>>1;
//3.縦横の長さの短い方を選ぶ。
var cr_:uint = cx_ < cy_ ? cx_ : cy_;
var cz_:Number = 30;
var k_:Number = 0.25;
radius_ = cr_ * k_;
//4.変形フィルタを作成する。
resetPos_();
filter_ = new DisplacementMapFilter(
createBmd_(cr_ * k_), point_,
BitmapDataChannel.RED,
BitmapDataChannel.GREEN,
-cz_ * k_, -cz_ * k_,
DisplacementMapFilterMode.IGNORE,
0x0, 0);
//5.変形対象を作成する。
grid_ = createGrid_();
addChild(grid_);
//6.ハイライトを作成する。
highlight_ = createHighlight_();
addChild(highlight_);
//6.アニメーションを設定する。
addEventListener(Event.ENTER_FRAME, update_);
}
private function createHighlight_ ():Shape {
var shape_:Shape = new Shape();
var graphics_:Graphics = shape_.graphics;
var rect_:Rectangle = new Rectangle(0, 0, 2 * radius_, 2 * radius_);
var matrix_:Matrix = new Matrix();
matrix_.createGradientBox(rect_.width, rect_.height, Math.PI/4, rect_.x, rect_.y);
const focalPointRatio_:Number = -0.75;
graphics_.beginGradientFill(
GradientType.RADIAL,
[0xFFFFFF, 0xFFFFFF, 0xCCDDEE],
[0.85,0,0.5],
[0, 0xCF, 0xFF],
matrix_,
SpreadMethod.PAD,
InterpolationMethod.RGB,
focalPointRatio_
);
graphics_.drawEllipse(rect_.x, rect_.y, rect_.width, rect_.height);
graphics_.endFill();
return shape_;
}
private function resetPos_ ():void {
point_.y = -2 * radius_;
point_.x = W_ * (Math.random() + 0.5) * 0.3;
}
private function update_ (event_:Event):void {
var newX:int = point_.x + 5 * (Math.random() - 0.25);
if (newX < -2 * radius_) newX += W_;
if (newX > W_) newX -= W_;
point_.x = newX;
var newY:int = point_.y + 10 * Math.random();
point_.y = newY;
if (newY > H_) {
resetPos_();
}
filter_.mapPoint = point_;
grid_.filters = [filter_];
highlight_.x = point_.x;
highlight_.y = point_.y;
}
private function createGrid_ ():Shape {
//縦横の罫線を描く。
var shape_:Shape = new Shape();
var graphics_:Graphics = shape_.graphics;
const span_:uint = 32;
graphics_.beginFill(0xDDEEFF);
graphics_.drawRect(0, 0, W_, H_);
graphics_.endFill();
graphics_.lineStyle(5, 0x9999FF);
for (var x_:uint = 5; x_ < W_; x_ += span_) {
graphics_.moveTo(x_, 0);
graphics_.lineTo(x_, H_);
}
for (var y_:uint = 3; y_ < H_; y_ += span_) {
graphics_.moveTo(0, y_);
graphics_.lineTo(W_, y_);
}
return shape_;
}
private function createBmd_ (cr_:uint):BitmapData {
//ビットマップを作成する。
//辺の長さが2 * cr_の正方形を返す。
var shape_:Shape = createShape_(cr_);
var bmd_:BitmapData = new BitmapData(2 * cr_, 2 * cr_, false);
//灰色をベースとする。
bmd_.fillRect(new Rectangle(0, 0, W_, H_), 0x808080);
var matrix_:Matrix = new Matrix();
var ct_:ColorTransform;
//赤のチャンネルに円のパタンを乗せる。
ct_ = new ColorTransform(1, 0, 0);
bmd_.draw(shape_, null, ct_, BlendMode.LIGHTEN);
//赤のチャンネルの左半分の階調を反転する。
ct_ = new ColorTransform(
-1, 1, 1, 1,
0x100, 0, 0, 0);
bmd_.colorTransform(new Rectangle(0, 0, cr_, 2 * cr_), ct_);
//円のパタンを90度回転して緑のチャンネルに乗せる。
ct_ = new ColorTransform(0, 1, 0);
matrix_.createBox(1, 1);
matrix_.rotate(Math.PI/2);
matrix_.translate(2 * cr_, 0);
bmd_.draw(shape_, matrix_, ct_, BlendMode.LIGHTEN);
//緑のチャンネルの上半分の階調を反転する。
ct_ = new ColorTransform(
1, -1, 1, 1,
0, 0x100, 0, 0);
bmd_.colorTransform(new Rectangle(0, 0, 2 * cr_, cr_), ct_);
//結果を返す。
return bmd_;
}
private function createShape_ (cr_:uint):Shape {
//シェイプを作成する。
//関数 y = x - x^3 を利用して円を塗り潰す。半径はcr_。
var shape_:Shape = new Shape();
var graphics_:Graphics = shape_.graphics;
const peak_:Number = Math.sqrt(1/3);
const depth_:int = 10;
//階調数は8bitだが階調を正確に2分割してはいない。
ellipse_(1, 0);
fill_(1, 0, peak_, 0x7F, 1, depth_);
//開始から終了に向かって単調増加する。
fill_(peak_, 0x7F, 0, 0, -1, depth_);
//開始から終了に向かって単調減少する。
ellipse_(0, 0);
return shape_;
//入れ子の関数定義。
function fill_ (
beginR_:Number, beginC_:int,
endR_:Number, endC_:int,
sign_:int, nest_:int
):void {
//単調な関数を呼び出して中割りを繰り返して階調を確保する。
var centerR_:Number = (beginR_ + endR_) * 0.5;
var centerC_:uint = color_(centerR_);
if (nest_ > 0 && (centerC_ - beginC_) * sign_ > 1) {
fill_(beginR_, beginC_, centerR_, centerC_, sign_, nest_ - 1);
}
ellipse_(centerR_, centerC_);
if (nest_ > 0 && (endC_ - centerC_) * sign_ > 1) {
fill_(centerR_, centerC_, endR_, endC_, sign_, nest_ - 1);
}
}
function ellipse_ (ratio_:Number, color_:int):void {
//横方向を縮小した楕円を描く。
var radius_:Number = cr_ * ratio_;
graphics_.beginFill(0x010101 * (color_ + 0x80));
graphics_.drawEllipse(cr_ - radius_, 0, radius_ * 2, cr_ * 2);
graphics_.endFill();
}
function color_ (x_:Number):int {
//x=0~1に対して値0x00~0x7Fを返す。
var z_:Number = x_ - x_ * x_ * x_;
//描きたい奥行きの形を定義する。
//zが極値sqrt(3)/4.5を取るのはx=sqrt(1/3)のとき。
if (z_ < 0) z_ = 0;
const k_:Number = 0x7F * 4.5 / Math.sqrt(3);
var result_:uint = Math.floor(k_ * z_);
if (result_ > 0x7F) result_ = 0x7F;
return result_;
}
}
}
}