Beautifl - Flash Gallery

Thumbnail : [etude] Native3D
[etude] Native3D
sekiryou 2010-01-02 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

package {
	import flash.display.*;
	import flash.geom.*;
	import flash.text.*;
	import flash.events.Event;
	import flash.utils.ByteArray;
	import flash.filters.BlurFilter;
	
	[SWF(width = "465", height = "465", backgroundColor = "0x000000", frameRate = "30")]
	
	public class etudeNative3D extends Sprite {
        private const STAGE_WIDTH:uint = 465;
        private const STAGE_HEIGHT:uint = 465;
        private const STAGE_CENTER_X:Number = STAGE_WIDTH * 0.5;
        private const STAGE_CENTER_Y:Number = STAGE_HEIGHT * 0.5;
		private var _canvas:BitmapData;
		private var _glow:BitmapData;
		private var _rect:Rectangle;
		private var _cTra:ColorTransform;
		private var mapList:Array = [];
		private var totalParticle:uint = 3600;
		private var particles:Array = [];
		private var mtx3D:Matrix3D = new Matrix3D();
		private var projection:PerspectiveProjection;
		private var projectionMatrix3D:Matrix3D;
		public function etudeNative3D() {
			init();
		}
		private function init():void {
			addChild( new Bitmap( _canvas = new BitmapData ( STAGE_WIDTH, STAGE_HEIGHT, true, 0x00FFFFFF ) ) );
			
			_glow = new BitmapData( STAGE_WIDTH/4, STAGE_HEIGHT/4, false, 0x0 );
			var bm:Bitmap = addChild( new Bitmap( _glow, PixelSnapping.NEVER, true ) ) as Bitmap;
			bm.scaleX = bm.scaleY = 4;
			bm.blendMode = BlendMode.ADD;
			
			_rect = new Rectangle( 0, 0, STAGE_WIDTH, STAGE_HEIGHT );
			_cTra = new ColorTransform( 0.95, 0.95, 0.95, 1.0 );
			
			projection = new PerspectiveProjection();
			projection.fieldOfView = 90;
			projectionMatrix3D = projection.toMatrix3D();
			
			mapList = textToBit();
			for ( var i:uint = 0; i < totalParticle; i++ ) {
				var particle:Particle = new Particle();
				particles.push( particle );
				var tmpPoint:Point = purposeMaker()
				particle.dx = tmpPoint.x;
				particle.dy = tmpPoint.y;
			}
			addEventListener( Event.ENTER_FRAME, onEnterFrameHandler );
		}
		private function textToBit():Array {
			var tmpList:Array = [];
			var accuracy:Number = 2;
			var threshold:uint = 0x00FFFFFF;
			for ( var i:uint = 0; i < 11; i++ ) {
				var txt:TextField = new TextField();
				txt.x = 0;
				txt.y = 0;
				txt.width = 90;
				txt.height = 90;
				txt.type = TextFieldType.DYNAMIC;
				txt.selectable = false;
				var tf:TextFormat = new TextFormat();
				
				tf.font = "Font Bold";
				tf.size = 80;
				tf.align = TextFormatAlign.CENTER;
				txt.textColor = 0xFFFFFF;
				txt.defaultTextFormat = tf;
				if ( i < 10 ) {
					txt.text = String( i );
				} else {
					txt.text = ":";
				}
				
				var tw:uint = txt.width / accuracy;
				var th:uint = txt.height / accuracy;
				var mapData:BitmapData = new BitmapData( tw, th, true, 0x00000000 );
				var matrix:Matrix = new Matrix();
				matrix.scale( 1 / accuracy, 1 / accuracy );
				mapData.draw(txt, matrix);

				var byteArray:ByteArray = mapData.getPixels( new Rectangle( 0, 0, mapData.width, mapData.height ) );
				byteArray.position = 0;
				tmpList[ i ] = [];
				for (var n:uint = 0; n < tw * th; n++) {
					var color:uint = byteArray.readInt();
					if ( color > threshold ) {
						var pos:uint = n;
						var px:Number = ( pos % tw ) * accuracy + txt.x;
						var py:Number = Math.floor(pos / tw) * accuracy + txt.y;
						tmpList[ i ].push( { dx:px, dy:py, dz:0 } );
					}
				}
			}
			return tmpList;
		}
		private function purposeMaker():Point {
			var destination:Point = new Point();
			var totalType:uint = 8;
			var rndtxt:int = int( Math.random() * totalType );
			
			var nDate:Date = new Date();
			var Hour:String = String(nDate.hours + 100);
			Hour = Hour.substring( 1, 3)
			var Minute:String = String(nDate.minutes + 100);
			Minute = Minute.substring( 1, 3)
			var Second:String = String(nDate.seconds + 100);
			Second = Second.substring(1, 3)
			var str:String = Hour + ":" + Minute + ":" + Second;
			
			str = str.substring( rndtxt, rndtxt + 1 );
			
			if( rndtxt == 2 || rndtxt == 5 ) {
				var dispTxt:uint = 10;
			} else {
				dispTxt = int( str );
			}
			var rndpoint:int = int( Math.random() * mapList[ dispTxt ].length );
			destination.x = mapList[ dispTxt ][ rndpoint ].dx + rndtxt * 50 - ( totalType * 50 * 0.5 );
			destination.y = mapList[ dispTxt ][ rndpoint ].dy - 45;
			return destination;
		}
		private function onEnterFrameHandler( eventObject:Event ):void {
			var vertices3D:Vector.<Number> = new Vector.<Number>();
			var projectedVerts:Vector.<Number> = new Vector.<Number>();
			var uvts:Vector.<Number> = new Vector.<Number>();
			var offsetZ:Number = 300;
			
			for ( var i:uint = 0; i < totalParticle; i++ ) {
				particles[ i ].update();
				vertices3D.push( particles[ i ].px, particles[ i ].py, particles[ i ].pz );
			}
			mtx3D.identity();
			mtx3D.appendRotation( -20, Vector3D.Y_AXIS);
			mtx3D.appendRotation( 20, Vector3D.X_AXIS);
			mtx3D.appendTranslation( 0, 0, offsetZ );
			mtx3D.append( projectionMatrix3D );
			bugfix( mtx3D );
			
			Utils3D.projectVectors( mtx3D, vertices3D, projectedVerts, uvts );
			
			var variation:Number = 0.04;
			var ctx:Number =  mouseX / 465;
			var cty:Number = mouseY / 465;
			if ( ctx > 0.95 ) {
				ctx = 0.95;
			} else if ( ctx < 0.05 ) {
				ctx = 0.05;
			}
			if ( cty > 0.95 ) {
				cty = 0.95;
			} else if ( cty < 0.05 ) {
				cty = 0.05;
			}
			if ( ctx > _cTra.redMultiplier ) {
				_cTra.redMultiplier += variation;
			} else {
				_cTra.redMultiplier -= variation;
			}
			if ( cty > _cTra.blueMultiplier ) {
				_cTra.blueMultiplier += variation;
			} else {
				_cTra.blueMultiplier -= variation;
			}
			
			_canvas.lock();
			_canvas.applyFilter( _canvas, _rect, new Point(), new BlurFilter( 1.6, 1.6 ) );
			_canvas.colorTransform( _rect, _cTra );
			var pvLength:uint = projectedVerts.length * 0.5;
			for ( var j:uint = 0; j < pvLength; j++ ) {
				if ( particles[ j ].arrivalFlag ) {
					particles[ j ].renew();
					var tmpPoint:Point = purposeMaker();
					particles[ j ].dx = tmpPoint.x;
					particles[ j ].dy = tmpPoint.y;
				}
				if( uvts[ j * 3 + 2 ] > 0 ) {
					_canvas.setPixel32( projectedVerts[ j * 2 ] + STAGE_CENTER_X, projectedVerts[ j * 2 + 1 ] + STAGE_CENTER_Y, 0xFF999999 );
				}
			}
			_canvas.unlock();
			_glow.fillRect( _glow.rect, 0x00000000 );
			_glow.draw( _canvas, new Matrix( 0.25, 0, 0, 0.25 ) );
		}
		private function bugfix( matrix:Matrix3D ):void {
			var m1:Matrix3D = new Matrix3D(Vector.<Number>( [ 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 1, 0 ] ) );
			var m2:Matrix3D = new Matrix3D(Vector.<Number>( [ 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 1,  0, 0, 0, 0 ] ) );
			m1.append( m2 );
			if ( m1.rawData[15] == 20 ) {
				var rawData:Vector.<Number> = matrix.rawData;
				rawData[15] /= 20;
				matrix.rawData = rawData;
			}
		}
	}
}
class Particle {
	public var px:Number;
	public var py:Number;
	public var pz:Number;
	public var dx:Number = 0;
	public var dy:Number = 0;
	public var dz:Number = 0;
	public var easingX:Number = Math.random() * 0.08 + 0.16;
	public var easingY:Number = Math.random() * 0.08 + 0.16;
	public var easingZ:Number = Math.random() * 0.08 + 0.16;
	
	private const range:Number = 0.1;
	public var distance:Number;
	public var arrivalFlag:Boolean = false;
	
	public function Particle() {
		renew();
	}
	public function update():void {
		px += ( dx - px ) * easingX;
		py += ( dy - py ) * easingY;
		pz += ( dz - pz ) * easingZ;
		
		distance = Math.sqrt( ( dx - px ) * (dx - px ) + ( dy - py ) * ( dy - py ) + ( dz - pz ) * ( dz - pz ) );
		
		if ( distance < range ) {
			arrivalFlag = true;
		}
	}
	public function renew():void {
		px = Math.random() * 800 - 400;
		py = dy;
		pz = Math.random() * 4000 - 2000;
		
		arrivalFlag = false;
	}
}