forked from: forked from: 【AS100本ノック】8回目:水

by bradsedito forked from forked from: 【AS100本ノック】8回目:水 (diff: 243)
AS100本ノック
8回目のお題は「水」
あなたなりの「水」を表現してください。
--
校庭の蛇口で遊ぶイメージでした。
水に見えないこともない・・・。
♥0 | Line 215 | Modified 2010-10-16 09:50:16 | MIT License
play

ActionScript3 source code

/**
 * Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tcgA
 */

// forked from mex_ichikawa's forked from: 【AS100本ノック】8回目:水
// forked from mex's 【AS100本ノック】8回目:水
/* 
* AS100本ノック
* 8回目のお題は「水」
* あなたなりの「水」を表現してください。
* --
* 校庭の蛇口で遊ぶイメージでした。
* 水に見えないこともない・・・。
*/
package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.display.GradientType;
    import flash.display.Graphics;
    import flash.display.InterpolationMethod;
    import flash.display.Loader;
    import flash.display.SpreadMethod;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.BitmapFilter;
    import flash.filters.DisplacementMapFilter;
    import flash.filters.DisplacementMapFilterMode;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;    
    
    [SWF(width=465, height=465, backgroundColor=0xFFFFFF, frameRate=60)]
    public class Fountain extends Sprite
    {
        public static const STAGE_WIDTH:uint = 465;
        public static const STAGE_HEIGHT:uint = 465;
        private static const REQUEST_IMAGE:String = "http://sphotos.ak.fbcdn.net/hphotos-ak-snc4/hs061.snc4/34435_824223712001_9021630_46770431_3138463_n.jpg";
        private static const CREATE_POS_X:uint = 460;
        private static const CREATE_POS_Y:uint = 460;
        private static const CREATE_NUM:uint = 10;
        private static const BASE_POWER_X:Number = -50;
        private static const BASE_POWER_Y:Number = -50;
        private static const BASE_SIZE:Number = 15;
        private static const BASE_COLOR:uint = 0xFF808080;
        private static const GRAVITY:Number = 0.9;
        private static const FRICTION:Number = 0.96;
        
        private var _waters:Vector.<WaterParticle>;
        private var _bm:Bitmap;
        private var _bmd:BitmapData;
        private var _filter:BitmapData;
        private var _particle:BitmapData;
        private var _imgLoader:Loader;
        private var _powerScaleX:Number;
        private var _powerScaleY:Number;
        public function Fountain()
        {
            init();
        }
        private function init():void
        {
            //format
            _waters = new Vector.<WaterParticle>();
            _bmd = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xFFFFFFFF);
            _filter = new BitmapData(stage.stageWidth, stage.stageHeight, true, BASE_COLOR);
            _powerScaleX = _powerScaleY = 0.5;
            
            //background
            var request:URLRequest = new URLRequest(REQUEST_IMAGE);
            var context:LoaderContext = new LoaderContext(true);
            _imgLoader = new Loader();
            _imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
            try
            {
                _imgLoader.load(request, context);
            } catch (error:Error) {
                trace("image load failed.");
            }
            
            //attach
            _bm = new Bitmap(_bmd);
            addChild(_bm);
        }
        
        private function completeHandler(event:Event):void
        {
            _imgLoader.x = (_imgLoader.width - STAGE_WIDTH) / 2;
            _imgLoader.y = (_imgLoader.height - STAGE_HEIGHT) / 2;
            _bmd.draw(_imgLoader);
            
            //event
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
        }
        private function enterFrameHandler(event:Event):void
        {
            createWater();
            drawWater();
        }
        private function mouseMoveHandler(event:MouseEvent):void
        {
            _powerScaleX = 1 - event.stageX / stage.width;
            _powerScaleY = 1 - event.stageY / stage.height;
        }
        
        private function createWater():void
        {
            var wp:WaterParticle;
            for(var i:uint=0,imax:uint=CREATE_NUM; i<imax; i++)
            {
                wp = new WaterParticle();
                wp.x = CREATE_POS_X;
                wp.y = CREATE_POS_Y;
                wp.px = BASE_POWER_X * _powerScaleX * (Math.random() / 2 + 0.5);
                wp.py = BASE_POWER_Y * _powerScaleY * (Math.random() / 2 + 0.5);
                wp.size = BASE_SIZE * (Math.random() / 2 + 0.5);
                wp.data = getBitmapCircle(wp.size);
                _waters.push(wp);
            }
        }
        private function drawWater():void
        {
            var newlist:Vector.<WaterParticle> = new Vector.<WaterParticle>();
            var mtx:Matrix = new Matrix();
            _filter.lock();
            _filter.fillRect(_filter.rect, BASE_COLOR);
            
            for(var i:uint=0,imax:uint=_waters.length; i<imax; i++)
            {
                if(_waters[i].isActive())
                {
                    _waters[i].x += _waters[i].px;
                    _waters[i].y += _waters[i].py;
                    _waters[i].px *= FRICTION;
                    _waters[i].py *= FRICTION;
                    _waters[i].py += GRAVITY * .6;
                    
                    //ドット絵?
//                    _filter.setPixel(
//                        _waters[i].x,
//                        _waters[i].y,
//                        0x0000
//                    );
                    
                    //水っぽいけど、重い。
                    mtx = new Matrix;
                    mtx.translate(
                        _waters[i].x - _waters[i].size/2,
                        _waters[i].y - _waters[i].size/2
                    );
                    _filter.draw(
                        _waters[i].data,
                        mtx
                    );
                    
                    //速いけど、角ばって水じゃない
//                    _filter.fillRect(
//                        new Rectangle(
//                            _waters[i].x - _waters[i].size/2,
//                            _waters[i].y - _waters[i].size/2,
//                            _waters[i].size,
//                            _waters[i].size
//                        ),
//                        0x000000
//                    );

                    newlist.push(_waters[i]);
                }
            }
            _waters = newlist;
            _filter.unlock();
            
            var bmd:BitmapData = _bmd.clone()
            bmd.applyFilter(
                _bmd,
                _bmd.rect,
                new Point(0,0),
                getBitmapFilter()
            );
            _bm.bitmapData = bmd;
        }
        private function getBitmapFilter():BitmapFilter
        {
            var mapBitmap:BitmapData = _filter;
            var mapPoint:Point       = new Point(0, 0);
            var channels:uint        = BitmapDataChannel.RED;
            var componentX:uint      = channels;
            var componentY:uint      = channels;
            var scaleX:Number        = 0.5;
            var scaleY:Number        = -30;
            var mode:String          = DisplacementMapFilterMode.CLAMP;
            var color:uint           = 0;
            var alpha:Number         = 0;
            return new DisplacementMapFilter(mapBitmap,
                mapPoint,
                componentX,
                componentY,
                scaleX,
                scaleY,
                mode,
                color,
                alpha
            );
        }
        private function getBitmapCircle(radius:Number):BitmapData
        {
            var s:Sprite = new Sprite();    
            var g:Graphics = s.graphics;
            var m:Matrix = new Matrix();
            var bd:BitmapData = new BitmapData(radius * 2, radius * 2, true, 0x00000000);
            var scale:Number = 1.0 / 1638.4 * radius * 2;
            m.identity();
            m.scale(scale , scale);
            m.translate(radius, radius);
            
            g.beginGradientFill(
                GradientType.RADIAL,
                [0x000000, 0x000000],
                [1, 0.5],
                [0x00, 0xFF],
                m,
                SpreadMethod.PAD,
                InterpolationMethod.RGB,
                0
            );            
            g.drawCircle(
                radius,
                radius,
                radius
            );
            bd.draw(s);
            return bd;
        }
    }
}
import flash.display.BitmapData;
class WaterParticle
{
    public var x:Number;
    public var y:Number;
    public var px:Number;
    public var py:Number;
    public var size:Number;
    public var data:BitmapData;
    public function WaterParticle()
    {
    }
    public function isActive():Boolean
    {
        if(y <= Fountain.STAGE_HEIGHT + size/2
            && y >= -size/2
            && x <= Fountain.STAGE_WIDTH + size/2
            && x >= -size/2)
        {
            return true;
        }
        return false;
    }
}