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

Realistic Sunlight through Clouds

Brad Sedito
Cloud and sun blending to imitate nature for realism
Feel free to add suggestions :)
Let's begin....
Get Adobe Flash player
by bradsedito 08 Aug 2011
/**
 * Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/dUzj
 */

// Brad Sedito
// Cloud and sun blending to imitate nature for realism
// Feel free to add suggestions :)
// Let's begin....

package {
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.media.SoundLoaderContext;
    import flash.media.SoundTransform;
    import flash.net.URLRequest;
    import flash.utils.Timer;
    import idv.cjcat.stardust.twoD.emitters.Emitter2D;
    import com.greensock.*;
    import com.greensock.easing.*;
    import net.hires.debug.Stats;
    
    public class HORIZON extends Sprite
    {
        public static const WIDTH:  Number = 450   ;
        public static const HEIGHT: Number = 450   ; 
        
        private var debug:Boolean = false;
        private var sun:SunLight;
        private var entities:Vector.<Entity> = new Vector.<Entity>();
        private var renderedScene:BitmapData = new BitmapData(WIDTH, HEIGHT);
        private var scene:Sprite = new Sprite;
        public static const CLOUD_NUM:int = 15;
        public static const ERROR_SEEDS:Array = [346, 514, 1155, 1519, 1690, 1977, 2327, 2337, 2399, 2860, 2999, 3099, 4777, 4952, 5673, 6265, 7185, 7259, 7371, 7383, 7717, 7847, 8032, 8350, 8676, 8963, 8997, 9080, 9403, 9615, 9685];
        public var loading:LoadingScene;

 // perlinNoise
        public function HORIZON():void
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            loading = new LoadingScene();
            addChild(loading);
            addEventListener(Event.ENTER_FRAME, onLoading);
            addEventListener(Event.ADDED_TO_STAGE, loop);
  /*           var mc:Sprite = new Sprite();
             mc.graphics.drawCircle(0,0,30); 
             mc.graphics.beginFill(0x00000000, 1);
          // mc.x = stage.mouseX;    mc.y = stage.mouseY;
             mc.x = 465/2;    mc.y = 465/2;
             addChild(mc);
             TweenMax.to(mc, 3, {x:mc.x + 30, yoyo:true, ease:Cubic.easeInOut});
       }        
   */   
        }

//         Cloud Constants
        public static const FOCUS:Number = 300;
        public static const MAX_Z:Number = 2000;
        public static const MIN_Z:Number = 400;

        private function onLoading(...arg):void {
            for (var i:int = 0; i < 3; i++) {
                if(Clouds.bmps.length >= CLOUD_NUM){
                    start();
                    break;
                }
                var seed:int = Math.random() * 10000 + 1;
                if (ERROR_SEEDS.indexOf(seed) >= 0) seed++;
                var ct:Number = (Math.random() < 0.2)? Math.random() * 0.3 : Math.random() * 1.5;
                var z:Number = MAX_Z - (MAX_Z-MIN_Z)/CLOUD_NUM*(Clouds.bmps.length);
                var w:Number = 400/(z/FOCUS);
                var h:Number = 200/(z/FOCUS);
                var bmp:Bitmap = new Bitmap(Painter.createCloud(w, h, seed, ct, Color.cloudBase, Color.cloudLight, Color.cloudShadow));
                bmp.x = Math.random() * (HORIZON.WIDTH + bmp.width) - bmp.width;
                bmp.y = HEIGHT*0.6 - HEIGHT*0.5 * FOCUS/z;
                Clouds.bmps.push(bmp);
                loading.setProgress(Clouds.bmps.length / CLOUD_NUM);
            }
        }

        public function start():void
        {            
            removeEventListener(Event.ENTER_FRAME, onLoading);
            removeChild(loading);
            stage.quality = StageQuality.BEST;
            var matrix:Matrix = new Matrix();
            matrix.createGradientBox(WIDTH, HEIGHT, Math.PI / 2);
            graphics.beginGradientFill(GradientType.LINEAR, [0x3A6CFF, 0x53ADFF], null, [0, 128], matrix);
//            graphics.beginGradientFill(GradientType.LINEAR, [0x51484A, 0x96644E], null, [0, 128], matrix);
            graphics.drawRect(0, 0, WIDTH, HEIGHT);
            graphics.endFill();

            var clouds:Clouds = new Clouds;
            entities.push(scene.addChild(clouds));
            
            var fogR:Number = 0x70;
            var fogG:Number = 0x70;
            var fogB:Number = 0x70;
            
            addChild(scene);
            addChild(sun = new SunLight(renderedScene));
            
            var outline:Shape = new Shape();
            var g:Graphics = outline.graphics;
            g.lineStyle(1, 0x808080);
            g.drawRect( -1, -1, WIDTH + 2, HEIGHT + 2);
            addChild(outline);
            
            restoreFilters(debug);
            
//          Play Audio
//            playSound();
            
            stage.addEventListener(MouseEvent.CLICK, clickHandler);
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }
        
        private function clickHandler(e:MouseEvent):void 
        {
            debug = !debug;
            
            var matrix:Matrix = new Matrix();
            if (debug) {
            //    Transform Matrix。
                matrix.scale(0.2, 0.2);
                matrix.translate(WIDTH * 0.4, HEIGHT * 0.4);
            }
            transform.matrix = matrix;
            
            restoreFilters(debug);
        }
        
        private function restoreFilters(debug:Boolean):void
        {
            for each (var entity:Entity in entities)
            {
                entity.restoreFilter(debug);
            }
        }
        
        private function enterFrameHandler(e:Event):void 
        {
            for each (var entity:Entity in entities)
            {
                entity.update();
            }
            
            renderedScene.fillRect(renderedScene.rect, 0);
            renderedScene.draw(scene);
            sun.update();            
        }        
    }
}

import flash.display.*;
import flash.filters.*;
import flash.geom.*;


class Entity extends Sprite
{
    public function update():void { };
    public function restoreFilter(debug:Boolean):void { };
}

class SunLight extends Entity {
    public static const FXW:int = 0x100;
    public static const FXH:int = 0x100;

    private var src:BitmapData = new BitmapData(FXW, FXH, true, 0);
    private var dst:BitmapData = new BitmapData(FXW, FXH, true, 0);
    private var sun:Shape = new Shape;
    private var obstruction:Bitmap;
    private var scaleDown:Matrix = new Matrix;
    private var scaleUp:Matrix = new Matrix;
    private var mtx:Matrix = new Matrix;
    private var canvas:Bitmap = new Bitmap(dst);
    private var blur:BlurFilter = new BlurFilter(3, 3, 3);
    
    public function SunLight(obstruction:BitmapData) {
        this.blendMode = "add";
        this.obstruction = new Bitmap(obstruction);
        var m:Matrix = new Matrix;
        m.createGradientBox(FXW, FXH, 0, 0, 0);
        sun.graphics.beginGradientFill("radial", [0x0C0a08, 0x0a0806, 0x060504, 0x020201, 0], [1, 1, 1, 1, 1], [0, 10, 34, 64, 255], m);
        sun.graphics.drawRect(0, 0, FXW*4, FXH);
        sun.graphics.endFill();
        sun.cacheAsBitmap = true;
        
        scaleDown.scale(FXW/HORIZON.WIDTH, FXH/HORIZON.HEIGHT);
        scaleUp.scale(HORIZON.WIDTH/FXW, HORIZON.HEIGHT/FXH);

        addChild(canvas);
        transform.matrix = scaleUp;
    }

    public override function update():void {
        src.lock();
        dst.lock();
        src.fillRect(src.rect, 0);
        src.draw(sun);
        src.draw(obstruction, scaleDown, null, "erase");
        canvas.bitmapData = process(src);
        src.unlock();
        dst.unlock();
        
//        this.x = (FXW/mouseX)/2;
//        this.y = mouseY;
    }
    
    private function process(src:BitmapData):BitmapData {
        var dst:BitmapData = this.dst;
        mtx.identity();
        mtx.translate(-FXW/34, -FXH/34);
        mtx.scale(17/16, 17/16);
        var cnt:int = 5;
        var tmp:BitmapData;
        while(cnt--) {
            mtx.concat(mtx);
            dst.copyPixels(src, src.rect, src.rect.topLeft);
            dst.draw(src, mtx, null, "add");
            dst.applyFilter(dst, dst.rect, dst.rect.topLeft, blur);
            tmp = src;
            src = dst;
            dst = tmp;
        }
        return src;
    }
}


import flash.display.*;
import flash.events.*;

class Clouds extends Entity 
{
    public static var bmps:Array = [];

    public function Clouds() 
    {          
        for each(var bmp:Bitmap in bmps) addChild(bmp);
    }

    public override function update():void {
        for each(var bmp:Bitmap in bmps) {
            bmp.x -= bmp.width * 0.001;
            if(bmp.x + bmp.width < 0) {
                bmp.x = HORIZON.WIDTH;
            }
        }
    }
}

const SPEED:Number = 300;

function lerp(n0:Number, n1:Number, p:Number):Number
{
    return n0 * (1 - p) + n1 * p;
}

// [min, max
function rnd(min:Number, max:Number):Number
{
    return min + Math.random() * (max - min);
    //  return lerp(min, max, Math.random());
}

class Color {
    static public var cloudBase   :uint = 0xFFFFFF;
    static public var cloudLight  :uint = 0xE0E0E0;
    static public var cloudShadow :uint = 0x8C8C8C;
}

class LoadingScene extends Sprite {
    private var _lineWidth:Number = 200;
    private var _loadedLine:Sprite;
    public function LoadingScene() {
        var bg:Sprite = addChild(Painter.createGradientRect(HORIZON.WIDTH, HORIZON.HEIGHT, [0x000000], [1])) as Sprite;
        var baseLine:Sprite = addChild(Painter.createGradientRect(_lineWidth, 2, [0x444444], [1])) as Sprite;
        _loadedLine = addChild(Painter.createGradientRect(_lineWidth, 2, [0x7DA3C8], [1])) as Sprite;
        baseLine.x = _loadedLine.x = int((HORIZON.WIDTH - _lineWidth) / 2);
        baseLine.y = _loadedLine.y = int((HORIZON.HEIGHT - baseLine.height) / 2);
        setProgress(0);
    }
    public function setProgress(per:Number):void {
        _loadedLine.width = _lineWidth * per;
    }
}

class Painter {
    /**
    * @param    width    
    * @param    height   
    * @param    seed    
    * @param    contrast  
    * @param    color   
    * @param    light   
    * @param    shadow   
    */
    static public function createCloud(width:int, height:int, seed:int, contrast:Number = 1, color:uint = 0xFFFFFF, light:uint = 0xFFFFFF, shadow:uint = 0xDDDDDD):BitmapData {
        var gradiation:Sprite = new Sprite();
        var drawMatrix:Matrix = new Matrix();
        drawMatrix.createGradientBox(width, height);
        gradiation.graphics.beginGradientFill("radial", [0x000000, 0x000000], [0, 1], [0, 255], drawMatrix);
        gradiation.graphics.drawRect(0, 0, width, height);
        gradiation.graphics.endFill();
        var alphaBmp:BitmapData = new BitmapData(width, height);
        alphaBmp.perlinNoise(width / 3, height / 2.5, 5, seed, false, true, 1|2|4, true);
        var zoom:Number = 1 + (contrast - 0.1) / (contrast + 0.9);
        if (contrast < 0.1) zoom = 1;
        if (contrast > 2.0) zoom = 2;
        var ctMatrix:Array = [contrast + 1, 0, 0, 0, -128 * contrast, 0, contrast + 1, 0, 0, -128 * contrast, 0, 0, contrast + 1, 0, -128 * contrast, 0, 0, 0, 1, 0];
        alphaBmp.draw(gradiation, new Matrix(zoom, 0, 0, zoom, -(zoom - 1) / 2 * width, -(zoom - 1) / 2 * height));
        alphaBmp.applyFilter(alphaBmp, alphaBmp.rect, new Point(), new ColorMatrixFilter(ctMatrix));
        var image:BitmapData = new BitmapData(width, height, true, 0xFF << 24 | color);
        image.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
        image.applyFilter(image, image.rect, new Point(), new GlowFilter(light, 1, 4, 4, 1, 3, true));
        var bevelSize:Number = Math.min(width, height) / 30;
        image.applyFilter(image, image.rect, new Point(), new BevelFilter(bevelSize, 45, light, 1, shadow, 1, bevelSize/5, bevelSize/5, 1, 3));
        var image2:BitmapData = new BitmapData(width, height, true, 0);
        image2.draw(Painter.createGradientRect(width, height, [light, color, shadow], [1, 0.2, 1], null, 90), null, null, BlendMode.MULTIPLY);
        image2.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
        image.draw(image2, null, null, BlendMode.MULTIPLY);
        alphaBmp.dispose();
        return image;
    }


        static public function 
        createGradientRect(width:Number, height:Number, colors:Array, alphas:Array, ratios:Array = null, rotation:Number = 0):Sprite {
            var i:int, rts:Array = new Array();
                if(ratios == null) for (i = 0; i < colors.length; i++) rts.push(int(255 * i / (colors.length - 1)));
                else for (i = 0; i < ratios.length; i++) rts[i] = Math.round(ratios[i] * 255);
            var sp:Sprite = new Sprite();
            var mtx:Matrix = new Matrix();

            mtx.createGradientBox(width, height, Math.PI / 180 * rotation, 0, 0);
                  if (colors.length == 1 && alphas.length == 1) sp.graphics.beginFill(colors[0], alphas[0]);
                   else sp.graphics.beginGradientFill("linear", colors, alphas, rts, mtx);
            sp.graphics.drawRect(0, 0, width, height);
         sp.graphics.endFill();
         return sp;
    }
}