Beautifl - Flash Gallery

Thumbnail : Famous Triangle Trick
Famous Triangle Trick
k0rin 2011-05-28 MIT License

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

package {
	import flash.display.*;
	import flash.events.*;
	import flash.filters.*;
	import flash.geom.Matrix;
	import flash.text.*;
	
	// My first use of Tweener. Brilliant library!
    import caurina.transitions.Tweener;
	import caurina.transitions.properties.CurveModifiers;
	
	[SWF(width = "465", height = "465", frameRate = "60", backgroundColor="0x38502A")]
	public class TriangleTrick extends Sprite {
		private const W:Number = stage.stageWidth;
		private const H:Number = stage.stageHeight;
		
		private const ORIGIN_X:Number = W * 0.06;
		private const ORIGIN_Y:Number = H * 0.63;
		private const GRID_SPACING:int = 30;
		
		private var polygons:Vector.<Shape> = new Vector.<Shape>();
		private var polygonData:Array = [
			{ x:[0, 5], y:[0, 2], bezier:{ x:0, y:9, rotation:20 }, color:0xFF3300, vertices:[0, 0,  8, 0,  8, 3] }, 
			{ x:[8, 0], y:[3, 0], bezier:{ x:4, y:4, rotation:-5 }, color:0x0033FF, vertices:[0, 0,  5, 0,  5, 2] }, 
			{ x:[8, 5], y:[1, 0], bezier:{ x:5, y:1, rotation:10 }, color:0xFFFF33, vertices:[0, 0,  2, 0,  2, 1,  5, 1,  5, 2,  0, 2] }, 
			{ x:[8, 8], y:[0, 0], bezier:{ x:9, y:-2.5, rotation:20 }, color:0x00FF00, vertices:[0, 0,  5, 0,  5, 2,  2, 2,  2, 1,  0, 1] }, 
		];
		private var triangleState:int = 0;
		
		private const MESSAGES:Array = [
			// Want some nifty messages but I'm not good at English... Please help!
			"Click it!", 
			"What the hell happened!?", 
			"Check it carefully!", 
			"Don't you understand?", 
		];
		private var messageNo:int = 0;
		private var textField:TextField = new TextField();
		
		private var circle:Shape = new Shape();
		private var cursor:Shape = new Shape();
		
		private const CURSOR_Y:Number = H * 0.95;
		
		public function TriangleTrick():void {
			CurveModifiers.init();
			
			var grid:Shape = new Shape();
			var g:Graphics = grid.graphics;
			g.lineStyle(1, 0x000000, 0.2);
			for (var i:int = -30; i < 30; i++) {
				g.drawRect(ORIGIN_X + GRID_SPACING * i + 2, -400, 0, 1600);
				g.drawRect(-400, ORIGIN_Y + GRID_SPACING * i + 2, 1600, 0);
			}
			addChild(grid);
			
			textField.defaultTextFormat = new TextFormat("Helvetica", 20, 0x444444, true, false);
			textField.text = MESSAGES[messageNo];
			textField.autoSize = TextFieldAutoSize.CENTER;
			textField.selectable = false;
			textField.x = W * 0.42;
			textField.y = H * 0.73;
			textField.filters = [ new GlowFilter(0xFFFFFF, 1, 40, 30, 8) ];
			addChild(textField);
			
			// Couldn't use DisplayObject.transform to zoom because lines' thickness is treated as integer.
			function toPixelX(graphX:Number):Number { return ORIGIN_X + graphX * GRID_SPACING; }
			function toPixelY(graphY:Number):Number { return ORIGIN_Y - graphY * GRID_SPACING; }
			
			var triangle:Sprite = new Sprite();
			for (i = 0; i < polygonData.length; i++) {
				var pd:Object = polygonData[i];
				
				// scale polygon data
				for (var j:int = 0; j < pd.x.length; j++) {
					pd.x[j] = toPixelX(pd.x[j]);
					pd.y[j] = toPixelY(pd.y[j]);
				}
				pd.bezier.x = toPixelX(pd.bezier.x);
				pd.bezier.y = toPixelY(pd.bezier.y);
				for (j = 0; j < pd.vertices.length; j += 2) {
					pd.vertices[j    ] *=  GRID_SPACING;
					pd.vertices[j + 1] *= -GRID_SPACING;
				}
				
				// create a polygon
				var polygon:Shape = new Shape();
				g = polygon.graphics;
				g.lineStyle(4, 0xFFFFFF);
				var matrix:Matrix = new Matrix();
				matrix.createGradientBox(GRID_SPACING * 4, GRID_SPACING * 4, 70 * Math.PI / 180, 0, -95);
				g.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, pd.color], [0.5, 0.6], [0, 255], matrix);
				var commands:Vector.<int> = Vector.<int>([GraphicsPathCommand.MOVE_TO]);
				for (j = 0; j < pd.vertices.length / 2; j++) {
					commands.push(GraphicsPathCommand.LINE_TO);
				}
				g.drawPath(commands, Vector.<Number>(pd.vertices.concat(pd.vertices[0], pd.vertices[1])));
				g.endFill();

				polygon.x = pd.x[0];
				polygon.y = pd.y[0];
				triangle.addChild(polygon);
				polygons.push(polygon);
			}
			triangle.filters = [ new DropShadowFilter(4, 45, 0x000000, 0.5, 0, 0) ];
			addChild(triangle);
			
			g = circle.graphics;
			g.lineStyle(8, 0xFF0000, 0.8);
			g.drawCircle(toPixelX(7.5), toPixelY(0.5), 1.2 * GRID_SPACING);
			circle.alpha = 0;
			addChild(circle);
			
			g = cursor.graphics;
			g.beginFill(0xFFFFFF);
			g.drawPath(Vector.<int>([1, 2, 2, 2]), Vector.<Number>([0, 0,  -1, -1.7,  1, -1.7,  0, 0]));
			cursor.x = W * 0.945;
			cursor.y = CURSOR_Y;
			cursor.scaleX = cursor.scaleY = 5;
			cursor.filters = [ new DropShadowFilter(3, 45, 0x000000, 0.5, 0, 0) ];
			addChild(cursor);
			enableClick();
		}
		
		private function enableClick():void {
			stage.addEventListener(MouseEvent.CLICK, clickHandler);
			tickCursor();
		}
		
		private function disableClick():void {
			stage.removeEventListener(MouseEvent.CLICK, clickHandler);
			Tweener.removeTweens(cursor);
			cursor.alpha = 0;
		}
		
		private function clickHandler(event:MouseEvent):void {
			disableClick();
			
			// an easy way to flip integers
			triangleState = 1 - triangleState;
			
			for (var i:int = 0; i < polygons.length; i++) {
				Tweener.addTween(polygons[i], { 
					// Which transition type do you like?
					time:0.7, transition:"easeOutCubic", 
					x:polygonData[i].x[triangleState], 
					y:polygonData[i].y[triangleState], 
					rotation:0, 
					_bezier:polygonData[i].bezier} );
			}
			
			if (triangleState == 1) {
				circle.x = -0;
				circle.y = -30;
				Tweener.addTween(circle, { delay:0.7, time:0.6, transition:"easeOutElastic", x:0, y:0 } );
				Tweener.addTween(circle, { delay:0.7, time:0.2, transition:"easeOutQuart", alpha:1 });
			} else {
				Tweener.addTween(circle, { time:0.2, transition:"easeOutQuart", alpha:0 });
			}
			
			if (++messageNo >= MESSAGES.length) {
				messageNo = 1;
			}
			textField.text = MESSAGES[messageNo];
			textField.alpha = 0;
			Tweener.addTween(textField, { delay:0.6, time:0.2, transition:"easeInQuart", alpha:1, onComplete:enableClick } );
		}
		
		private function tickCursor():void {
			cursor.y = CURSOR_Y;
			Tweener.addTween(cursor, { time:0.25, transition:"linear", y:CURSOR_Y + 3 } );
			Tweener.addTween(cursor, { time:0.1, transition:"easeOutSine", alpha:1 } );
			Tweener.addTween(cursor, { delay:0.15, time:0.1, transition:"easeOutSine", alpha:0 } );
			Tweener.addTween(cursor, { delay:0.45, onComplete:tickCursor } );
		}
	}
}