Beautifl - Flash Gallery

Thumbnail : Eclipse
Eclipse
makc3d 2009-08-27 see code comments

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

package {
    import flash.display.*;
    import flash.geom.*;
    import flash.filters.*;

    /**
     * The Eclipse.
     * This is quick AS3 port of my old AS2 stuff from '07.
     * See also http://eclipse.gsfc.nasa.gov/SEmono/TSE2009/TSE2009.html
     */
    [SWF(backgroundColor="#000000", frameRate="20")]
    public class Eclipse extends Sprite {
        // magic numbers
        private const H:Number = 465, W:Number = 465;
        private const T2:Number = 100.0, SR:Number = 18.3;
        private const A:Number = (1.0001 * W) / H;
        private const SY:Number = 2.0001 / H, SX:Number = 2.0001 / W;
        private const DY:Number = -30, DX:Number = A * DY;

        // more magic numbers
        private const FadeOut:ColorTransform = new ColorTransform(1, 1, 1, 1, -15, -10, -5, 0);
        private const MixPixels:BlurFilter = new BlurFilter(2, 2, 2);
        private const Origin:Point = new Point (0, 0);
        private const StarCopyMatrix:Matrix = new Matrix (1, 0, 0, 1, (W + 1)*0.5, (H + 1)*0.5);
        private const ScaleMatrix:Matrix = new Matrix(1 - SX * DX, 0, 0, 1 - SY * DY, DX /* hack: */-0.3, DY);

        private var T:Number = 0, starShineR:Number = 18;
        private var star:Sprite = new Sprite;
        private var starShine:Shape = new Shape;
        private var starMask:Shape = new Shape;
        private var starBitmap:Bitmap = new Bitmap;
        private var starBitmapData:BitmapData = new BitmapData (W, H, true, 0xFF000000);
        private var starBitmapData2:BitmapData = new BitmapData (W, H, true);
        private var skyPatch:Sprite = new Sprite;
        private var skyStars:Shape = new Shape;
        private var skyColor:Shape = new Shape;

        public function Eclipse () {
            // init all the stuff
            star.addChild (starShine); starShine.x = starShine.y = -20;
            star.addChild (starMask);
            starMask.graphics.beginFill (0); starMask.graphics.drawCircle (0, 0, 20); starMask.graphics.endFill ();
            starShine.mask = starMask;
            starBitmap.bitmapData = starBitmapData;
            addChild (starBitmap); addChild (skyPatch);
            skyPatch.addChild (skyStars); drawStars ();
            skyPatch.addChild (skyColor);
            skyColor.graphics.beginFill (0x1580); skyColor.graphics.drawRect (0, 0, W, H); skyColor.graphics.endFill ();
            skyStars.alpha = skyColor.alpha = 0;
            skyColor.blendMode = "lighten";

            addEventListener ("enterFrame", onEnterFrame);
        }

        private function onEnterFrame (e:*):void {
            // advance "time"
            T++;

            var dX:Number = 0;
            if (T < T2) {
                // this formula was probably supposed to be
                // independent of T2, but it is not :((
                dX = 20.5 / T2 * Math.sqrt(2) * (T2 - 1 - T);
            }

            if ((T > T2 * 0.8) && (skyColor.alpha > 0)) {
                // get rid of minimal color constraint, lit up damn stars
                skyColor.alpha -= 4 / T2; skyStars.alpha += 6 / T2;
            }

            if (T > T2 * 0.95) {
                // darken the sky after the eclipse by growing the moon
                if (starShineR < SR) starShineR += 4 / T2;
            }

            // draw star and moon
            starShine.graphics.clear();
            starShine.graphics.beginFill (0xFFFFFF);
            starShine.graphics.drawCircle (20, 20, 20);
            starShine.graphics.drawCircle (20 + dX, 20 + 0.3 * dX, starShineR);
            starShine.graphics.endFill ();

            // decide on filtering passes number
            var PassN:Number = 0;
            if (T == 1) {
                // initial moment
                PassN = 40; skyColor.alpha = 1;
            } else if ((T > T2 - 10) && (starShineR < SR)) {
                // try to avoid fire-like effect at eclipse first moments
                if (PassN < 30) PassN += 3;
            } else {
                // default
                PassN = 1;
            }

            // apply radial filtering
            for (var i:int = 0; i < PassN; i++) {
                starBitmapData.draw(star, StarCopyMatrix)
                starBitmapData2.applyFilter(starBitmapData, starBitmapData.rect, Origin, MixPixels);
                starBitmapData.draw(starBitmapData2, ScaleMatrix, FadeOut, "normal", starBitmapData.rect);
            }
        }

        private function drawStars ():void {
            // star helper (could be done with Bitmap/noise, I think)
            for (var z:int = 0; z < 100; z++) {
                var xp:Number = W * Math.random (), yp:Number = H * Math.random ();
                var p:Point = new Point (xp - W/2, yp - H/2); if (p.length > 20 + 40) {
                    skyStars.graphics.lineStyle(1, 0x8F8FFF, 50 + 50 * Math.random ());
                    skyStars.graphics.moveTo (xp, yp); skyStars.graphics.lineTo (xp +1, yp);
                }
            }
        }
    }
}