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

Tunnel [Optimized]

Optimized a bit source using fast integers and cast calls and done some tidying - there is room still.
Roughly jumped *2 in perfs so far.
Nice one Bruce :)
Hasufel 2012
/**
 * Copyright Hasufel ( http://wonderfl.net/user/Hasufel )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/iNuN
 */

// forked from Bruce_Jawn's Tunnel
/*
Dirty and Slow AS3 Port of http://lodev.org/cgtutor/tunnel.html
by Bruce Jawn (May/20/2012)
http://bruce-lab.blogspot.com

//optimized a bit using fast integers and cast calls - there is room still.
//roughly jumped *2 in perfs so far.
//nice one Bruce :)
//@Hasufel 2012
*/
package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display.StageQuality;
    import flash.events.Event;
    import net.hires.debug.Stats;

    [SWF(width=256, height=256, backgroundColor=0,frameRate=60)]

    public class Tunnel extends Sprite {
        private const texWidth:uint = 256;
        private const texWidth1:uint = texWidth-1;
        private const w2:uint = texWidth*.5;
        private const texHeight:uint = 256;
        private const texHeight1:uint = texHeight-1;
        private const h2:uint = texHeight*.5;
        private const h4:uint = texHeight*.25;
        private var texture:BitmapData;

        //Make the tables twice as big as the screen. The center of the buffers is now the position (w,h).
        private var distanceTable:Array;
        private var angleTable:Array;

        private var buffer:BitmapData;  
        private var animation:uint = 0;
        
        public function Tunnel():void {
            setProps(stage, {quality:StageQuality.LOW,scaleMode:StageScaleMode.NO_SCALE,align:StageAlign.TOP_LEFT, stageFocusRect:false, tabChildren:false});
            texture=new BitmapData(texWidth,texHeight,false,0xffffff);
            texture.perlinNoise(texWidth,texHeight, 4, 95, true, true, 3, false);
            distanceTable=Array2(texWidth<<1,texHeight<<1);
            angleTable=Array2(texWidth<<1,texHeight<<1);
            buffer=new BitmapData(texWidth,texHeight,false,0xffffff);
            init();
        }
        
        private function init():void {
            //generate non-linear transformation table, now for the bigger buffers (twice as big)
            var angle:uint,distance:uint;
            var ratio:Number=32.0;
            for (var x:uint = 0; x < texWidth<<1; x++) {
                for (var y:uint = 0; y < texHeight<<1; y++) {
                    //these formulas are changed to work with the new center of the tables
                    distance = (ratio * texHeight / Math.sqrt((x - texWidth) * (x - texWidth) + (y - texHeight) * (y - texHeight)))>>0 & (texHeight1);
                    angle = (.5 * texWidth * Math.atan2(y - texHeight, x - texWidth) / 3.1416)>>0;
                    distanceTable[x>>0][y>>0]=distance;
                    angleTable[x>>0][y>>0]=angle;
                }
            }
            addChild(new Bitmap(buffer));
            var stats:Stats = new Stats();
            addChild(stats);
            addEventListener(Event.ENTER_FRAME,loop);
        }
        
        private final function loop(e:Event):void {
            //begin the loop
            animation+=5;//0.05;
            //calculate the shift values out of the animation value
            var shiftX:uint=(texWidth*animation)>>7;
            var shiftY:uint=(h4*animation)>>7;//*.25*animation;
            //calculate the look values out of the animation value
            //by using sine functions, it'll alternate between looking left/right and up/down
            //make sure that x + shiftLookX never goes outside the dimensions of the table, same for y
            var shiftLookX:uint=w2+w2*Math.sin(animation/100);
            var shiftLookY:uint=h2+h2*Math.sin(animation*2.0/100);//*2 -> <<1 /2 -> >> 1;
            var color:uint;
            buffer.lock();
            for (var x:uint = 0; x < texWidth; ++x) {
                for (var y:uint = 0; y < texHeight; ++y) {
                    //get the texel from the texture by using the tables, shifted with the animation variable
                    //now, x and y are shifted as well with the "look" animation values
                    color = texture.getPixel((distanceTable[(x + shiftLookX)>>0][(y + shiftLookY)>>0] + shiftX)>>0 & (texWidth1),
                                                   (angleTable[(x + shiftLookX)>>0][(y + shiftLookY)>>0]+ shiftY)>>0 & (texHeight1));
                    buffer.setPixel(x,y,color);
                }
            }
            buffer.unlock();
        }

        private function Array2(gridSize1:int,gridSize2:int):Array {
            var a:Array=new Array(gridSize1);
            for (var i:uint= 0; i < gridSize1; ++i) {
                a[i]=new Array(gridSize2);
                for (var j:uint = 0; j < gridSize2; ++j) {
                    a[i>>0][j>>0]=0;
                }
            }
            return a;
        }

        private function setProps(o:*,p:Object):void {
            for (var k:String in p) o[k]=p[k];
        }

    }
}