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

Chapter 38 Example 3

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

package {
  import flash.display.*;
  import flash.events.*;
  import flash.geom.*;
  import flash.net.*;
  public class ch38ex3 extends Sprite {
    protected const URL_BASE:String = "http://actionscriptbible.com/files/";
    protected const INITIAL_PARTICLES:int = 1000;
    protected const WELL_GRAVITY_MAX:Number = 5000;
    protected var W:int, H:int; 

    protected var generatorShader:Shader;
    protected var stepShader:Shader;
    protected var forcemap:BitmapData;
    protected var particleData:Vector.<Number>; //4 channels: px,py,vx,vy
    
    protected var bmp:BitmapData;
    protected var bitmap:Bitmap;
    protected const DIM:ColorTransform = new ColorTransform(.9, .9, .9, .95);
    public function ch38ex3() {
      stage.frameRate = 60;
      loadShader("GravitySimGenerateMap.pbj", onGeneratorShaderReady);
    }
    protected function loadShader(url:String, onComplete:Function):void {
      var loader:URLLoader = new URLLoader(new URLRequest(URL_BASE + url));
      loader.dataFormat = URLLoaderDataFormat.BINARY;
      loader.addEventListener(Event.COMPLETE, onComplete);
    }
    protected function onGeneratorShaderReady(event:Event):void {
      event.target.removeEventListener(Event.COMPLETE, onGeneratorShaderReady);
      generatorShader = new Shader(URLLoader(event.target).data);
      
      forcemap = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0);
      W = forcemap.width; H = forcemap.height;
      var forceBitmap:Bitmap = new Bitmap(forcemap);
      addChild(forceBitmap);
      bmp = new BitmapData(W, H, false, 0);
      bitmap = new Bitmap(bmp);
      addChild(bitmap);
      bitmap.alpha = .99;
      
      initializeParticles();
      initializeWells();
      loadShader("GravitySimStep.pbj", onStepReady);
    }
    protected function onStepReady(event:Event):void {
      event.target.removeEventListener(Event.COMPLETE, onGeneratorShaderReady);
      stepShader = new Shader(URLLoader(event.target).data);
      
      stage.addEventListener(MouseEvent.CLICK,
        function(event:Event):void{initializeParticles()});
      stage.addEventListener(KeyboardEvent.KEY_UP,
        function(event:Event):void{initializeWells()});
      addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }
    protected function initializeParticles():void {
      var r:Function = Math.random;
      particleData = new Vector.<Number>();
      for (var i:int = 0; i < INITIAL_PARTICLES; i++) {
        particleData.push(r()*W, r()*H, (r()-0.5)*4, (r()-0.5)*4);
      }
    }
    protected function initializeWells():void {
      var r:Function = Math.random;
      var data:ShaderData = generatorShader.data;
      data.power.value = [1.4];
      data.star0.value = [r()*W/2 + W/4, r()*H/2 + H/4, r()*WELL_GRAVITY_MAX];
      data.star1.value = [r()*W/2 + W/4, r()*H/2 + H/4, r()*WELL_GRAVITY_MAX];
      var shaderJob:ShaderJob = new ShaderJob(generatorShader, forcemap);
      shaderJob.start(true);
    }
    protected function step():void {
      var data:ShaderData = stepShader.data;
      data.forcemap.input = forcemap;
      data.inpoints.input = particleData;
      data.inpoints.height = 1;
      data.inpoints.width = particleData.length/4;
      var shaderJob:ShaderJob = new ShaderJob(stepShader, particleData, 
        particleData.length/4, 1);
      shaderJob.start(true);
    } 
    protected function draw():void {
      bmp.colorTransform(bmp.rect, DIM);
      bmp.lock();
      for (var i:int = 0; i < particleData.length; i+=4) {
        bmp.setPixel(particleData[i], particleData[i+1], 0xffffff);
      }
      bmp.unlock();
    }
    protected function onEnterFrame(event:Event):void {
      step();
      draw();
    }
  }
}

/***********************
<languageVersion : 1.0;>
kernel GravitySimGenerateMap
< namespace : "com.actionscriptbible";
  vendor : "ActionScript 3.0 Bible";
  version : 1;
  description : "Generates a force map from two stars";
>
{
  parameter float3 star0;
  parameter float3 star1;
  parameter float power <defaultValue: float(2.0);>;
  input image4 src;
  output pixel4 dst;

  void evaluatePixel() {
    float2 point = outCoord();
    float2 totalForce = float2(0.0);
    float2 force;
    float dist;

    //unrolled loop iteration 0
    force = star0.xy - point;
    dist = length(force);
    force = normalize(force);
    force *= star0.z / (pow(dist, power));
    totalForce += force;
    //unrolled loop iteration 1
    force = star1.xy - point;
    dist = length(force);
    force = normalize(force);
    force *= star1.z / (pow(dist, power));
    totalForce += force;

    totalForce = clamp(totalForce, -100.0, 100.0) + 100.0;
    totalForce /= 200.0;
    
    dst = pixel4(0.0, 0.0, 0.0, 1.0);
    dst.rg = totalForce.xy;
  }
}
************************************
<languageVersion : 1.0;>
kernel GravitySimStep
< namespace : "com.actionscriptbible";
  vendor : "ActionScript 3.0 Bible";
  version : 1;
  description : "Gravity simulation step";
>
{
  parameter float2 scale <defaultValue: float2(1.0, 1.0);>;
  input image3 forcemap;
  input image4 inpoints;
  output pixel4 outpoint;

  void evaluatePixel() {
    //each input pixel represents a point mass (particle) with mass=1
    //inpoint.XY = <x, y> position
    //inpoint.ZW = <x, y> velocity
    float4 particle = sampleNearest(inpoints, outCoord());
    //the forcemap at a pixel stores the force vector at that point
    //forcemap[x, y].RG = <x, y> force vector (normalized... 0.5 = 0)
    float2 force = sampleNearest(forcemap, particle.xy).rg;
    force = (force - float2(0.5)) * scale;
    float2 velocity = particle.zw + force;
    float2 position = particle.xy + velocity;
    
    outpoint.xy = position;
    outpoint.zw = velocity;
  }
}
**************************************/