リアルな水滴を求めて
マウスクリックでタイルに水滴が付着します
* ----------------------------------------------
* ToDo: 大きな水滴はズリ落ちる
* 重なった水滴は合体する
* ----------------------------------------------
* 問題: DropShadowFilterは重複できない?
/*
* マウスクリックでタイルに水滴が付着します
* ----------------------------------------------
* ToDo: 大きな水滴はズリ落ちる
* 重なった水滴は合体する
* ----------------------------------------------
* 問題: DropShadowFilterは重複できない?
*/
package {
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.GradientType;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.geom.Vector3D;
import flash.geom.Rectangle;
//import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.filters.BlurFilter;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
import flash.filters.DropShadowFilter;
import flash.filters.BevelFilter;
public class Take06 extends Sprite {
private const SW:Number = stage.stageWidth;
private const SH:Number = stage.stageHeight;
private var drops:Vector.<Vector3D> = new Vector.<Vector3D>();
private var backGround:Sprite = new Sprite();
private var dropStage1:Sprite = new Sprite();
private var dropStage2:Sprite = new Sprite();
private var xStage :Sprite = new Sprite();
private var yStage :Sprite = new Sprite();
private var map:BitmapData;
public function Take06():void {
var stripe:BitmapData = new BitmapData(80,80,false,0xcccccc);
stripe.fillRect(new Rectangle(2,2,76,76),0x9999cc);
stripe.fillRect(new Rectangle(6,6,76,76),0x333366);
stripe.fillRect(new Rectangle(4,4,76,76),0x666699);
backGround.graphics.beginBitmapFill(stripe);
backGround.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
backGround.graphics.endFill();
addChild(backGround);
addChild(dropStage1);
addChild(dropStage2);
map = new BitmapData(SW,SH,false,0x7f7f7f);
// フィルターを駆使して水滴を表現する
var fGlow1:GlowFilter = new GlowFilter();
fGlow1.blurX = fGlow1.blurY = 16;
fGlow1.color = 0x000066;
fGlow1.strength = 10;
fGlow1.inner = true;
var fDropWhite:DropShadowFilter = new DropShadowFilter();
fDropWhite.blurX = 4;
fDropWhite.blurY = 4;
fDropWhite.distance = 4;
fDropWhite.angle = 70; // 0で左(右回り)
fDropWhite.color = 0x9999cc;
fDropWhite.strength = 2;
fDropWhite.alpha = 0.8;
fDropWhite.inner = true;
fDropWhite.knockout = true;
var fDropBlue:DropShadowFilter = new DropShadowFilter();
fDropBlue.blurX = fDropBlue.blurY = 16;
fDropBlue.distance = 8;
fDropBlue.angle = 270; // 0で左(右回り)
fDropBlue.color = 0x333366;
fDropBlue.alpha = 0.7;
fDropBlue.inner = true;
fDropBlue.knockout = true;
var fBevel:BevelFilter = new BevelFilter();
fBevel.highlightColor = 0xffffff;
fBevel.shadowColor = 0x000000;
fBevel.angle = 270;
fBevel.blurX = 16;
fBevel.blurY = 16;
fBevel.strength = 4;
// DropShadowFilterは重複できない?
// だったらステージを複数用意しちゃえ!
dropStage1.filters = [fGlow1,fDropWhite];
dropStage2.filters = [fGlow1,fDropBlue,fBevel];
// 初期水滴を配置
drops.push(new Vector3D(250,100,0,20));
drops.push(new Vector3D(200,300,0,10));
drops.push(new Vector3D(400,150,0,10));
render();
//addEventListener(Event.ENTER_FRAME, render);
stage.addEventListener(MouseEvent.CLICK,addDrop);
}
private function addDrop(e:MouseEvent):void {
drops.push(new Vector3D(mouseX,mouseY,0,Math.random()*10+10));
render();
}
// ENTER_FRAMEで毎画面描画することを想定しています
private function render():void {
// dropStage1, 2 をクリア
while (dropStage1.numChildren) dropStage1.removeChildAt(0);
while (dropStage2.numChildren) dropStage2.removeChildAt(0);
drops.forEach(drawDrop);
// ビットマップデータに変換
map.fillRect(map.rect,0x7f7f7f);
map.draw(xStage);
var yMap:BitmapData = new BitmapData(SW, SH, false, 0x7F7F7F);
yMap.draw(yStage);
map.copyChannel(yMap, yMap.rect, new Point(0, 0), BitmapDataChannel.BLUE, BitmapDataChannel.BLUE);
yMap.dispose();
map.applyFilter(map,map.rect,new Point(0,0),new BlurFilter(20,20));
// 背景に畳み込みフィルタを適用
var xyFilter:DisplacementMapFilter = new DisplacementMapFilter();
xyFilter.mapBitmap = map;
xyFilter.mapPoint = new Point(0,0);
xyFilter.componentX = BitmapDataChannel.RED;
xyFilter.componentY = BitmapDataChannel.BLUE;
xyFilter.scaleX = 128;
xyFilter.scaleY = 128;
xyFilter.mode = DisplacementMapFilterMode.IGNORE;
backGround.filters = [xyFilter];
// xStage,yStageをクリアする
while (xStage.numChildren) xStage.removeChildAt(0);
while (yStage.numChildren) yStage.removeChildAt(0);
}
private function drawDrop(drop:Vector3D, index:int, vector:Vector.<Vector3D>):void {
// 落下(このバージョンでは動作しない)
//vector[index].y += drop.w/400;
// グラデーション設定
var type:String = GradientType.LINEAR;
var redColors :Array = [0xFF0000, 0x000000];
var blueColors:Array = [0x0000FF, 0x000000];
var alphas :Array = [1, 1];
var ratios :Array = [0, 255];
var xMatrix:Matrix = new Matrix();
var yMatrix:Matrix = new Matrix();
xMatrix.createGradientBox(drop.w*2, drop.w*2, 0, drop.x-drop.w, drop.y-drop.w);
yMatrix.createGradientBox(drop.w*2, drop.w*2, Math.PI/2, drop.x-drop.w, drop.y-drop.w);
// xStage
var xCircle:Shape = new Shape();
xCircle.graphics.beginGradientFill(type, redColors, alphas, ratios, xMatrix);
xCircle.graphics.drawCircle(drop.x,drop.y,drop.w-10); // Glowフィルタとのズレを修正
xCircle.graphics.endFill();
xStage.addChild(xCircle);
// yStage
var yCircle:Shape = new Shape();
yCircle.graphics.beginGradientFill(type, blueColors, alphas, ratios, yMatrix);
yCircle.graphics.drawCircle(drop.x,drop.y,drop.w-10); // Glowフィルタとのズレを修正
yCircle.graphics.endFill();
yStage.addChild(yCircle);
// dropStage1
var circle1:Shape = new Shape();
circle1.graphics.beginFill(0x0000ff);
circle1.graphics.drawCircle(drop.x,drop.y,drop.w);
circle1.graphics.endFill();
dropStage1.addChild(circle1);
// dropStage2
var circle2:Shape = new Shape();
circle2.graphics.beginFill(0x0000ff);
circle2.graphics.drawCircle(drop.x,drop.y,drop.w);
circle2.graphics.endFill();
dropStage2.addChild(circle2);
}
}
}