forked from: forked from: HANABIをカラフルにしてみた

by masarizm forked from forked from: HANABI(初級者がコードに注釈をつけてみた) (diff: 311)
↓ Start writing by masarizm
基本はおなじですが、構造を変えてみました。
オブジェクト指向っぽく、花火それぞれが消えるタイミングを持つ様にしました。
柳っぽい感じから丸い花火になりました。
消え方は良い感じなのではと思います。
Forkとよんでよいのか、失礼でしたらすぐに消します
↑ Ent writing by masarizm
♥0 | Line 129 | Modified 2009-09-10 18:16:07 | MIT License
play

ActionScript3 source code

/**
 * Copyright masarizm ( http://wonderfl.net/user/masarizm )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/xJFi
 */

// forked from Hiiragi's forked from: HANABI(初級者がコードに注釈をつけてみた)
package {
    /*
        ↓ Start writing by masarizm
        基本はおなじですが、構造を変えてみました。
        オブジェクト指向っぽく、花火それぞれが消えるタイミングを持つ様にしました。
        柳っぽい感じから丸い花火になりました。
        消え方は良い感じなのではと思います。
        Forkとよんでよいのか、失礼でしたらすぐに消します
        ↑ Ent writing by masarizm
        
    */
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.PixelSnapping;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.filters.BlurFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Timer;

	[SWF(width = "465", height = "465", backgroundColor = "0x000000", frameRate = "20")]
	public class Hanabitaikai extends Sprite {

		// ステージの高さと幅
		private const WIDTH:Number = 465;
		private const HEIGHT:Number = 465;
		
		// 打ち上げる間隔[ms]
		private var interval:int =250; 
		
		// 打ち上げる花火を入れておく配列
		private var fireWorks:Array = [];
		
		// 表示エリア
		private var canvas:BitmapData;
		// フィルター適用用のBitmap
		private var glow:BitmapData;
		// 矩形情報
		private var rect:Rectangle;
		
		// timerオブジェクト
		private var timer:Timer;
		
		private var clrTrsFom:ColorTransform = new ColorTransform(.7, .7, .7, 1.0);
		
		public function Hanabitaikai() {
			initialize();
		}
		
		public function initialize():void {
			
			canvas = new BitmapData(WIDTH, HEIGHT, false ,0x0);
			addChild(new Bitmap(canvas)) as Bitmap;
			
			//glowFilter
			glow = new BitmapData(WIDTH/4, HEIGHT/4, false, 0x0);
			var bm:Bitmap = addChild(new Bitmap(glow, PixelSnapping.NEVER, true)) as Bitmap;

			// bitmapDataを4分の1で作成して、addChildした戻り値のスケールを4倍してる。
			bm.scaleX = bm.scaleY = 4;
			bm.blendMode = BlendMode.ADD;
			// ステージサイズと同じ矩形
			rect = new Rectangle(0, 0, WIDTH, HEIGHT);
			
			
			//--- イベント ---
			//framerateに依存し描画を繰り返すイベント
			this.stage.addEventListener(Event.ENTER_FRAME, startFireWorks);
			
			//花火の打ち上げを行う
			timer = new Timer(interval);
			timer.addEventListener(TimerEvent.TIMER, uchiage);
			timer.start();
		}
		
		public function uchiage(e:TimerEvent):void {
			fireWorks.push(new Hanabi(WIDTH, HEIGHT));
		}
		
		public function startFireWorks(e:Event):void {
			update();
		}
		
		private function update():void {
			canvas.lock();
			
			//canvas.applyFilter(canvas, rect, new Point(), new BlurFilter(1, 1));
			
			canvas.colorTransform(rect, clrTrsFom);
			
			for (var i:int=0;i<fireWorks.length;i++) {
				var hanabi:Hanabi = fireWorks[i] as Hanabi;
				if (hanabi) {
					for (var j:int=0;j<hanabi.particls.length;j++) {
						var p:Particle = hanabi.particls[j];
						// 落下速度をプラス
						p.vy += 0.2;
						// 速度に摩擦をかける
						p.vx *= 0.98;
						p.vy *= 0.98;
						// 実際の移動
						p.x += p.vx;
						p.y += p.vy;
						
						canvas.setPixel32(p.x, p.y, p.c);
					}
					// 花火の寿命が来たら消す
					if (!hanabi.isLive()) {
						this.fireWorks.splice(i,1);
					}
					// 花火の寿命を縮める
					hanabi.shortenLifeSpan();
				}
			}
			
			canvas.unlock();
			glow.draw(canvas, new Matrix(0.25, 0, 0, 0.25));
		}
	}
}
	
	class Hanabi
	{
		// 火花達
		public var particls:Array = [];
		// 火花の数
		private var size:int = 200;
		
		// 寿命
		private var lifeSpan:int;
		
		// 色情報
		private var red:uint;
		private var green:uint;
		private var blue:uint;
		private var color:uint = 0x000000FF;
		private const MIN_COLOR:uint = 100;
		private const MAX_COLOR:uint = 255-MIN_COLOR;

		
		// 描画するcanvasのサイズをコンストラクタにて取得してるけど微妙。不細工
		// いっそcanvasごとうけとってしまおうか、なんかいい方法があれば変更したい
		private var width:Number;
		private var height:Number;
		
		// 花火の中心位置
		private var sx:Number;
		private var sy:Number;
		
		public function Hanabi(width:Number, height:Number)
		{
			// 初期化処理
			this.width = width;
			this.height = height;
			
			//  寿命決定(あんまり早く死なない様にゲタ履かせる)
			this.lifeSpan = Math.random() * 10 + 3;
			
			// 花火炸裂位置決定
			sx = Math.random() * this.width;
			sy = Math.random() * this.height/3;
			
			// 花火の色を決める
			// まず各色の重みを計算
			red = Math.random() * 255;
			green = Math.random() * 255;
			blue = 255;

			// 実際の値計算
			
			color = color + (red << 24) + (green <<16) + (blue << 8);
	
			// 火花を散らせ!
			while(size--)createParticle();			
		}
		
		// 花火の生死確認
		public function isLive():Boolean {
			return this.lifeSpan > 0;
		}
		// 寿命を縮める
		public function shortenLifeSpan():void {
			this.lifeSpan--;
		}
		
		private function createParticle():void {
			var p:Particle = new  Particle();
			p.x = sx;
			p.y = sy;
			
			//半径と角度をランダムに決めて、x,y軸の速度に変換する
			var radius:Number = Math.sqrt(Math.random()) * 10;
			var angle:Number = Math.random() * (Math.PI) * 2;
			p.vx = Math.cos(angle) * radius;
			p.vy = Math.sin(angle) * radius;
			
			// 色の決定
			p.c = color;
			//配列に追加
			particls.push(p);
		}

	}
	
	class Particle
	{
		public var x:Number;
		public var y:Number;
		public var vx:Number;
		public var vy:Number;
		public var c:uint = 0xFFFFFFFF;
		
		public function Particle() {
		}
		
	}