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];
}
}
}