風呂場forked from: 水滴のようなフィルタ効果
窓を流れる雨と合体したら風呂っぽくなった。
* とりあえずだったんでフィルタ効果は使用してません。
* クリックで初期化
マウス位置に水滴を表示する
/*
* 窓を流れる雨と合体したら風呂っぽくなった。
* とりあえずだったんでフィルタ効果は使用してません。
* クリックで初期化
*/
// forked from Kay's 水滴のようなフィルタ効果
/*
* マウス位置に水滴を表示する
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
[SWF(width=465, height=465, backgroundColor=0x666666, frameRate=20)]
public class Main extends Sprite
{
private var particles:Vector.<Particle> = new Vector.<Particle>();//雨粒
private const NUM:int = 200;//表示する雨粒の数
public function Main():void
{
init();
}
private function init():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);
var backGround:Sprite = new Sprite();
backGround.graphics.beginBitmapFill(stripe);
backGround.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
backGround.graphics.endFill();
addChild(backGround);
//雨粒作成
this.create();
this.addEventListener(Event.ENTER_FRAME , onEnterFrame);
this.stage.addEventListener(MouseEvent.CLICK , removeAll);
}
private function onEnterFrame(e:Event):void
{
var w:uint = this.stage.stageWidth;
var h:uint = this.stage.stageHeight;
var num:uint = this.particles.length;
var i:int;
var j:int;
for (i = 0; i < num; i++)
{
var p:Particle = this.particles[i];
//有効な雨粒だったら
if (!p.isDeleteFlg)
{
p.w = w;
p.h = h;
p.addAccelY(0.1);//下へ向かう
//動いた時
if (p.move())
{
//他の雨粒と接触していないかチェック
for (j = 0; j < num; j++)
{
var pHitTest:Particle = this.particles[j];
//有効な雨粒だったら
if (!pHitTest.isDeleteFlg && i!=j)
{
//接触したら
if (p.hitTestObject(pHitTest))
{
//マージする
ParticleManager.margeParticles(p , pHitTest);
//接触したほうは削除予定フラグ立てる
pHitTest.isDeleteFlg = true;
}
}
}
}
}
}
//有効な雨粒じゃなかったら削除する
for (i = num-1; i >= 0; i--)
{
p = this.particles[i];
if (p.isDeleteFlg)
{
this.removeChild(p);
this.particles.splice(i,1);
}
}
//新しい雨粒を作成
this.create();
}
private function create(e:Event = null):void
{
var num:uint = this.NUM - this.particles.length;
var w:uint = this.stage.stageWidth;
var h:uint = this.stage.stageHeight;
var i:int;
for (i = 0; i < num; i++)
{
var p:Particle = new Particle();
p.r = (Math.random() * 5) + 2;
p.x = Math.random() * w;
p.y = Math.random() * h;
this.addChild(p);
this.particles.push(p);
}
}
private function removeAll(e:Event = null):void
{
var num:uint = this.particles.length;
var i:int;
for (i = 0; i < num; i++)
{
this.particles[i].isDeleteFlg = true;
}
}
}
}
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
import flash.display.Shape;
import flash.display.GradientType;
import flash.filters.GradientBevelFilter;
import flash.display.BitmapData;
class Particle extends Sprite
{
public var isDeleteFlg:Boolean = false;
public var w:Number = 1;
public var h:Number = 1.2;
public var vX:Number = 0;
public var vY:Number = 0;
private var _r:Number;//半径
private var _area:Number;//面積
private const PAI:Number = Math.PI;//π
/**
* 半径
*/
public function get r():Number
{
return this._r;
}
/**
* 半径
*/
public function set r(r:Number):void
{
this._r = r;
this._area = this.PAI * r * r;
this.scaleX = this.scaleY = r;
}
/**
* 面積
*/
public function get area():Number
{
return this._area;
}
/**
* 面積
*/
public function set area(area:Number):void
{
this._area = area;
this._r = Math.sqrt(area / this.PAI);
this.scaleX = this.scaleY = this._r;
}
//■初期化■■■
public function Particle(x:int=0 , y:int=0 , r:int=1)
{
this.x = x;
this.y = y;
this.r = r;
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
var g:Graphics = this.graphics;
// フィルターマップを作成
var matrix:Matrix = new Matrix();
var type:String=GradientType.RADIAL;
var redColors:Array=[0xff0000,0x990000,0x7f7f7f];
var alphas :Array=[1,1,0];
var ratios :Array=[0x11,0x99,0xff];
matrix.createGradientBox(this.w, this.h, Math.PI/2);
g.beginGradientFill(type, redColors, alphas, ratios, matrix, "pad","rgp",0.75);
g.drawEllipse(0,0,this.w,this.h);
g.endFill();
var map:BitmapData=new BitmapData(this.width,this.height,false,0x7F7F7F);
map.draw(this);
// グラデーションベベルフィルタ
var gvFilter:GradientBevelFilter = new GradientBevelFilter();
gvFilter.distance = 1;
gvFilter.angle = 0xcc;
gvFilter.colors = [0xffffff, 0x0000ff];
gvFilter.alphas = [1, 0.9];
gvFilter.ratios = [0x66, 0xdd];
this.filters = [gvFilter];
this.alpha = 0.5;
//g.x = -100;
this.scaleX = this.scaleY = this.r;
}
//■public■■■
public function move():Boolean
{
var ret:Boolean = false;
//ある程度の大きさになっているかどうか
//大きければ下に移動する
if (this.r > 6)
{
ret = true;
this.x += this.vX;
this.y += this.vY;
if (this.x > this.w + this.r) this.isDeleteFlg = true;
if (this.x < -this.r) this.isDeleteFlg = true;
if (this.y > this.h + this.r) this.isDeleteFlg = true;
if (this.y < -this.r) this.isDeleteFlg = true;
//縦長にする
this.r = this._r;
this.scaleX += this.vX / 1;
this.scaleY += this.vY / 1;
}
//大きくなければ移動しない
else
{
this.vX = this.vY = 0;
}
//動いたかどうかを返す
//動いたらtrue
return ret;
}
public function addAccelX(accel:Number):void
{
this.vX += accel;
}
public function addAccelY(accel:Number):void
{
this.vY += accel;
}
}
class ParticleManager
{
public function ParticleManager()
{
}
/**
* p1とp2をp1にマージ
* @param p1
* @param p2
*/
public static function margeParticles(p1:Particle , p2:Particle):void
{
p1.vX = (p1.vX + p2.vX) ;
p1.vY = (p1.vY + p2.vY) ;
p1.area = p1.area + p2.area ;
var areaRatio:Number;
var moveX:Number;
var moveY:Number;
if (p1.area >= p2.area)
{
areaRatio = p2.area / p1.area;
moveX = (p2.x - p1.x) * areaRatio;
moveY = (p2.y - p1.y) * areaRatio;
}
else
{
areaRatio = p1.area / p2.area;
moveX = (p1.x - p2.x) * areaRatio;
moveY = (p1.y - p2.y) * areaRatio;
}
p1.x += moveX;
p1.y += moveY;
p1.addAccelX(moveX / 10);
}
}