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

forked from: 【AS100本ノック】11回目:ろうそく

AS100本ノック
* 11回目のお題は「ろうそく」
* あなたなりの「ろうそく」を表現してください。

ろうそくの影がきれいだと思ったんです。
クリックでろうそく追加
ドラッグでろうそく移動
/**
 * Copyright mex_md ( http://wonderfl.net/user/mex_md )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/zX3D
 */

/**
 * AS100本ノック
 * 11回目のお題は「ろうそく」
 * あなたなりの「ろうそく」を表現してください。
 **/
 //ろうそくの影がきれいだと思ったんです。
 //クリックでろうそく追加
 //ドラッグでろうそく移動
package 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.GradientType;
	import flash.display.Graphics;
    import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.BlurFilter;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import net.hires.debug.Stats;
	
	[SWF(width = "465", height = "465", frameRate = "30")]
	
    public class FlashTest extends Sprite
	{
		private const ZERO:Point = new Point();
		private const BLUR_FILTER:BlurFilter = new BlurFilter(4, 4, 1);
		private const LIGHT_GRAD:Array = [0xffdaa5, 0xbbaa88, 0x000000];
		private const LIGHT_GRAD_ALPHA:Array = [1,0.7,0];
		private const LIGHT_GRAD_RATIO:Array = [15, 60, 255];
		private const FLAME_GRAD:Array = [0xCCAA88, 0xDD8833, 0xffffff]
		
		private var scaleMat:Matrix = new Matrix(0.5, 0, 0, 0.5, 0, 0);
		private var candles:Vector.<Candle> = new Vector.<Candle>();
		private var draggingCandle:Candle;
		private var shadowCanvas:Sprite = new Sprite();
		private var shadowBitmap:Bitmap;
		private var shadowBMD:BitmapData;
		private var lightCanvas:Bitmap;
		private var lightBMD:BitmapData;
		private var tempLightSprite:Sprite;
		private var lightDrawMt:Matrix = new Matrix();
		private var flameSprite:Sprite = new Sprite();
		private var flames:Vector.<Sprite> = new Vector.<Sprite>();
		private var lightGradMtx:Matrix = new Matrix();
		private var shadowGradArr:Array = [0x333333, 0x000000];
		
		public function FlashTest():void
		{
			createCanvases();//createCanvas
			stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
        }
		
		private function createCandle(xPos:Number, yPos:Number, h:Number, r:Number, power:Number):void
		{
			candles.push(new Candle(xPos, yPos, h, r, power));
			var flameShape:Sprite = flameSprite.addChild(new Sprite()) as Sprite;
			flameShape.blendMode = BlendMode.ADD;
			flameShape.buttonMode = true;
			flames.push(flameShape);
		}
		
		private function createCanvases():void
		{
			tempLightSprite = new Sprite();
			lightBMD = new BitmapData(465, 465, false, 0x000000);
			lightCanvas = new Bitmap(lightBMD);
			lightCanvas.scaleX = lightCanvas.scaleY = 1;
			addChild(lightCanvas);
			shadowBMD = new BitmapData(465 / 2, 465 / 2, true, 0x00000000);
			shadowBitmap = new Bitmap(shadowBMD);
			shadowBitmap.smoothing = true;
			shadowBitmap.blendMode = BlendMode.SUBTRACT;
			shadowBitmap.scaleX = shadowBitmap.scaleY = 2;
			addChild(shadowBitmap);
			addChild(flameSprite);
		}
		
		private function mouseDownHandler(evt:MouseEvent):void 
		{
			var draggable:Sprite = getObjectsUnderPoint(new Point(mouseX, mouseY))[2];
			if (draggable)
			{
				draggingCandle= candles[flames.indexOf(draggable)]
				stage.addEventListener(MouseEvent.MOUSE_MOVE, drag);
				stage.addEventListener(MouseEvent.MOUSE_UP, endDrag)
			}else
			{
				createCandle(mouseX, mouseY, 20 + Math.random() * 15, 7, 350 + Math.random() * 20);
			}
		}
		
		private function endDrag(evt:MouseEvent):void 
		{
			stage.removeEventListener(MouseEvent.MOUSE_UP, endDrag);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, drag);
		}
		
		private function drag(evt:MouseEvent):void 
		{
			draggingCandle.x = mouseX;
			draggingCandle.y = mouseY;
		}
		
		private function enterFrameHandler(evt:Event):void 
		{
			var l:int = candles.length;
			for (var i:int = 0; i < l; i++ )
			{
				var t:Candle = candles[i];
				if (!t.update())
				{
					candles.splice(i, 1);
					flames[i].graphics.clear();
					flames.splice(i, 1);
					l--;
					i--;
				}
			}
			loop();
		}
		
		/*-----------------------------------------//
		//Mainloop
		//------------------------------------------*/
		private function loop(evt:Event = null ):void 
		{
			lightBMD.lock();
			shadowBMD.lock();
			//resetCanvases
			shadowCanvas.graphics.clear();
			lightBMD.fillRect(lightBMD.rect, 0x000000);
			shadowBMD.fillRect(shadowBMD.rect, 0x00000000);
			var l:int = candles.length;
			for (var i:int = 0; i < l; i++ )
			{
				var c:Candle = candles[i];
				//shineLight
				tempLightSprite.graphics.clear();
				lightGradMtx.createGradientBox(c.lightPower, c.lightPower, 0, 0);
				tempLightSprite.graphics.beginGradientFill(GradientType.RADIAL, LIGHT_GRAD, LIGHT_GRAD_ALPHA, LIGHT_GRAD_RATIO,lightGradMtx,"pad","rgb",0);
				tempLightSprite.graphics.drawRect(0,0,c.lightPower, c.lightPower);
				tempLightSprite.graphics.endFill();
				lightDrawMt.createBox(1,1, 0, c.x-c.lightPower*0.5,c.y-c.lightPower*0.5);
				lightBMD.draw(tempLightSprite, lightDrawMt, null, BlendMode.ADD,new Rectangle(c.x-c.lightPower*0.5,c.y-c.lightPower*0.5,c.lightPower,c.lightPower), true);
				//flame
				var flame:Sprite = flames[i];
				flame.graphics.clear();
				flame.x = c.x;
				flame.y = c.y;
				var fCenter:Point = new Point(Math.random()*2-1-20,Math.random()*2-1-20) 
				lightGradMtx.createGradientBox(40, 40,0,fCenter.x ,fCenter.y);
				flame.graphics.beginGradientFill(GradientType.RADIAL,FLAME_GRAD,[1,0.2,0],[25,100,200],lightGradMtx );
				flame.graphics.drawCircle(fCenter.x+20, fCenter.y+20, 40);
				flame.graphics.endFill();
				
				//castShadow
				for (var j:int = 0; j < l; j++ )
				{
					if (j != i)//自分以外
					{
						var anotherCandle:Candle = candles[j];
						
						var a:Point = new Point(anotherCandle.x + Math.random() * 28-14, anotherCandle.y + Math.random() * 28-14);//光源の位置にゆらぎを加えとく
						var vec:Point = c.subtract(a);
						var dis:Number = vec.length;
						
						//接点ポイント計算
						var tPs:Vector.<Point> = calcTangPoint(anotherCandle, c, c.radius, vec);
						
						if (anotherCandle.height > c.height) vec.normalize(dis * (c.height / (anotherCandle.height - c.height)))
						else vec.normalize(465);//無限になるのでステージサイズの長さに制限
						
						//接点
						var tP1:Point = tPs[0];//接点1(光源point基準)
						var tP2:Point = tPs[1];//接点1(光源point基準)
						
						//影のポイントを作成
						var sc:Number = 1 + vec.length / dis;
						//MainShadow
						var mt:Matrix = new Matrix();
						var translateX:Number = anotherCandle.x + c.x * sc;
						var translateY:Number= anotherCandle.y + c.y * sc;
						mt.createBox(sc, sc, 0, translateX, translateY);
						var cP1:Point = mt.transformPoint(tP1);//接点1の影がcastされるポイント(ステージ基準)
						var cP2:Point = mt.transformPoint(tP2);//接点2の影がcastされるポイント(ステージ基準)
						//SubShadow1
						mt.createBox(sc, sc, 2 * Math.PI / 180, translateX, translateY);
						var cP1_l:Point = mt.transformPoint(tP1);//接点1の影がcastされるポイント(ステージ基準)
						var cP2_l:Point = mt.transformPoint(tP2);//接点2の影がcastされるポイント(ステージ基準)
						//SubShadow2
						mt.createBox(sc, sc, -2 * Math.PI / 180, translateX, translateY);
						var cP1_r:Point = mt.transformPoint(tP1);//接点1の影がcastされるポイント(ステージ基準)
						var cP2_r:Point = mt.transformPoint(tP2);//接点2の影がcastされるポイント(ステージ基準)
						
						tP1.offset(anotherCandle.x+c.x,anotherCandle.y+c.y)//接点1(ステージ基準に変換)
						tP2.offset(anotherCandle.x + c.x, anotherCandle.y + c.y)//接点2(ステージ基準に変換)
						
						//drawShadowShape
						var alphaArr:Array = [1 - dis / (anotherCandle.lightPower * 0.8), 0];
						lightGradMtx.createGradientBox(vec.length * 2, vec.length * 2, 0, c.x - vec.length, c.y - vec.length);
						
						//MainShadow
						shadowCanvas.graphics.beginGradientFill(GradientType.RADIAL, shadowGradArr, alphaArr, [0, 127],lightGradMtx);
						shadowCanvas.graphics.moveTo(tP1.x, tP1.y);
						shadowCanvas.graphics.lineTo(cP1.x, cP1.y);
						shadowCanvas.graphics.lineTo(cP2.x, cP2.y);
						shadowCanvas.graphics.lineTo(tP2.x, tP2.y);
						shadowCanvas.graphics.lineTo(tP1.x, tP1.y);
						shadowCanvas.graphics.endFill();
						//subShadow1
						shadowCanvas.graphics.beginGradientFill(GradientType.RADIAL,shadowGradArr, alphaArr, [0, 100],lightGradMtx);
						shadowCanvas.graphics.moveTo(tP1.x, tP1.y);
						shadowCanvas.graphics.lineTo(cP1_l.x, cP1_l.y);
						shadowCanvas.graphics.lineTo(cP2_l.x, cP2_l.y);
						shadowCanvas.graphics.lineTo(tP2.x, tP2.y);
						shadowCanvas.graphics.lineTo(tP1.x, tP1.y);
						shadowCanvas.graphics.endFill();
						//subShadow2
						shadowCanvas.graphics.beginGradientFill(GradientType.RADIAL, shadowGradArr, alphaArr, [0, 100],lightGradMtx);
						shadowCanvas.graphics.moveTo(tP1.x, tP1.y);
						shadowCanvas.graphics.lineTo(cP1_r.x, cP1_r.y);
						shadowCanvas.graphics.lineTo(cP2_r.x, cP2_r.y);
						shadowCanvas.graphics.lineTo(tP2.x, tP2.y);
						shadowCanvas.graphics.lineTo(tP1.x, tP1.y);
						shadowCanvas.graphics.endFill();
					}
				}
			}
			shadowBMD.draw(shadowCanvas, scaleMat, null, null, null, true);
			shadowBMD.applyFilter(shadowBMD, shadowBMD.rect, ZERO, BLUR_FILTER);
			lightBMD.unlock();
			shadowBMD.unlock();
		}
		
		/*-----------------------------------------//
		//任意の点と円の接点を求める
		//------------------------------------------*/
		private function calcTangPoint(p:Point, cP:Point, cR:Number,vec:Point):Vector.<Point>
		{
			var returnPoints:Vector.<Point> = new Vector.<Point>();
			var angle:Number = Math.acos(cR / vec.length);
			var offsetAngle:Number = Math.atan2(vec.y, vec.x);
			
			var tP1:Point = Point.polar(cR, offsetAngle+angle);
			var tP2:Point = Point.polar(cR, offsetAngle-angle);
			tP1.offset(-p.x, -p.y);
			tP2.offset(-p.x, -p.y);
			returnPoints.push(tP1);
			returnPoints.push(tP2);
			
			return returnPoints;
		}
    }
}

import flash.geom.Point;
class Candle extends Point
{
	private var fading:Boolean = false;
	private var max_power:Number;
	
	private var _height:Number;
	public function get height():Number { return _height; }
	public function set height(value:Number):void {_height = value;}
	
	private var _radius:Number;
	public function get radius():Number { return _radius; }
	public function set radius(value:Number):void {_radius = value;}
	
	private var _lightPower:Number;
	public function get lightPower():Number { return _lightPower; }
	public function set lightPower(value:Number):void { _lightPower = value;}
	
	public function Candle(xPos:Number, yPos:Number, height:Number,radius:Number, power:Number):void
	{
		super(xPos, yPos);
		this.height = height;
		this.radius = radius;
		this.max_power = power;
		this.lightPower = power;
	}
	
	public function update():Boolean
	{
		if (!fading)
		{
			this.height -= 0.03;
			
			if (height <= 3) fading = true;
		}else
		{
			max_power -= (16 * Math.random() + 2);
			if (max_power <= 0) return false;
		}
		lightPower = max_power*(0.95+0.1*Math.random());
		return true;
	}
}