topical media & game development

talk show tell print

#perlin-landscape.ax

#perlin-landscape.ax [swf] flex


  /*
  
  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 @ax-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 @ax-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);
                  }
          }
  }
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.