forked from: 窓を流れる雨
窓を流れる雨風。
クリックで初期化。
// forked from demouth's 窓を流れる雨
//窓を流れる雨風。
//クリックで初期化。
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
[SWF(width=465, height=465, backgroundColor=0xffffff, frameRate=20)]
public class Main extends Sprite
{
private var particles:Vector.<Particle> = new Vector.<Particle>();//雨粒
private const NUM:int = 200;//表示する雨粒の数
private var bd:BitmapData = new BitmapData(465, 465);
private var b:Bitmap;//残像用のBitmap
private var s:Sprite;//だんだん消えていくためのSprite
public function Main():void
{
init();
}
private function init():void
{
//残像用セットアップ
this.s = new Sprite();
this.s.graphics.beginFill(0x000000 , 0.3);
this.s.graphics.drawRect(0, 0, 465, 465);
this.s.graphics.endFill();
this.b = new Bitmap(this.bd);
this.addChild(this.b);
//雨粒作成
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.bd.draw(this.s);
this.bd.draw(this);
//新しい雨粒を作成
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;
class Particle extends Sprite
{
public var isDeleteFlg:Boolean = false;
public var w:uint = 1;
public var h:uint = 1;
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;
g.beginFill(0xBBDDFF);
g.drawCircle(0, 0, 1);
g.endFill();
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);
}
}