// forked from mex's 【AS100本ノック】11回目:ろうそく /** * AS100本ノック * 11回目のお題は「ろうそく」 * あなたなりの「ろうそく」を表現してください。 * * 画像が溶ける * 最近勉強したdrawTrianglesで描画。 **/ package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.events.TimerEvent; import flash.net.URLRequest; import flash.filters.DisplacementMapFilter; import flash.filters.DisplacementMapFilterMode; import flash.filters.GradientGlowFilter; import flash.filters.BlurFilter; import flash.geom.Point; import flash.geom.Matrix; import flash.utils.Timer; import flash.system.LoaderContext; /** * @author Mao Takagi */ [SWF(width = "465", height = "465", backgroundColor = 0x000000, frameRate = "60")] public class Main extends Sprite { private const MAX_IMAGE_WIDTH:uint = 250; private const MAX_IMAGE_HEIGHT:uint = 500; private var _points:uint; private var _vertices:Vector.<Number>; private var _indices:Vector.<int>; private var _uvtData:Vector.<Number>; private var _pointArray:Vector.<MeltPoint>; private var _adjustX:Number; private var _adjustY:Number; private var _scale:Number; private var _loader:Loader; private var _bitmap:Bitmap; private var _bitmapData:BitmapData; private var _graphic:Sprite; private var _pointMax:uint; private var _canvasBmd:BitmapData; private var _canvas:Bitmap; private var _canvasSprite:Sprite; private var _fire:BallUnit; private var _fireY:Number; private var _meltTimer:Timer; private var _nowLine:uint; private var _firstine:Vector.<MeltPoint>; /** * constructor */ public function Main():void { _vertices = new Vector.<Number>(); _indices = new Vector.<int>(); _uvtData = new Vector.<Number>(); _pointArray = new Vector.<MeltPoint>(); _firstine = new Vector.<MeltPoint>(); _points = 20; _graphic = new Sprite(); _nowLine = 0; _meltTimer = new Timer(2 * 1000); _meltTimer.addEventListener(TimerEvent.TIMER, onTimerHandler); var context:LoaderContext = new LoaderContext(true); _loader = new Loader(); _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoadComplete); //_loader.load(new URLRequest("http://farm4.static.flickr.com/3057/2930778027_b4faff737a.jpg"), context); _loader.load(new URLRequest("http://farm5.static.flickr.com/4001/4281928692_8f8fe04824.jpg"), context); } /** * onImageLoadComplete * @param event Event */ private function onImageLoadComplete(event:Event):void { event.target.removeEventListener(Event.COMPLETE, onImageLoadComplete); var scaleX:Number = _loader.width / MAX_IMAGE_WIDTH; var scaleY:Number = _loader.height / MAX_IMAGE_HEIGHT; var matrix:Matrix = new Matrix(); _scale = 1; if (scaleX > 1 || scaleY > 1) { _scale = 1 / Math.max(scaleX, scaleY); matrix.scale(_scale, _scale); } _bitmapData = new BitmapData(_loader.width * _scale, _loader.height * _scale, true, 0x00000000); _bitmap = new Bitmap(_bitmapData); _bitmapData.draw(_loader, matrix); _bitmap.x = (stage.stageWidth - _bitmap.width) / 2; _bitmap.y = (stage.stageHeight - _bitmap.height) / 2; _adjustX = (stage.stageWidth - _bitmap.width) / 2; _adjustY = (stage.stageHeight - _bitmap.height) / 2; var spanX:Number = _bitmap.width / _points; var spanY:Number = _bitmap.height / _points; var i:uint = 0; var j:uint = 0; for (i = 0;i < _points + 1;i++ ) { for (j = 0;j < _points + 1;j++ ) { var point:MeltPoint = new MeltPoint(j * spanX, i * spanY, _bitmap.height); if (i == 0)_firstine.push(point); _pointArray.push(point); } } _pointMax = _pointArray.length; var uvtSpan:Number = 1 / _points; var ins:uint = 0; for(i = 0;i < _points;i++) { for (j = 0;j < _points;j++) { _indices.push(ins + 0, ins + 1, ins + 2); _indices.push(ins + 1, ins + 2, ins + 3); ins += 4; _uvtData.push((j) * uvtSpan, (i) * uvtSpan); _uvtData.push(((j) * uvtSpan) + uvtSpan, (i) * uvtSpan); _uvtData.push((j) * uvtSpan, ((i) * uvtSpan) + uvtSpan); _uvtData.push(((j) * uvtSpan) + uvtSpan, ((i) * uvtSpan) + uvtSpan); } } _graphic.x = _adjustX; _graphic.y = _adjustY; _canvasSprite = new Sprite(); _canvasBmd = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xFF000000); _canvas = new Bitmap(_canvasBmd); _fire = new BallUnit(); _fire.x = stage.stageWidth / 2 + _fire.width / 2; _canvasSprite.addChild(_fire); var glowFileter:GradientGlowFilter = new GradientGlowFilter(10, 90, [0xFF0000, 0xFFFF00, 0xFFFFFF], [0.8, 0.6, 1], [0, 120, 255], 8, 10, 1, 1); var blurFileter:BlurFilter = new BlurFilter(10, 10, 1); _canvasSprite.filters = [blurFileter, glowFileter]; addChild(_canvas); addChild(_graphic); _meltTimer.start(); addEventListener(Event.ENTER_FRAME, enterFrameHandler); } /** * fireY * @return Number */ private function fireY():Number { var temp:Array = new Array(); for (var i:uint = 0; i < _points + 1;i++ ) { temp.push(_firstine[i].y); } return Math.min.apply(null, temp) + _adjustY; } /** * onTimerHandler * @param event TimerEvent */ private function onTimerHandler(event:TimerEvent):void { if (_nowLine < _points) { var i:uint; for (i = 0; i < _points; i++ ) { var target:MeltPoint = _pointArray[_nowLine * _points + i]; target.melt(); } _nowLine++; } } /** * enterFrameHandler * @param event Event */ private function enterFrameHandler(event:Event):void { draw(); } /** * draw */ private function draw():void { var i:uint = 0; var j:uint = 0; _graphic.graphics.clear(); _vertices = new Vector.<Number>(); for (i = 0; i < _points; i++) { for (j = 0; j < _points; j++) { var base:uint = i * (_points + 1) + j; var leftTop:MeltPoint = _pointArray[base]; var rightTop:MeltPoint = _pointArray[base + 1]; var leftBottom:MeltPoint = _pointArray[base + _points + 1]; var rightBottom:MeltPoint = _pointArray[base + _points + 2]; _vertices.push(leftTop.x, leftTop.y); _vertices.push(rightTop.x, rightTop.y); _vertices.push(leftBottom.x, leftBottom.y); _vertices.push(rightBottom.x, rightBottom.y); } } _graphic.graphics.beginBitmapFill(_bitmapData); _graphic.graphics.drawTriangles(_vertices, _indices, _uvtData); _graphic.graphics.endFill(); _fire.y = fireY(); _canvas.bitmapData.dispose(); var bmd:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xFF000000); bmd.lock(); bmd.draw(_canvasSprite); bmd.unlock(); bmd.paletteMap(bmd, bmd.rect, bmd.rect.topLeft, null, null, null); _canvas.bitmapData = bmd; } } } import flash.geom.Point; import org.libspark.betweenas3.BetweenAS3; import org.libspark.betweenas3.events.TweenEvent; import org.libspark.betweenas3.tweens.ITween; class MeltPoint extends Point { private var _target:Number; private var _rate:Number; private var _tempTarget:Number; /** * constructor */ public function MeltPoint(x:Number, y:Number, target:Number) { super(x, y); _target = target; _rate = _target / 10; } /** * melt * @param */ public function melt():void { _tempTarget = _rate + y; if (_tempTarget < _target) { var t:ITween = BetweenAS3.tween(this, { y:_tempTarget }, null, Math.random() * 2 + 6); t.addEventListener(TweenEvent.COMPLETE, function():void { t.removeEventListener(TweenEvent.COMPLETE, arguments.callee); melt(); }); t.play(); } } } import flash.display.Sprite class BallUnit extends Sprite { private var _ballArray:Vector.<Ball>; /** * constructor */ public function BallUnit() { _ballArray = new Vector.<Ball>(); for (var i:uint = 0; i < 5;i++ ) { var ball:Ball = new Ball(35 - (i * 4)); ball.y = -i * 5; _ballArray.push(ball); if (i != 0) { _ballArray[i - 1].addChild(ball); } else { addChild(ball); } } } } import flash.display.Sprite import flash.events.Event; import flash.filters.BlurFilter; class Ball extends Sprite { /** * constructor * @param size */ public function Ball(size:uint) { var sprite:Sprite = new Sprite(); sprite.graphics.beginFill(0xFFFFFF); sprite.graphics.drawCircle(0, 0, size / 2); sprite.graphics.endFill(); sprite.x = -size / 2; sprite.y = -size / 2; var filter:BlurFilter = new BlurFilter(); sprite.filters = [filter]; addChild(sprite); addEventListener(Event.ENTER_FRAME, enterFrameHandler); } /** * enterFrameHandler * @param event */ private function enterFrameHandler(event:Event):void { x += Math.random() * Math.random()*(2 - (-2) + 1) + (-2) - x; y += Math.random() * Math.random()*(6 - (-6) + 1) + (-6) - y - 6; } } forked from: 【AS100本ノック】11回目:ろうそく