topical media & game development

talk show tell print

actionscript-book-SpinningMoon-com-example-programmingas3-moon-MoonSphere.ax

actionscript-book-SpinningMoon-com-example-programmingas3-moon-MoonSphere.ax [swf] flex


  package 
  {
          import flash.display.Bitmap;
          import flash.display.BitmapData;
          import flash.display.BitmapDataChannel;
          import flash.display.Loader;
          import flash.display.Shape;
          import flash.display.Sprite;
          import flash.events.Event;
          import flash.events.TimerEvent;
          import flash.filters.BitmapFilterQuality;
          import flash.filters.DisplacementMapFilter;
          import flash.filters.GlowFilter;
          import flash.geom.Point;   
          import flash.geom.Rectangle;
          import flash.net.URLRequest;
          import flash.utils.Timer;
          
          public class @ax-actionscript-book-SpinningMoon-com-example-programmingas3-moon-MoonSphere extends Sprite 
          {
                  // The Bitmap containing the moon map that's actually displayed on the screen.
                  private var sphere:Bitmap;
                  
                  // The moon map "source" -- pixels from this map are copied onto sphere
                  // to create the animated motion of the moon.
                  private var textureMap:BitmapData;
                  
                  // The radius of the moon.
                  private var radius:int;
                  
                  // The current x position on textureMap from which the pixels are copied onto sphere.
                  private var sourceX:int = 0;
                  
                  // @ax-actionscript-book-SpinningMoon-com-example-programmingas3-moon-MoonSphere constructor
                  // Starts loading the moon image.
                  public function @ax-actionscript-book-SpinningMoon-com-example-programmingas3-moon-MoonSphere() 
                  {
                          var imageLoader:Loader = new Loader();
                          imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadComplete);
                          imageLoader.load(new URLRequest("actionscript-book-SpinningMoon-moonMap.png"));
                  }
                  
                  // Movement (a'la rotation) routine
                  private function rotateMoon(event:TimerEvent):void
                  {
                          sourceX += 1;
                          if (sourceX >= textureMap.width / 2)
                          {
                                  sourceX = 0;
                          }
                          
                          sphere.bitmapData.copyPixels(textureMap,
                                                                                                    new Rectangle(sourceX, 0, sphere.width, sphere.height),
                                                                                                    new Point(0, 0));
                          
                          event.updateAfterEvent();
                  }
                  
                  // Creates the displacement map image that's used to create the fisheye lens effect
                  private function createFisheyeMap(radius:int):BitmapData
                  {
                          var diameter:int = 2 * radius;
                          
                          var result:BitmapData = new BitmapData(diameter,
                                                                                                                                  diameter,
                                                                                                                                  false,
                                                                                                                                  0x808080);
                          
                          // Loop through the pixels in the image one by one
                          for (var i:int = 0; i < diameter; i++)
                          {
                                  for (var j:int = 0; j < diameter; j++)
                                  {
                                          // Calculate the x and y distances of this pixel from
                                          // the center of the circle (as a percentage of the radius).
                                          var pctX:Number = (i - radius) / radius;
                                          var pctY:Number = (j - radius) / radius;
                                          
                                          // Calculate the linear distance of this pixel from
                                          // the center of the circle (as a percentage of the radius).
                                          var pctDistance:Number = Math.sqrt(pctX * pctX + pctY * pctY);
                                          
                                          // If the current pixel is inside the circle,
                                          // set its color.
                                          if (pctDistance < 1)
                                          {
                                                  // Calculate the appropriate color depending on the
                                                  // distance of this pixel from the center of the circle.
                                                  var red:int;
                                                  var green:int;
                                                  var blue:int;
                                                  var rgb:uint;
                                                  red = 128 * (1 + 0.75 * pctX * pctX * pctX / (1 - pctY * pctY));
                                                  green = 0;
                                                  blue = 0;
                                                  rgb = (red << 16 | green << 8 | blue);
                                                  // Set the pixel to the calculated color.
                                                  result.setPixel(i, j, rgb);
                                          }
                                  }
                          }
                          return result;
                  }
                  
                  // Called when the moon map image finishes loading.
                  // Sets up the on-screen elements (moon image with fisheye filter and its mask);
                  // starts the Timer that creates the animation effect.
                  private function imageLoadComplete(event:Event):void
                  {
                          textureMap = event.target.content.bitmapData;
                          radius = textureMap.height / 2;
                          
                          sphere = new Bitmap();
                          sphere.bitmapData = new BitmapData(textureMap.width / 2, textureMap.height);
                          sphere.bitmapData.copyPixels(textureMap,
                                                                                                    new Rectangle(0, 0, sphere.width, sphere.height),
                                                                                                    new Point(0, 0));
  
                          // Create the BitmapData instance that's used as the displacement map image
                          // to create the fisheye lens effect.
                          var fisheyeLens:BitmapData = createFisheyeMap(radius);
                          
                          // Create the fisheye filter
                          var displaceFilter:DisplacementMapFilter;
                          displaceFilter = new DisplacementMapFilter(fisheyeLens,
                                                                                                                                           new Point(radius, 0), 
                                                                                                                                           BitmapDataChannel.RED,
                                                                                                                                           BitmapDataChannel.BLUE,
                                                                                                                                           radius, 0);
                          
                          // Apply the filter
                          sphere.filters = [displaceFilter];
  
                          this.addChild(sphere);        
          
                          // Create and apply the image mask
                          var moonMask:Shape = new Shape();
                          moonMask.graphics.beginFill(0);
                          moonMask.graphics.drawCircle(radius * 2, radius, radius);
                          this.addChild(moonMask);
                          this.mask = moonMask;
                          
                          // Set up the timer to start the animation that 'spins' the moon
                          var rotationTimer:Timer = new Timer(15);
                          rotationTimer.addEventListener(TimerEvent.TIMER, rotateMoon);
                          rotationTimer.start();
                          
                          // add a slight atmospheric glow effect
                          this.filters = [new GlowFilter(0xC2C2C2, .75, 20, 20, 2, BitmapFilterQuality.HIGH, true)];
                          
                          dispatchEvent(event);
                  }
          }
  }


(C) Æliens 27/08/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.