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

Particles in a perlin field

Space to render a new perlin heightmap and to launch new particles (and remove the current ones).

The sliders change: 

Height - how much the particles is affected by the heightmap. Zero means no effect at all; higher values equals more powerful reaction (try it for yourselves!)

Count - The number of particles (duh)

Speed - The speed in which the particles travel (pixels per frame)
/**
 * Copyright antalg ( http://wonderfl.net/user/antalg )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/duDT
 */

package {
    import flash.events.KeyboardEvent;
    import flash.text.TextField;
    import flash.utils.ByteArray;
    import flash.geom.Rectangle;
    import flash.filters.ColorMatrixFilter;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import flash.filters.BlurFilter;
    import flash.events.Event;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    
    import com.bit101.components.HUISlider;
    
    [SWF(backgroundColor="0x000000")]    
    
    public class FlashTest extends Sprite {
        public function FlashTest() {
            // Assign main bitmapData to bitmap and add it to stage
            addChild(new Bitmap(_canvas));
            
            // Add heightmap to stage
            //addChild(new Bitmap(_hmap));
            
            // Set-up event listeners
            addEventListener(Event.ENTER_FRAME, onFrame);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
            
            // Set-up sliders
            _sliderHeight = new HUISlider (null, 0, 0, "Height", updSlider);
            _sliderHeight.setSliderParams(0, 1, _slopeAdjust);
            _sliderHeight.labelPrecision = 2;
            _sliderHeight.width = 300;
            addChild(_sliderHeight);
            
            _sliderCount = new HUISlider (null, 0, 0, "Count", updSlider);
            _sliderCount.setSliderParams(1, 3000, _particleCount);
            _sliderCount.labelPrecision = 0;
            _sliderCount.tick = 1;
            _sliderCount.width = 300;
            _sliderCount.y = 20;
            addChild(_sliderCount);
            
            _sliderSpeed= new HUISlider (null, 0, 0, "Speed", updSlider);
            _sliderSpeed.setSliderParams(0, 30, _baseV);
            _sliderSpeed.width = 300;
            _sliderSpeed.y = 40;
            addChild(_sliderSpeed);
            
            // Trace textField
            addChild(txt);
            txt.textColor = 0xFF2222;
            txt.x = 4;       
            txt.y = 440;
            
            // The first rendering
            renderNew();
        }
        
        private var txt:TextField = new TextField();
        
        private var _sliderHeight:HUISlider;
        private var _sliderCount:HUISlider;
        private var _sliderSpeed:HUISlider;
        
        private var _particleCount:int = 700;
        private var _particles:Array;
        private var _particleColor:Array = [0xFF8888, 0x88FF88, 0x8888FF, 0xFFFFFF];
        private var _slopeAdjust:Number = 0.1;
        private var _baseV:Number = 4;
        
        private const HGT:Number = 465;
        private const WDT:Number = 465;
        private var _canvas:BitmapData = new BitmapData(WDT, HGT, false, 0x000000);
        private var _hmap:BitmapData = new BitmapData(WDT, HGT, true, 0x000000);
        
        private function renderNew():void {
            _particles = new Array();
            
            addParticles(_particleCount);
            _hmap.perlinNoise(100,100,2,Math.random()*int.MAX_VALUE, true, true, 0xFFFFFF, true);
        }
        
        // Event functions
        private function keyDown(e:KeyboardEvent):void {
            if(e.keyCode == 32) renderNew();
        }
        
        private function updSlider(e:*):void {
            // Active setting, affects without reset
            _slopeAdjust = _sliderHeight.value;
            _baseV = _sliderSpeed.value;
            
            // Requires reset
            if(_particleCount != _sliderCount.value) {
                _particleCount = _sliderCount.value;
                renderNew();
            }
        }
        
        private function onFrame(e:Event):void {
            move();
            processBMD();
            
            if(txt.alpha>0) {
                txt.alpha -= 0.01;
            }
        }
        
        private function addParticles(n:int):void {
            var x:Number;
            var y:Number;
            var vx:Number;
            var vy:Number;
            var angle:Number;
            
            for(var i:int = 0; i<n; i++) {
                angle = 2*Math.PI*Math.random();
                vx = Math.cos(angle)*_baseV;
                vy = Math.sin(angle)*_baseV;
                
                x = Math.random()*WDT;
                y = Math.random()*HGT;
                
                var p:Object = {x:x, y:y, v:new Point(vx,vy)};              
                
                _particles.push(p);
            }
        }
        
        ////////////////////////
        
        private function move():void {
            for(var i:int = 0; i<_particles.length; i++) {
                var p:Object = _particles[i];
                
                // Calculate slope at point
                var slope:Point = calcSlope(p.x, p.y);
                
                // Update speed and position
                p.x += (p.v.x+=slope.x);
                p.y += (p.v.y+=slope.y);
                
                // Keep a constant speed
                p.v.normalize(_baseV);
                
                // Wrap around
                p.x = p.x<0 ? (p.x+WDT) : (p.x>WDT ? (p.x-WDT) : p.x);
                p.y = p.y<0 ? (p.y+HGT) : (p.y>HGT ? (p.y-HGT) : p.y);
                
                //var r:int = Math.random()*3.0+1;
                var r:int = i%_particleColor.length;
                
                //_canvas.fillRect(new Rectangle(p.x,p.y,2,2), _particleColor[r]);
                _canvas.setPixel(p.x, p.y, _particleColor[r]);
            }
        }
        
        private var bf:BlurFilter = new BlurFilter(2,2,1);
        private var cmf:ColorMatrixFilter = new ColorMatrixFilter(
            [  1,  0,  0,  0,  0,
               0,  1,  0,  0,  0,
               0,  0,  1,  0,  0,
               0,  0,  0, .98,  0]
        );
        
        private function processBMD():void {
            _canvas.applyFilter(_canvas, _canvas.rect, new Point(0,0), bf);
            _canvas.applyFilter(_canvas, _canvas.rect, new Point(0,0), cmf);
        }
        
        private function calcSlope(x:int, y:int):Point {
            var slope:Point = new Point();
            
            var rect:Rectangle = new Rectangle(x-1, y-1, 3, 3);
            
            var p:Array =
            [_hmap.getPixel(x-1, y-1)>>16, _hmap.getPixel(x, y-1)>>16, _hmap.getPixel(x+1, y-1)>>16,
             _hmap.getPixel(x-1, y)>>16,   _hmap.getPixel(x, y)>>16,   _hmap.getPixel(x+1, y)>>16,
             _hmap.getPixel(x-1, y+1)>>16, _hmap.getPixel(x, y+1)>>16, _hmap.getPixel(x+1, y+1)>>16];
            
            slope.x = p[0]+p[3]+p[6]-(p[2]+p[5]+p[8]);
            slope.y = p[0]+p[1]+p[2]-(p[6]+p[7]+p[8]);
            
            slope.x*=_slopeAdjust;
            slope.y*=_slopeAdjust;
            
            return slope;
        }
    }
}