In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Cloud Flying

Get Adobe Flash player
by bradsedito 03 Feb 2011
/**
 * Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/8LC9
 */





package  {
    import flash.display.*;
    import flash.events.*;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
    import net.hires.debug.Stats;
    import org.papervision3d.core.geom.renderables.Triangle3D;
    import org.papervision3d.core.geom.renderables.Vertex3D;
    import org.papervision3d.core.geom.TriangleMesh3D;
    import org.papervision3d.core.math.Number3D;
    import org.papervision3d.core.math.NumberUV;
    import org.papervision3d.core.proto.MaterialObject3D;
    import org.papervision3d.materials.ColorMaterial;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.Papervision3D;
    import org.papervision3d.view.BasicView;
    
    [SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "#000000")]
    public class Clouds extends Sprite {
        /**雲の数*/
        public const CLOUD_NUM:int = 120;
        /**雲画像のパターン数*/
        public const PATTERN_NUM:int = 35;
        /**雲のサイズ*/
        public const CLOUD_SIZE:Rectangle = new Rectangle(0, 0, 400, 200);
        /**perlinNoiseに使うとまずいシード値(画像に穴があくかもしれない)*/
        public const ERROR_SEEDS:Array = [346, 514, 1155, 1519, 1690, 1977, 2327, 2337, 2399, 2860, 2999, 3099, 4777, 4952, 5673, 6265, 7185, 7259, 7371, 7383, 7717, 7847, 8032, 8350, 8676, 8963, 8997, 9080, 9403, 9615, 9685];
        
        public const PI:Number = Math.PI / 180;
        public var loading:LoadingScene;
        public var cameraCtrl:CameraController;
        public var view:BasicView;
        public var horizonTarget:DisplayObject3D;
        public var airplane:TriangleMesh3D;
        public var canvas1:BitmapData;
        public var canvas2:BitmapData;
        public var bg:BackGround;
        public var ground:Sprite;
        public var clouds:Vector.<Cloud> = new Vector.<Cloud>();
        public var drawObjects:Vector.<Cloud> = new Vector.<Cloud>();
        public var cloudImages:Vector.<BitmapData> = new Vector.<BitmapData>();
        public var clearColor:ColorTransform = new ColorTransform(1, 1, 1, 0);
        
        public function Clouds() {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            Display.setSize(465, 465);
            stage.frameRate = 60;
            stage.quality = "low";
            Papervision3D.PAPERLOGGER.unregisterLogger(Papervision3D.PAPERLOGGER.traceLogger);
            
            view = new BasicView(Display.width, Display.height, false, false, "Free");
            horizonTarget = view.scene.addChild(new DisplayObject3D());
            horizonTarget.autoCalcScreenCoords = true;
            addChild(Painter.createGradientRect(Display.width, Display.height, [Color.sky1], [1]));
            ground = Painter.createGradientRect(Display.width, Display.height, [Color.ground], [1]);
            bg = new BackGround();
            bg.x = Display.center.x;
            bg.mask = addChild(Painter.createGradientRect(Display.width, Display.height, [0x000000], [1]));
            canvas1 = new BitmapData(Display.width, Display.height, true, 0x00FFFFFF);
            canvas2 = new BitmapData(Display.width, Display.height, true, 0x00FFFFFF);
            loading = new LoadingScene();
            
            //色々配置
            addChild(ground);
            addChild(bg);
            addChild(new Bitmap(canvas1));
            addChild(view.viewport);
            addChild(new Bitmap(canvas2));
            addChild(new Stats({bg:0x808080, fps:0xFFFFFF})).blendMode = BlendMode.OVERLAY;
            addChild(loading);
            
            //雲生成
            for (var i:int = 0; i < CLOUD_NUM; i++) {
                var cloud:Cloud = new Cloud();
                clouds.push(cloud);
                cloud.setPosition(Math.random() * 3500 - 1750, Math.random() * -300 + 9000, Math.random() * 4000 - 2000);
            }
            
            //飛行機生成
            airplane = createAirplane();
            airplane.y = 10000;
            airplane.autoCalcScreenCoords = true;
            view.scene.addChild(airplane);
            
            //カメラ初期化
            cameraCtrl = new CameraController();
            cameraCtrl.init(view.scene, view.camera);
            
            //雲画像生成開始
            addEventListener(Event.ENTER_FRAME, onLoading);
        }
        
        //航空機モデルを生成
        private function createAirplane():TriangleMesh3D {
            var scale:Number = 0.1;
            var vts:Array = [
          ];
            var ids:Array = [
                ];
            var material:MaterialObject3D = new ColorMaterial(Color.planeSkin, 1);
            var mesh:TriangleMesh3D = new TriangleMesh3D(material, [], []);
            var vertexes:Array = [];
            for each (var vt:Array in vts) vertexes.push(new Vertex3D(vt[0]*scale, vt[1]*scale, vt[2]*scale));
            for each (var id:Array in ids) mesh.geometry.faces.push(new Triangle3D(mesh, [vertexes[id[0]], vertexes[id[1]], vertexes[id[2]]], null, [new NumberUV(), new NumberUV(), new NumberUV()]));
            mesh.geometry.vertices = vertexes;
            mesh.geometry.ready = true;
            return mesh;
        }
        
        //雲画像生成中
        private function onLoading(...arg):void {
            for (var i:int = 0; i < 3; i++) {
                if(cloudImages.length >= PATTERN_NUM){
                    start();
                    break;
                }
                var seed:int = Math.random() * 10000 + 1;
                if (ERROR_SEEDS.indexOf(seed) >= 0) seed++;
                var ct:Number = (Math.random() < 0.3)? Math.random() * 0.3 : Math.random() * 1.5;
                cloudImages.push(Painter.createCloud(CLOUD_SIZE.width, CLOUD_SIZE.height, seed, ct, Color.cloudBase, Color.cloudLight, Color.cloudShadow));
                loading.setProgress(cloudImages.length / PATTERN_NUM);
            }
        }
        
        //レンダリング開始
        private function start():void {
            removeEventListener(Event.ENTER_FRAME, onLoading);
            removeChild(loading);
            var index:int = -1;
            for each (var cloud:Cloud in clouds) {
                index = ++index % cloudImages.length;
                cloud.image = cloudImages[index];
            }
            stage.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void {
                cameraCtrl.switchCamera();
            });
            Time.start();
            addEventListener(Event.ENTER_FRAME, onEnter);
            onEnter(null);
        }
        
        //毎フレーム処理
        private function onEnter(e:Event):void {
            var c:Cloud;
            Time.update();
            var time:int = Time.count;
            
            //飛行機を傾ける
            airplane.rotationZ = Math.sin(PI * time / 150) * 30;
            
            //カメラ位置更新
            cameraCtrl.setAirplaneRoll(airplane.rotationZ);
            cameraCtrl.update();
            
            //地平線用ダミーモデルをカメラの前方に配置
            horizonTarget.position = new Number3D(Math.cos(cameraCtrl.lookDirection) * 10000, 10000, Math.sin(cameraCtrl.lookDirection) * 10000);
            
            //PV3Dレンダリング
            view.singleRender();
            
            //雲を動かす
            var area:int = 2000;
            for each(c in clouds) {
                c.z = ((c.startPosition.z + time * 0.42) + area) % (area * 2) - area;
                var loop:int = int(((c.startPosition.z + time * 0.42) + area) / (area * 2));
                if (c.loop != loop) {
                    //周回数が変化する度に雲の配置を変化させる
                    c.loop = loop;
                    c.x = Math.random() * 3500 - 1750;
                    c.y = Math.random() * -300 + 10000;
                }
                cameraCtrl.calculateScreen(c.screen, c.x, c.y, c.z);
            }
            
            //背景画像を地平線の高さに移動
            bg.y = horizonTarget.screen.y + Display.center.y;
            bg.rotation = cameraCtrl.roll;
            bg.slide(cameraCtrl.lookDirection / (Math.PI * 2));
            ground.visible = horizonTarget.screen.y + Display.center.y < Display.height;
            
            //雲画像処理
            canvas1.lock();
            canvas2.lock();
            canvas1.colorTransform(Display.size, clearColor);
            canvas2.colorTransform(Display.size, clearColor);
            //描画対象の雲を絞り込む
            drawObjects.length = 0;
            for each(c in clouds) {
                if (c.screen.z > 10) {
                    c.update();
                    if (c.alpha <= 0) continue;
                    if (c.screen.x + Display.center.x < -CLOUD_SIZE.width * c.scale / 2) continue;
                    if (c.screen.x + Display.center.x > Display.width + CLOUD_SIZE.width * c.scale / 2) continue;
                    drawObjects.push(c);
                }
            }
            drawObjects.sort(function(a:Cloud, b:Cloud):Number { return int(b.screen.z - a.screen.z); } );
            //雲描画
            for each(c in drawObjects) {
                var target:BitmapData = (airplane.screen.z < c.screen.z)? canvas1 : canvas2;
                var ct:ColorTransform = new ColorTransform(1, 1, 1, c.alpha, 0, 0, 0, 0);
                var mtx:Matrix = new Matrix();
                mtx.scale(c.scale, c.scale);
                mtx.rotate(PI * view.camera.localRotationZ);
                var dx:Number = c.scale * CLOUD_SIZE.width / 2;
                var dy:Number = c.scale * CLOUD_SIZE.height / 2;
                var cos:Number = Math.cos(PI * cameraCtrl.roll);
                var sin:Number = Math.sin(PI * cameraCtrl.roll);
                var px:Number = c.screen.x + Display.center.x - cos * dx + sin * dy;
                var py:Number = c.screen.y + Display.center.y - sin * dx - cos * dy;
                mtx.translate(px, py);
                target.draw(c.image, mtx, ct);
            }
            canvas1.unlock();
            canvas2.unlock();
        }
    }
}

import flash.display.*;
import flash.filters.*;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.getTimer;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.proto.CameraObject3D;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.scenes.Scene3D;

/**
 * 画面サイズ
 */
class Display {
    static public var width:Number;
    static public var height:Number;
    static public var size:Rectangle;
    static public var center:Point;
    static public function setSize(width:Number, height:Number):void {
        Display.width = width;
        Display.height = height;
        size = new Rectangle(0, 0, width, height);
        center = new Point(width / 2, height / 2);
    }
}

/**
 * 色
 */
class Color {
    /**航空機の色*/
    static public var planeSkin:uint = 0xFFFFFF;
    /**雲の色*/
    static public var cloudBase:uint = 0xD7DDE5;
    /**雲のハイライト色*/
    static public var cloudLight:uint = 0xFFFFFF;
    /**雲の影の色*/
    static public var cloudShadow:uint = 0x6D8790;
    /**空の色(上)*/
    static public var sky1:uint = 0x1F437F;
    /**空の色(下)*/
    static public var sky2:uint = 0x6290C1;
    /**地平線付近の色*/
    static public var horizon:uint = 0xA0BCD1;
    /**地上の色*/
    static public var ground:uint = 0xA1ACA4;
}

/**
 * 経過時間
 */
class Time {
    static private var _start:int;
    static public var count:int;
    static public function update():void {
        count = getTimer() - _start + 7000;
    }
    static public function start():void {
        _start = getTimer();
    }
}

/**
 * 雲
 */
class Cloud {
    public var x:Number = 0;
    public var y:Number = 0;
    public var z:Number = 0;
    public var screen:Number3D = new Number3D();
    public var loop:int;
    public var startPosition:Number3D;
    public var image:BitmapData;
    public var alpha:Number;
    public var scale:Number;
    public function Cloud() {
    }
    /**
     * 雲の初期位置を設定
     */
    public function setPosition(x:Number, y:Number, z:Number):void {
        startPosition = new Number3D(x, y, z);
        this.x = x;
        this.y = y;
        this.z = z;
    }
    /**
     * スケールと透明度を更新
     */
    public function update():void {
        scale = 600 / screen.z;
        var perMin:Number = screen.z / 200;
        var perMax:Number = 1 - (screen.z - 1500) / 800;
        if (perMin > 1) perMin = 1;
        if (perMax > 1) perMax = 1;
        alpha = perMin * perMax * 2;
    }
}

/**
 * カメラ操作
 */
class CameraController {
    private const RADIAN:Number = Math.PI / 180;
    private var _calculateObject:DisplayObject3D = new DisplayObject3D();
    private var _lookAtTarget:DisplayObject3D = new DisplayObject3D();
    private var _camera:Camera3D;
    private var _type:int = 0;
    private var _airplaneRoll:Number = 0;
    public var roll:Number;
    public var angle:Number;
    public var rotation:Number;
    public var distance:Number;
    public var lookDirection:Number;
    public function CameraController() {
    }
    /**
     * シーンとカメラを渡して初期化
     */
    public function init(scene:Scene3D, camera:CameraObject3D):void {
        _camera = camera as Camera3D;
        scene.addChild(_calculateObject);
        scene.addChild(_lookAtTarget);
    }
    /**
     * (x,y,z)のスクリーン座標を計算してscreenに設定する
     */
    public function calculateScreen(screen:Number3D, x:Number, y:Number, z:Number):void {
        _calculateObject.x = x;
        _calculateObject.y = y;
        _calculateObject.z = z;
        _calculateObject.view.calculateMultiply(_camera.eye, _calculateObject.transform);
        _calculateObject.calculateScreenCoords(_camera);
        screen.copyFrom(_calculateObject.screen);
    }
    /**
     * カメラ変更
     */
    public function switchCamera():void {
        _type = ++_type % 5;
    }
    /**
     * 飛行機の傾きを渡す
     */
    public function setAirplaneRoll(roll:Number):void {
        _airplaneRoll = roll;
    }
    /**
     * カメラ位置更新
     */
    public function update():void {
        var time:int = Time.count;
        switch(_type) {
            case 0:
                distance = Math.sin(RADIAN * time / 80) * 200 + 600;
                rotation = time / 1000 * 60 * 0.2;
                roll = Math.sin(RADIAN * time / 50) * 20;
                angle = Math.sin(RADIAN * time / 100) * 100 + 50;
                _lookAtTarget.position = new Number3D(0, 10000, 0);
                break;
            case 1:
                distance = 280;
                rotation = Math.sin(RADIAN * time / 110) * 20 + 90;
                roll = -_airplaneRoll;
                angle = Math.sin(RADIAN * time / 90) * 50 + 30;
                _lookAtTarget.position = new Number3D(0, 10000, -10000);
                break;
            case 2:
                distance = 500;
                rotation = Math.sin(RADIAN * time / 110) * 10;
                roll = 0;
                angle = Math.sin(RADIAN * -time / 70) * 200;
                _lookAtTarget.position = new Number3D(0, 10000, 0);
                break;
            case 3:
                distance = 800;
                rotation = -time / 200;
                roll = 0;
                angle = -400;
                _lookAtTarget.position = new Number3D(0, 10000, 0);
                break;
            case 4:
                distance = 40;
                rotation = 50;
                roll = -_airplaneRoll / 2;
                angle = 30 + _airplaneRoll;
                _lookAtTarget.position = new Number3D(1000, 10000, -700);
                break;
        }
        _camera.position = new Number3D(Math.cos(RADIAN * rotation) * distance, angle + 10000, Math.sin(RADIAN * rotation) * distance);
        _camera.lookAt(_lookAtTarget);
        _camera.roll(roll);
        lookDirection = Math.atan2(_lookAtTarget.z - _camera.z, _lookAtTarget.x - _camera.x);
    }
}

class Painter {
    /**
     * 雲画像生成
     * @param    width    幅
     * @param    height    高さ
     * @param    seed    ランダムシード値
     * @param    contrast    コントラスト0~
     * @param    color    ベースの色
     * @param    light    明るい色
     * @param    shadow    暗い色
     */
    static public function createCloud(width:int, height:int, seed:int, contrast:Number = 1, color:uint = 0xFFFFFF, light:uint = 0xFFFFFF, shadow:uint = 0xDDDDDD):BitmapData {
        var gradiation:Sprite = new Sprite();
        var drawMatrix:Matrix = new Matrix();
        drawMatrix.createGradientBox(width, height);
        gradiation.graphics.beginGradientFill("radial", [0x000000, 0x000000], [0, 1], [0, 255], drawMatrix);
        gradiation.graphics.drawRect(0, 0, width, height);
        gradiation.graphics.endFill();
        var alphaBmp:BitmapData = new BitmapData(width, height);
        alphaBmp.perlinNoise(width / 3, height / 2.5, 5, seed, false, true, 1|2|4, true);
        var zoom:Number = 1 + (contrast - 0.1) / (contrast + 0.9);
        if (contrast < 0.1) zoom = 1;
        if (contrast > 2.0) zoom = 2;
        var ctMatrix:Array = [contrast + 1, 0, 0, 0, -128 * contrast, 0, contrast + 1, 0, 0, -128 * contrast, 0, 0, contrast + 1, 0, -128 * contrast, 0, 0, 0, 1, 0];
        alphaBmp.draw(gradiation, new Matrix(zoom, 0, 0, zoom, -(zoom - 1) / 2 * width, -(zoom - 1) / 2 * height));
        alphaBmp.applyFilter(alphaBmp, alphaBmp.rect, new Point(), new ColorMatrixFilter(ctMatrix));
        var image:BitmapData = new BitmapData(width, height, true, 0xFF << 24 | color);
        image.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
        image.applyFilter(image, image.rect, new Point(), new GlowFilter(light, 1, 4, 4, 1, 3, true));
        var bevelSize:Number = Math.min(width, height) / 30;
        image.applyFilter(image, image.rect, new Point(), new BevelFilter(bevelSize, 45, light, 1, shadow, 1, bevelSize/5, bevelSize/5, 1, 3));
        var image2:BitmapData = new BitmapData(width, height, true, 0);
        image2.draw(Painter.createGradientRect(width, height, [light, color, shadow], [1, 0.2, 1], null, 90), null, null, BlendMode.MULTIPLY);
        image2.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
        image.draw(image2, null, null, BlendMode.MULTIPLY);
        alphaBmp.dispose();
        return image;
    }
    /**
     * グラデーションスプライト生成
     */
    static public function createGradientRect(width:Number, height:Number, colors:Array, alphas:Array, ratios:Array = null, rotation:Number = 0):Sprite {
        var i:int, rts:Array = new Array();
        if(ratios == null) for (i = 0; i < colors.length; i++) rts.push(int(255 * i / (colors.length - 1)));
        else for (i = 0; i < ratios.length; i++) rts[i] = Math.round(ratios[i] * 255);
        var sp:Sprite = new Sprite();
        var mtx:Matrix = new Matrix();
        mtx.createGradientBox(width, height, Math.PI / 180 * rotation, 0, 0);
        if (colors.length == 1 && alphas.length == 1) sp.graphics.beginFill(colors[0], alphas[0]);
        else sp.graphics.beginGradientFill("linear", colors, alphas, rts, mtx);
        sp.graphics.drawRect(0, 0, width, height);
        sp.graphics.endFill();
        return sp;
    }
}

/**
 * 遠景画像
 */
class BackGround extends Sprite {
    private var _imageWidth:int = 2000;
    private var _viewWidth:int = 600;
    private var _cloudWidth:int = 120;
    private var _cloudHeight:int = 60;
    private var _image:BitmapData;
    private var _cloudSprite:Sprite;
    public function BackGround() {
        _viewWidth = Display.width * 1.5;
        var sky:Sprite = addChild(Painter.createGradientRect(Display.width*2, Display.height, [Color.sky1, Color.sky2, Color.horizon], [1, 1, 1], [0, 0.9, 1], 90)) as Sprite;
        sky.x = -Display.width;
        sky.y = -Display.height;
        var ground:Sprite = addChild(Painter.createGradientRect(Display.width*2, Display.height, [Color.horizon, Color.ground], [1, 1], null, 90)) as Sprite;
        ground.y = -1;
        ground.x = -Display.width;
        //遠景画像作成
        _image = new BitmapData(_imageWidth, _cloudHeight, true, 0x00FFFFFF);
        for (var n:int = 0; n < 80; n++) {
            var cloud:BitmapData = Painter.createCloud(_cloudWidth, _cloudHeight, n+200, 1, Color.cloudBase, Color.cloudLight, Color.cloudShadow);
            _image.copyPixels(cloud, cloud.rect, new Point(Math.random() * (_imageWidth - _cloudWidth), 0), null, null, true);
        }
        _image.applyFilter(_image, _image.rect, new Point(), new BlurFilter(2, 2, 1));
        
        _cloudSprite = new Sprite();
        _cloudSprite.x = -_viewWidth / 2;
        _cloudSprite.y = -_cloudHeight / 2;
        addChild(_cloudSprite);
    }
    /**
     * 遠景画像をスライドする
     */
    public function slide(per:Number):void {
        per %= 1;
        _cloudSprite.graphics.clear();
        _cloudSprite.graphics.beginBitmapFill(_image, new Matrix(1, 0, 0, 1, _imageWidth * per, 0), true, true);
        _cloudSprite.graphics.drawRect(0, 0, _viewWidth, _cloudHeight);
    }
}

/**
 * 画像生成中画面
 */
class LoadingScene extends Sprite {
    private var _lineWidth:Number = 200;
    private var _loadedLine:Sprite;
    public function LoadingScene() {
        var bg:Sprite = addChild(Painter.createGradientRect(Display.width, Display.height, [0x000000], [1])) as Sprite;
        var baseLine:Sprite = addChild(Painter.createGradientRect(_lineWidth, 2, [0x444444], [1])) as Sprite;
        _loadedLine = addChild(Painter.createGradientRect(_lineWidth, 2, [0x7DA3C8], [1])) as Sprite;
        baseLine.x = _loadedLine.x = int((Display.width - _lineWidth) / 2);
        baseLine.y = _loadedLine.y = int((Display.height - baseLine.height) / 2);
        setProgress(0);
    }
    public function setProgress(per:Number):void {
        _loadedLine.width = _lineWidth * per;
    }
}