/* Written by: Dustin Andrew dustin@flash-dev.com www.flash-dev.com */ package { import flash.media.Camera; import flash.media.Video; import flash.display.*; import flash.geom.*; import flash.filters.*; import flash.events.*; import flash.net.*; import flash.ui.*; public class perlin_landscape extends Sprite { private var vid:Video; private var _bmpPerl:BitmapData; // BitmapData that will hold the perlin noise private var _numPerlW:Number = 200; // Perlin noise width private var _numPerlH:Number = 200; // Perlin noise height private var _numGridW:Number = 16; // Tile grid width private var _numGridH:Number = 16; // Tile grid height private var _sprTiles:Sprite; // Sprite that will hold all the tiles private var _numTileW:Number = 25; // Tile width private var _numTileH:Number = 12; // Tile height private var _arrBaseY:Array; // Array to record each tile's base y private var _numMoveX:Number = 0; // X offset for perlin noise private var _numMoveY:Number = 0; // Y offset for perlin noise private var _numMoveSX:Number; // Speed that x offset increments by private var _numMoveSY:Number; // Speed that y offset increments by private var _numColor:Number; // Tile Color private var _menuDLSource:ContextMenu; // Right-click menu for downloading source // Constructor public function perlin_landscape() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; // Create bitmapdata to draw perlin noise on //vid = new Video(); //vid.attachCamera(Camera.getCamera()); _bmpPerl = new BitmapData(_numPerlW, _numPerlH, false, 0); // Uncomment this if you want to see the perlin noise var bmp:Bitmap = new Bitmap(_bmpPerl); //_bmpPerl.addChild(vid); this.addChild(bmp); _sprTiles = new Sprite(); //_sprTiles.addChild(vid); _sprTiles.cacheAsBitmap = true; createTiles(); // Center tiles _sprTiles.x = (stage.stageWidth / 2) - _numTileH; _sprTiles.y = stage.stageHeight / 3; this.addChild(_sprTiles); // Start with random values onMouseDown(new Event("")); // Add eventlisteners this.addEventListener("enterFrame", onEnterFrame); this.addEventListener("mouseDown", onMouseDown); // Add right-click menu to download source createSourceLink(); } // Called to create tiles based on grid width and height private function createTiles():void { // Rows _arrBaseY = new Array(); for (var r:Number = 0; r < _numGridH; r++) { // Columns _arrBaseY.push(new Array()); for (var c:Number = 0; c < _numGridW; c++) { var shpTile:Shape = new Shape(); //var shpTile:Sprite = new Sprite(); //shpTile.addChild(vid); shpTile.name = "tile_" + r + "_" + c; drawTile(shpTile); // Line up tiles from back to front if (c > 0) { shpTile.x = shpLast.x - (shpLast.width / 2); shpTile.y = shpLast.y + (shpLast.height / 2); } else { shpTile.x = (shpTile.width / 2) * r; shpTile.y = (shpTile.height / 2) * r; } // Record last added tile var shpLast:Shape = shpTile; _sprTiles.addChild(shpTile); // Record base y _arrBaseY[r].push(shpTile.y); } } } // Called to draw tile graphic based on tile width and height private function drawTile(shpTile:Shape):void { shpTile.graphics.clear(); shpTile.graphics.moveTo(0, _numTileH / 2); shpTile.graphics.beginFill(_numColor, 1); shpTile.graphics.lineTo(_numTileW / 2, 0); shpTile.graphics.lineTo(_numTileW, _numTileH / 2); shpTile.graphics.lineTo(_numTileW / 2, _numTileH); shpTile.graphics.lineTo(0, _numTileH / 2); shpTile.graphics.endFill(); } // Called on mouse down to randomize x,y speed and color private function onMouseDown(event:Event):void { _numMoveSX = (Math.random() * 25) - 12; _numMoveSY = (Math.random() * 25) - 12; _numColor = Math.random() * 0xFFFFFF; } // Called on enter frame to update perlin noise and y of each tile private function onEnterFrame(event:Event):void { // Create perlin noise based on current x,y offset _bmpPerl.perlinNoise(175, 175, 1, 333, false, false, 7, true, new Array(new Point(_numMoveX, _numMoveY))); // Rows for (var r:Number = 0; r < _numGridH; r++) { // Columns for (var c:Number = 0; c < _numGridW; c++) { var shpTile:Shape = _sprTiles.getChildByName("tile_" + r + "_" + c) as Shape; // We get the color of the perlin noise at the general pixel location that // the tile is, based in the tile grid. We then bring that color number down to // a size that we can work with. In this instance, it gives us a range from around // 0 to 75, thats what gives us the y offset. var numSetY:Number = _bmpPerl.getPixel((_numPerlW / _numGridW) * c, (_numPerlH / _numGridH) * r) / 100000; // Affect tile alpha and tint based on y offset shpTile.y = _arrBaseY[r][c] + (numSetY * -1); var colTrans:ColorTransform = new ColorTransform(); var numTint:Number = (numSetY * .01) + .4; colTrans.color = _numColor; colTrans.blueMultiplier = numTint; colTrans.greenMultiplier = numTint; colTrans.redMultiplier = numTint; colTrans.alphaMultiplier = numTint; var trans:Transform = new Transform(shpTile); trans.colorTransform = colTrans; // Create a drop shadow thats distance and blur is affected by the tile's y offset var numBlur:Number = numSetY * .05; var filShad:DropShadowFilter = new DropShadowFilter(numSetY * .8, 90, _numColor, .5, numBlur, numBlur * 2, 1, 1, false, false, false); shpTile.filters = new Array(filShad); } } // Increment x,y offset based on x,y offset _numMoveX -= _numMoveSX; _numMoveY -= _numMoveSY; } // Called to add right-click menu option to download source private function createSourceLink():void { _menuDLSource = new ContextMenu(); var menuDL:ContextMenuItem = new ContextMenuItem("Download Source"); menuDL.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, downloadSource); _menuDLSource.customItems.push(menuDL); this.contextMenu = _menuDLSource; } // Called to download source private function downloadSource(event:ContextMenuEvent):void { var reqUrl:URLRequest = new URLRequest("PerlinLandscape.zip"); navigateToURL(reqUrl); } } }