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

Mr Grass, The grass movement algorithm

Grass movement algorithm in actionscript 3, in this experiment I'm using some flash drawing options for painting grass leaves with gradients and filters
/**
 * Copyright yoambulante.com ( http://wonderfl.net/user/yoambulante.com )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/8G0P
 */

/********************************************************/
/*  Copyright © YoAmbulante (alex.nino@yoambulante.com) */
/*                                                      */
/*  You may modify or sell this code, you can do        */
/*  whatever you want with it, I don't mind. Just don't */
/*  forget to contribute with a beer thru the website.  */
/*                                                      */
/*  Visit http://www.yoambulante.com to clarify any     */
/*  doubt with this code. Note that donators have       */
/*  priority on information enquiries.                  */
/*                                                      */
/********************************************************/
package {
    import flash.display.Sprite;
    import flash.display.Shape;
    import flash.events.Event;
    import flash.events.MouseEvent;    
    import flash.filters.BlurFilter;    
    import flash.geom.Matrix;
    import flash.geom.Rectangle;    
    [SWF(width="500", height="100", frameRate="30", backgroundColor="#FFFFFF")]
    public class GrassMain extends Sprite {        
        private var a:Array;
        private var mouse_down:Boolean = false;                
        private var drawing:Boolean = false;        
        private var blur_rect:Rectangle;
        private var blur_mx:Matrix;                            
        private var gradient_bg:Sprite;
        function GrassMain():void {            
            //-------------- gradient background ------------------            
            gradient_bg = new Sprite();
            var m:Matrix = new Matrix();
            m.createGradientBox(500, 100, (Math.PI / 180) * 90, 0, 0);            
            gradient_bg.graphics.beginGradientFill("linear", [0x9ED0F1, 0xD6EDF5], [1, 1], [0,130], m);
            gradient_bg.graphics.drawRect(0, 0, 500, 100);    
            gradient_bg.cacheAsBitmap = true;            
            this.addChild(gradient_bg);            
            //-------------- gradient background ------------------
            //-------------- grass layers ------------------
            var grass_areas:Array = new Array();            
            var i:int;
            var sp:Sprite;
            var blur_fac:int = 2;
            for (i = 0; i < 3; i++) {                
                sp = new Sprite();
                sp.mouseEnabled = false;
                sp.mouseChildren = false;
                if (i != 1){
                    var blur_eff:BlurFilter = new BlurFilter(blur_fac, blur_fac, 1);
                    blur_fac *= 2;                    
                    sp.filters = [blur_eff];                    
                }
                grass_areas.push(sp);
                sp.x = 4;
                sp.y = 20;
                this.addChild(sp);            
                //add mask for each
                var grass_mask:Shape = new Shape();
                grass_mask.graphics.beginFill(0, 1);                
                grass_mask.x = 6;
                grass_mask.graphics.drawRect(0, 0, 500, 100);            
                this.addChild(grass_mask);
                sp.mask = grass_mask;
            }
            //-------------- grass layers ------------------
            //-------------- grass leaves ------------------
            var max_size:int = 0;
            a = new Array();
            for (i = 0; i < 500; i++) {
                var dp:int = int(i / 167);
                sp = grass_areas[dp];
                var len:int = Grass.rand(100) + 50;
                if (len > max_size) {
                    max_size = len;
                }
                var g:Grass = new Grass(Grass.rand(600), 0, len, (Grass.rand(100) / 100) * 1, 60, Grass.rand(40) - 20, (Grass.rand(100) / 100) * 1);
                if (dp == 0) {
                    g.y += 15;
                    g.scaleX = .75;
                    g.scaleY = g.scaleX;                    
                } else if (dp == 2) {
                    g.y -= 10;
                    g.scaleX = 1.7;
                    g.scaleY = g.scaleX;                
                }
                sp.addChild(g);
                g.next(0, true);            
                a.push(g);
            }    
            //-------------- grass leaves ------------------            
            this.addEventListener(Event.ENTER_FRAME, enterFrame);            
            this.addEventListener(MouseEvent.MOUSE_DOWN, mDown);            
        }                
        public function mDown (e:MouseEvent):void {                
            mouse_down = true;            
            stage.addEventListener(MouseEvent.MOUSE_UP, mUp);
            this.addEventListener(MouseEvent.MOUSE_UP,  mUp);            
            this.addEventListener(MouseEvent.ROLL_OUT,  mUp);            
        }
        public function mUp (e:MouseEvent):void {                        
            mouse_down = false;                    
            stage.removeEventListener(MouseEvent.MOUSE_UP, mUp);
            this.removeEventListener(MouseEvent.MOUSE_UP,  mUp);            
            this.removeEventListener(MouseEvent.ROLL_OUT,  mUp);            
        }        
        public function enterFrame (e:Event):void {
            if (drawing || mouse_down){    
                drawing    = false;
                for (var i:int = 0; i < a.length; i++) {
                    var wind:Number = 0;
                    if (mouse_down){                    
                        var diff:Number = Grass(a[i]).x - stage.mouseX;
                        if (Math.abs(diff) < 100) {                            
                            wind = (1 - Math.abs(diff / 100)) * 50 * (diff < 0 ? -1 : 1);                        
                        }
                    }
                    if (Grass(a[i]).next(wind, false)) {                    
                        drawing    = true;                        
                    }                    
                }                
            }            
        }
        
    }    
}
class Grass extends flash.display.Shape {        
    private var size:Number; /* pixels length */
    private var stiffness:Number; /* 0..1 how flexible it should be */
    private var springiness:Number; /* max limit applyed by the wind */
    private var wind_force:Number; //used for moving the whole body, is like his actual position.     
    private var zero_force:Number; //is the position when it is stopped.
    private var shadow_width:Number;             
    private var shadow_color:Number;
    private var grass_color:Number;
    private var px:Number; //x position
    private var py:Number; //y position        
    //using in drawing function.
    private var st_mov:Number; //depending of its position, ending point will be lower.
    private var tension:Number; //constant value, see object creation
    private var tension2:Number; //constant value, see object creation
    private var redraw:Boolean;                            
    //vars used in animation.
    private var vel:Number = 0;    //velocity applyed during animation.
    private var fact_friction:Number;
    private var fact_acc:Number;
    private var last_wf:Number;
    private var returning:Boolean;
    private var shadow_green:uint;
    private var grass_green:uint;
    private var status:uint;
    //colors during animation.
    public static var GRASS_GREEN:uint = 120;    
    public static var SHADOW_GREEN:uint = 60;    
    public static var GRASS_RED:uint = 0x66;
    public static var SHADOW_RED:uint = 0x33;        
    function Grass(newx:Number, newy:Number, len:Number, st:Number, sp:Number, zf:Number, sw:Number) {            
        status = 0;
        redraw = true;
        returning = false;            
        x = newx;
        y = newy;
        px = 0;
        py = 170;
        size = len;
        stiffness = st;        
        st_mov = .8 + (1 - stiffness) * .2;
        springiness = sp;
        zero_force = zf;
        shadow_width = sw;            
        shadow_green = rand(40);
        grass_green = rand(40);            
        shadow_color = RGBtoNum(SHADOW_RED, SHADOW_GREEN + shadow_green, 0x00);
        grass_color = RGBtoNum(GRASS_RED, GRASS_GREEN + grass_green, 0x00);            
        tension = this.size / 4;
        tension2 = tension / 16;            
        fact_friction = .95 + (stiffness * .025);            
        resetSpeed();
    }
    public static function rand(n:uint):uint {
        return int(Math.random() * n);
    }
    public static function RGBtoNum(i_r:int,i_g:int,i_b:int):Number{
        return i_r<<16 | i_g<<8 | i_b;
    }        
    public function resetSpeed():void {
        fact_acc = 0;        
        vel = 0;    
    }
    private function applyAnimation(limit:Number):Boolean {
        var diff:Number = limit-wind_force;        
        if (fact_acc == 0){
            fact_acc = 0.5 * (diff < 0 ? -1 : 1);
            fact_acc += (stiffness * .45)
        } else if ((diff > 0 && fact_acc < 0) || (diff < 0 && fact_acc > 0)){                
            fact_acc *= -1;        
        }                
        var old_vel:Number = vel;            
        vel = (vel+fact_acc)*fact_friction;
        if ((vel > 0 && old_vel < 0) || (vel < 0 && old_vel > 0)){
            fact_acc *= .7;
            if (Math.abs(diff) <= 0.65){                    
                return false;
                vel = 0;
            }
        }                
        wind_force += vel;            
        return true;
    }
    public function next(wf:Number, refresh_color:Boolean = false):Boolean {
        if (wf != 0){
            if (status != 1) {
                resetSpeed();                    
                status = 1;
            }
            if (last_wf != wf) {
                last_wf = wf;
                if (fact_acc < .5) {
                    fact_acc += .5;
                }
            }
            returning = true;
            redraw = true;                
            applyAnimation(zero_force + wf);
        } else if (returning) {    
            if (status != 2) {
                resetSpeed();
                status = 2;
            }
            redraw = true;
            returning = applyAnimation(zero_force);
        } else {
            wind_force = zero_force;
            status = 0;
        }    
        if (redraw || refresh_color) {
            if (refresh_color) {
                shadow_color = RGBtoNum(SHADOW_RED, SHADOW_GREEN + shadow_green, 0x00);
                grass_color = RGBtoNum(GRASS_RED, GRASS_GREEN + grass_green, 0x00);
            }
            var canvas:flash.display.Graphics = this.graphics;                
            canvas.clear();                
            var end_x:Number = px+wind_force;
            var end_y:Number = py - size + (Math.abs(wind_force) * Math.abs(wind_force/springiness)*.3);        
            var control_y:Number = tension*stiffness+tension;                
            canvas.beginFill(shadow_color);
            canvas.moveTo(px,py);
            canvas.curveTo(px,control_y,end_x,end_y);
            canvas.curveTo(px+tension2,control_y,px+tension2,py);
            canvas.lineTo(px,py);
            canvas.endFill();
            canvas.beginFill(grass_color);
            canvas.moveTo(px,py);
            canvas.curveTo(px,control_y,end_x,end_y);
            canvas.curveTo(px-tension2*(1+shadow_width),control_y,px-tension2,py);
            canvas.lineTo(px,py);
            canvas.endFill();                
            redraw = wind_force != zero_force;                
            return redraw; 
        }            
        return false;
    }        
}