Kolejny sympatyczny efekt, wykorzystywany bardzo często w produkcjach demosceny to tunel. W milionach różnych wersji, wyewoluował od całkiem prostej realizacji rysowanych okręgów do hiper-super-triple teksturowanego tunelu z dynamicznym oświetleniem, cieniami i bajerami.
Realizacja tego efektu we flashu jest jak najbardziej możliwa. Sprawa wygląda prosto:
package { import flash.display.Sprite; import flash.events.Event; import flash.display.BitmapData; import flash.display.Bitmap; import flash.display.StageAlign; import flash.display.StageScaleMode; [SWF(width="500", height="500", backgroundColor="0x000000")] public class TunnelEfect extends Sprite { private var w:int = 250; private var h:int = 250; private var texWidth:int = 256; private var texHeight:int = 256; private var texture:Array = new Array(texWidth); private var distanceTable:Array = new Array(w * 2); private var angleTable:Array = new Array(w * 2); private var animationShift:Number = 0; private var bitmap:BitmapData = new BitmapData(w * 2, h * 2, false, 0x000000); public function TunnelEfect() { var angle:int, distance:int, ratio:Number = 32; this.stage.scaleMode = StageScaleMode.NO_SCALE; this.stage.align = StageAlign.TOP_LEFT; this.stage.frameRate = 20; this.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); this.addChild(new Bitmap(bitmap)); for(var x:int = 0; x < texWidth; x++) { texture[x] = new Array(texHeight); for(var y:int = 0; y < texHeight; y++) { texture[x][y] = ((x) ^ (y)) * 256; } } for(x = 0; x < w * 2; x++) { distanceTable[x] = new Array(h * 2); angleTable[x] = new Array(h * 2); for(y = 0; y < h * 2; y++) { distance = (ratio * texHeight / Math.sqrt(((x - w) * (x - w) + (y - h) * (y - h)))) % texHeight; angle = Math.abs(0.5 * texWidth * Math.atan2((y - h), (x - w)) / 3.1416); distanceTable[x][y] = distance; angleTable[x][y] = angle; } } } private function draw():void { var shiftX:int, shiftY:int, shiftLookX:int, shiftLookY:int, color:Number; shiftX = (texWidth * 1.0 * animationShift); shiftY = (texHeight * 0.25 * animationShift); shiftLookX = w / 2 + (w / 2 * Math.cos(animationShift)); shiftLookY = h / 2 + (h / 2 * Math.sin(animationShift * 2.0)); for(var x:int = 0; x < w; x++) { for(var y:int = 0; y < h; y++) { color = texture[Math.abs(distanceTable[x + shiftLookX][y + shiftLookY] + shiftX) % texWidth][Math.abs(angleTable[x + shiftLookX][y + shiftLookY] + shiftY) % texHeight]; bitmap.setPixel(x * 2, y * 2, color); } } } private function onEnterFrame(e:Event):void { draw(); animationShift += 0.05; } } } |
A oto i gotowy tunel: