In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

HANABI(yanbakaさん作)を勉強中。ランダムに色をつけてみた。

BitmapDataで3Dを表現してみる ver.挫折しました。
* 
* HANABI(http://wonderfl.net/c/2PFV) yanbakaさん作
* に感動したので、別アプローチで作成中ですが、
* 動作部分はそのまま拝借したったし、負荷高いし、もう色々と挫折気味;
* 先人の知恵は偉大ですね!
* 素直にForkしておけばよかったと後悔しっぱなしです。
* 本当に勉強になります!
* 
* perlineNoiseで花火の色をランダムで出すようにしました。
* 
* 自分のに限界を感じたので、オリジナルをForkしてみました。
* http://wonderfl.net/c/R006
*
* 配列の出し入れがオブジェクトの場合Arrayの方が早いとのことでしたので、
* VectorからArrayに変更しました。
* どうなんでしょうか?
/**
 * Copyright code ( http://wonderfl.net/user/code )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wou3
 */

/*
 * BitmapDataで3Dを表現してみる ver.挫折しました。
 * 
 * HANABI(http://wonderfl.net/c/2PFV) yanbakaさん作
 * に感動したので、別アプローチで作成中ですが、
 * 動作部分はそのまま拝借したったし、負荷高いし、もう色々と挫折気味;
 * 先人の知恵は偉大ですね!
 * 素直にForkしておけばよかったと後悔しっぱなしです。
 * 本当に勉強になります!
 * 
 * perlineNoiseで花火の色をランダムで出すようにしました。
 * 
 * 自分のに限界を感じたので、オリジナルをForkしてみました。
 * http://wonderfl.net/c/R006
 *
 * 配列の出し入れがオブジェクトの場合Arrayの方が早いとのことでしたので、
 * VectorからArrayに変更しました。
 * どうなんでしょうか?
 */
package 
{
 	import flash.display.*;
	import flash.events.*;
	import flash.filters.BlurFilter;
	import flash.geom.*;
	import flash.text.TextField;
	import flash.utils.Timer;
	
	[SWF(width = "500", height = "500", backgroundColor = "0x000000", frameRate = "30")]
	public class main_HANABI extends Sprite 
	{
		//変数
		private var fromPoint:Vector3D;	//出発地点
		private var canvas:BitmapData;	//ビットマップを描写するカンバス
		private var glow:BitmapData;	//キラキラ発生用ビットマップデータ
		private var beemBMD:BitmapData;	//花火のビットマップデータ
		private var alphaBMD:BitmapData;	//深度調整用のビットマップデータ
		private var dammy:Sprite;		//ダミーの3D空間
		private const PI2:Number = Math.PI * 2;	//phi
		private var Beems:Array;	//ビームのインスタンスを格納する配列
		private var BeemPool:Array;	//ビームのインスタンスをプールしておくための配列
		private var debugTxt:TextField;	//デバッグ用のテキスト
		
		private const size:Number=1.5; //ビームの大きさ
		
		private const ADD_NUM:uint = 200; //1フレームで追加するビームの数
		private const RADIUS:uint = 70; //球体の半径
		private var myTimer:Timer;
		private var startPosX:Number;
		private var startPosY:Number;
		private var colorTransform:ColorTransform;
		private var time:Number = 500;	//花火を発生させる頻度
		
		
		//コンストラクタ
		public function main_HANABI()
		{
			
			//初期化
			setInit();
			
			//空間情報を格納するスプライト登録
			setCanvas();
			
			//ビームbitmapData作成
			createBEEMBMD();
			
			//ループ処理
			addEventListener(Event.ENTER_FRAME, loopHandler);
			
			//花火作成
			myTimer = new Timer(time);
			myTimer.addEventListener(TimerEvent.TIMER, createHANABI);
			myTimer.start();

			
		}
		

		
		//色々初期化
		private function setInit():void
		{
			//ステージの情報
			stage.quality = StageQuality.MEDIUM;
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			//出発地点
			fromPoint = new Vector3D(0, 0, 0);
			
			//消失点設定
			this.transform.perspectiveProjection.projectionCenter = new Point(stage.stageWidth / 2, stage.stageHeight / 2);
			
			//ダミー用スプライト
			dammy = new Sprite();
			addChild(dammy);
			dammy.x = 0;
			dammy.y = 0;
			dammy.z = 3000; //2次元へ変換する際の基本深度
			
			//BeemManagerインスタンスをプールさせておく配列の初期化
			BeemPool =[];
			
			//実際に動いているBeemManagerインスタンスを格納しておく配列の初期化
			Beems = [];
			
			//モーションブラー 軌跡をオレンジ色ぽく
			colorTransform= new ColorTransform (0.9, 0.9, 0.9);
			
		}
		
		//bitmapデータを描くカンバス作成
		private function setCanvas():void
		{
			canvas = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000);
			addChild(new Bitmap(canvas));
		}
		
		//ビームのBitmapData作成
		private function createBEEMBMD():void
		{
			//ビットマップデータ作成 perlineNoiseで色を作成
			beemBMD = new BitmapData(100,100, true, 0);
			beemBMD.perlinNoise(100, 100, 7, 1, true, true);

			//キラキラマップ
			glow = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000);
			var bmp:Bitmap = new Bitmap(glow, PixelSnapping.NEVER, true);
			addChild(bmp);
			bmp.blendMode = BlendMode.ADD;
			bmp.scaleX = bmp.scaleY = 10;
			
			//BitmapDataで、深度α値適用させるためのBitmapDataを作成
			var beem:Shape = new Shape();
			var beemG:Graphics = beem.graphics;
			var gType:String = GradientType.LINEAR;
			var gColor:Array = [0x000000, 0x000000];
			var gAlpha:Array = [0.1, 1];
			var gRatio:Array = [0, 100];
			//グラデーションをかける
			beemG.beginGradientFill(gType, gColor, gAlpha, gRatio);
			beemG.drawRect(0,0,100,size*2);
			beemG.endFill();
			alphaBMD = new BitmapData(100,size*2, true,0xffffff);
			alphaBMD.draw(beem);
		
		}
			
		private function loopHandler(e:Event):void 
		{
			
			//描画ロック
			canvas.lock();
			
			//軌跡をオレンジ色へ	
            canvas.colorTransform(canvas.rect, colorTransform);
			
			//ループ処理
			for (var i:uint = 0; i < Beems.length; i++) 
			{
				var beem:BeemManager = Beems[i];
				
				//抵抗値計算
				setFriction(beem);
				
				//3D座標を2Dへコンバート
				convert2D(beem);
				
				//画面外にでたら、または、移動量が少量になったらオブジェクトをプールさせる。
				if ((beem.toPoint2D.x > stage.stageWidth || beem.toPoint2D.x < 0) || (beem.toPoint2D.y < 0 || beem.toPoint2D.y > stage.stageHeight) || Math.abs(beem.toPoint3D.x) < 0.01 || Math.abs(beem.toPoint3D.y) < 0.01 || Math.abs(beem.toPoint3D.z) < 0.01)
				{
					poolObject(i);
					continue;
				}
				
				//カンバスにコピー
				canvas.copyPixels(beemBMD, beem.rect, beem.toPoint2D, alphaBMD, new Point(beem.depth, 0), true);
				
			}
			
			//これが無いと始らない すてきなキラキラ
			glow.draw(canvas,new Matrix(0.1,0,0,0.1));
			
			//描画ロック解除
			canvas.unlock();


		}
		
		private function getAbs(n:Number):Number
		{
			return (n ^ n>>31) - (n>>31);
		}
		
		private function createHANABI(e:TimerEvent):void 
		{
			//新しくビームを作成
			createBEEM();
		}
		
		//ビームインスタンスをプールする
		private function poolObject(i:uint):void
		{
				BeemPool.push(Beems[i]);
				Beems.splice(i, 1);
		}
		
		//新しくビームを作成
		private function createBEEM():void 
		{
			//発射地点 もうね、ほんと行き当たりばったりな設定
			startPosX = (stage.stageWidth+2000) *( Math.random()-0.5);
			startPosY = -stage.stageHeight*2.5 * Math.random();
			//球体の半径
			var radius:uint = RADIUS * (Math.random() + 0.8);
			//奥行き
			var depth:Number = 1000 * Math.random();
			//色決定 perlineNoiseビットマップデータの場所指定
			var u:uint = Math.random() * 100 | 0;
			var v:uint = Math.random() * 100 | 0;
			
			//新しく追加するビームの初期化
			for (var i:uint = 0; i < ADD_NUM; i++)
			{
				//新しくビームを作成
				var newBeem:BeemManager;
				if ( BeemPool.length != 0){
				//プールしているBeemManagerインスタンスがあったら。そこから持ってくる。
					newBeem = BeemPool.pop();
				}else{
				//プールしているBeemManagerインスタンスが無かったら新しく作成。
					newBeem = new BeemManager();
				}
				
				//座標を決める要素の初期化
				var angleAlpha:Number = Math.random()*PI2;
				var angleBeta:Number = Math.random()*PI2;
				
				//初期位置設定
				newBeem.myPoint3D.x = startPosX;
				newBeem.myPoint3D.y = startPosY;
				newBeem.myPoint3D.z = depth;
				
				//後で抵抗値で変化させるけど、最初のターゲットポイントを決める。
				var posX:Number = radius * Math.cos(angleBeta) * Math.sin(angleAlpha);
				var posY:Number = radius* Math.sin(angleBeta);
				var posZ:Number = radius * Math.cos(angleBeta) * Math.cos(angleAlpha);	
				
				//3D座標へ格納
				newBeem.toPoint3D = new Vector3D(posX, posY, posZ);
				
				//作ったビームインスタンスを格納
				Beems.push(newBeem);
				
				//色決定
				newBeem.rect=new Rectangle(u, v, size, size);
			}	
			
		}
		
		//抵抗値計算
		private function setFriction(beem:BeemManager):void 
		{
			//加速度
			beem.toPoint3D.y++;
			//抵抗値
			beem.toPoint3D.scaleBy(0.9);
			//現在位置更新
			beem.myPoint3D.incrementBy(beem.toPoint3D);
		}
		
			
		//3D座標を2D座標へコンバート
		private function convert2D(beem:BeemManager):void
		{	
			
			//2D座標へコンバート はっきり言って、ほぼ無意味です 負荷高めるだけかも
			beem.toPoint2D = dammy.local3DToGlobal(beem.myPoint3D);
			
			//深度計算 100分割
			var myDepth:Number = (beem.toPoint3D.z + RADIUS) / RADIUS*0.5;
			beem.depth = myDepth*100 | 0;
			
		}



		
	}
}

import flash.geom.*;
class BeemManager
{
	public var toPoint3D:Vector3D;
	public var myPoint3D:Vector3D;
	public var toPoint2D:Point;
	public var depth:uint;
	public var rect:Rectangle;
	
	//コンストラクタ
	public function BeemManager()
	{
		toPoint3D = new Vector3D();
		myPoint3D = new Vector3D();
		toPoint2D = new Point();
		rect = new Rectangle();
	}
	
}