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

forked from: forked from: RollCameraController(Simple Easing) [Alternativa3d7.6 TIPS]

Alternativa3D 7.6

RollCameraController
イージング(遅延減速)付き

@author narutohyper
Get Adobe Flash player
by amyneon 23 Oct 2012
    Embed
/**
 * Copyright amyneon ( http://wonderfl.net/user/amyneon )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/gGUl
 */

// forked from narutohyper's forked from: RollCameraController(Simple Easing) [Alternativa3d7.6 TIPS]
// forked from narutohyper's RollCameraController(Simple Easing) [Alternativa3d7.6 TIPS]
// forked from narutohyper's Alternativa3D 7.6 Template
package
{
    import alternativ7.engine3d.materials.FillMaterial;
    import alternativ7.engine3d.materials.TextureMaterial;
    import alternativ7.engine3d.loaders.MaterialLoader;
    import alternativ7.engine3d.primitives.Plane;
    import alternativ7.engine3d.primitives.GeoSphere;
    import alternativ7.engine3d.objects.Sprite3D;
    import alternativ7.engine3d.controllers.SimpleObjectController
    import flash.display.Sprite;
    import flash.display.Shape;
    import flash.display.BitmapData;
    import flash.system.LoaderContext;
    
    import flash.events.Event;
    import flash.ui.Keyboard;
    
    /**
     *
     * Alternativa3D 7.6
     *
     * RollCameraController
     * イージング(遅延減速)付き
     * 
     * @author narutohyper
     */
    [SWF(backgroundColor="#000000", frameRate="100", width="800", height="600")]
    public class Main extends Sprite
    {
        
        public function Main():void    {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event=null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
        
            //AlternativaTemplate作成
            var scene:AlternativaTemplate = new AlternativaTemplate(this)

            //星パーティクル
            var RADIAN:Number = Math.PI / 180;
            var stars:Vector.<Sprite3D> = new Vector.<Sprite3D>(500, true);
            var circle:Shape = new Shape();
            circle.graphics.beginFill(0xFFFFFF);
            circle.graphics.drawCircle(25, 25, 25);
            var bmd:BitmapData = new BitmapData(50, 50, true, 0);
            bmd.draw(circle);
            var material:TextureMaterial = new TextureMaterial(bmd);
            var angle:Number;
            var length:Number;
            for (var i:int = 0; i < 500; i++)
            {
                    stars[i] = new Sprite3D(100, 100, material);
                    scene.container.addChild(stars[i]);
                    angle = Math.random() * 360 * RADIAN;
                    length = Math.random() * 100000 + 5000;
                    stars[i].x = Math.cos(angle) * length;
                    stars[i].y = Math.sin(angle) * length;
                    angle = Math.random() * 360 * RADIAN;
                    length = Math.random() * 100000 + 5000;
                    stars[i].z = Math.sin(angle) * length;
            }

            //地球
            var earthMaterial:TextureMaterial = new TextureMaterial(null, false, true);
            earthMaterial.diffuseMapURL = 'http://vreshenie.ru/work/alternativa3d/earth/globe_boundaries.jpg';

            var textures:Vector.<TextureMaterial> = new Vector.<TextureMaterial>();
            textures[0] = earthMaterial;
            var context:LoaderContext = new LoaderContext(true);
            var materialLoader:MaterialLoader = new MaterialLoader();
            materialLoader.load(textures,context);

            var earth:GeoSphere = new GeoSphere(200, 8);
            //earth.sorting = Sorting.DYNAMIC_BSP;
            earth.setMaterialToAllFaces(earthMaterial);
            scene.container.addChild(earth);
            
            
            
            scene.cameraController.object = null;
            
            var cameraController:RollCameraController = new RollCameraController(stage, scene.camera, 200);
            cameraController.mouseSensitivity = 0;
            cameraController.mouseSensitivityX = 1; 
            cameraController.mouseSensitivityY = 1; 
            cameraController.unbindAll();
            cameraController.accelerate(true);
            //Cameraの中心からの距離
            cameraController.length(700);
            cameraController.minLength = 200;
            
            //イージング設定
            //1~数値が高いほど、遅延大でぬるぬる
            cameraController.easingSeparator = 30;
            
            //Cameraの初期位置
            cameraController.posZ(500,true);
            cameraController.angle(0);
            
            //視点の調整
            //ただし回転するCameraなので、Z以外は、おかしくなる
            cameraController.lookAtPosition(0, 0, 10);
            cameraController.minZ = -1000;
            cameraController.maxZ = 1000;
            cameraController.bindKey(Keyboard.LEFT, SimpleObjectController.ACTION_YAW_LEFT);
            cameraController.bindKey(Keyboard.RIGHT,SimpleObjectController.ACTION_YAW_RIGHT);
            cameraController.bindKey(Keyboard.DOWN, SimpleObjectController.ACTION_PITCH_DOWN);
            cameraController.bindKey(Keyboard.UP, SimpleObjectController.ACTION_PITCH_UP);
            cameraController.bindKey(Keyboard.PAGE_UP, RollCameraController.ACTION_ZOOM_IN);
            cameraController.bindKey(Keyboard.PAGE_DOWN,RollCameraController.ACTION_ZOOM_OUT);
            cameraController.update();
            
            //描画開始
            scene.startRendering()
            
            scene.onPreRender = function():void {
                cameraController.update();
            }

        }

    }
    
}





import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Object3D;
import flash.display.InteractiveObject;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Vector3D;

/**
 * RollCameraController
 *
 * @author narutohyper
 */

class RollCameraController extends SimpleObjectController{
    public static const ACTION_ZOOM_IN : String="action_zoom_in";
    public static const ACTION_ZOOM_OUT : String="action_zoom_out";
    

    
    /**
     * Camera位置の最小高さ(z) 上が+ 初期値は100
     */
    public var minZ:Number = 100;
    /**
     * Camera位置の最大高さ(z) 上が+ 初期値は800
     */
    public var maxZ:Number = 800;
    /**
     * Cameraから、中心までの最小距離
     */
    public var minLength:Number = 200;
    /**
     * Cameraから、中心までの最大距離
     */
    public var maxLength:Number = 2000;
    
    private var _easingSeparator:Number = 20;
    private var _yawNear:Boolean=false
    private var _yawNearAngle:Number
    private var _pitchNear:Boolean=false
    private var _pitchNearAngle:Number


    private var _target:Object3D
    private var _pitchDown:Boolean;
    private var _pitchUp:Boolean;
    private var _yawLeft:Boolean;
    private var _yawRight:Boolean;
    
    private var _mouseMove:Boolean;
    private var _mouseSensitivityX:Number=1
    private var _mouseSensitivityY:Number=1
    private var _mouseX:Number;
    private var _mouseY:Number;
    private var _zoomIn:Boolean;
    private var _zoomOut:Boolean;
    private var _length:Number = 700;
    private var _lastLength:Number = 700;
    
    private var _zoomSpeed:Number = 10;
    private var _yawSpeed:Number = 5;
    private var _pitchSpeed:Number = 30;

    private var _oldAngle:Number;
    private var _angle:Number = 90;
    private var _lastAngle:Number = _angle;
    private var _oldZ:Number;
    private var _lastZ:Number;
    private var _eventSource:InteractiveObject;
    
    private var _lookAtX:Number=0;
    private var _lastLookAtX:Number=_lookAtX;
    private var _lookAtY:Number=0;
    private var _lastLookAtY:Number=_lookAtY;
    private var _lookAtZ:Number=0;
    private var _lastLookAtZ:Number=_lookAtZ;
    
    
    public function RollCameraController(eventSource:InteractiveObject, object:Object3D, speed:Number, speedMultiplier:Number = 3, mouseSensitivityX:Number = 1, mouseSensitivityY:Number = 1) {
        _target = object;
        _lastZ = _target.z;
        _eventSource = eventSource;
        super(eventSource, object, speed, speedMultiplier, mouseSensitivity);
        
        eventSource.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        eventSource.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
        _eventSource.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
    }
    
    private function onMouseWheel(e:MouseEvent):void
    {
        _lastLength += e.delta*20;
        if (_lastLength < minLength) {
            _lastLength=minLength
        } else if (_lastLength > maxLength) {
            _lastLength=maxLength
        }
    }
    
    public function onKeyDown(e:KeyboardEvent):void {
        for (var key:String in keyBindings) {
            if (String(e.keyCode)==key) {
                keyBindings[key](true)
            }
        }
    }
    
    public function onKeyUp(e:KeyboardEvent = null):void {
        for (var key:String in keyBindings) {
            keyBindings[key](false)
        }
        _yawNear = false
        _pitchNear = false;
    }

    
    override public function bindKey(keyCode:uint, action:String): void {
        switch (action) {
            case ACTION_ZOOM_IN:
                keyBindings[keyCode] = zoomIn;
            break
            case ACTION_ZOOM_OUT:
                keyBindings[keyCode] = zoomOut;
            break
            case ACTION_YAW_LEFT:
                keyBindings[keyCode] = yawLeft;
            break
            case ACTION_YAW_RIGHT:
                keyBindings[keyCode] = yawRight;
            break
            case ACTION_PITCH_DOWN:
                keyBindings[keyCode] = pitchDown;
            break
            case ACTION_PITCH_UP:
                keyBindings[keyCode] = pitchUp;
            break
        }
        //super.bindKey(keyCode, action)
    }
    

    public function pitchDown(value:Boolean):void {
        _pitchDown=value
    }
    
    public function pitchUp(value:Boolean):void {
        _pitchUp=value
    }
    
    public function yawLeft(value:Boolean,near:Boolean=false):void {
        _yawLeft = value;
        _yawNear = near;
    }
    
    public function yawRight(value:Boolean,near:Boolean=false):void {
        _yawRight = value;
        _yawNear = near;
    }
    
    public function zoomIn(value:Boolean):void {
        _zoomIn = value;

    }
    
    public function zoomOut(value:Boolean):void {
        _zoomOut = value;
    }

    
    
    override public function update(): void {
        var RADIAN:Number = Math.PI / 180;
        
        //CameraZoom制御
        if (_zoomIn) {
            _lastLength -= _zoomSpeed
        } else if (_zoomOut){
            _lastLength += _zoomSpeed
        }
        if (_lastLength < minLength) {
            _lastLength=minLength
        } else if (_lastLength > maxLength) {
            _lastLength=maxLength
        }
        if (_lastLength - _length) {
            _length += (_lastLength - _length) / _easingSeparator;
        }
        
        //Camera回転制御
        if (_mouseMove) {
            _lastAngle = _oldAngle + (_eventSource.mouseX - _mouseX) * _mouseSensitivityX/2
            
        } else if (_yawLeft) {
            _lastAngle += _yawSpeed;

        } else if (_yawRight) {
            _lastAngle -= _yawSpeed;

        }
        if (_lastAngle-_angle) {
            _angle += (_lastAngle - _angle) / _easingSeparator;
        }
        
        _target.x = Math.cos(_angle * RADIAN) * _length;
        _target.y = Math.sin(_angle * RADIAN) * _length;
        
        
        //CameraZ位置制御
        if (_mouseMove) {
            _lastZ = _oldZ + (_eventSource.mouseY - _mouseY) * _mouseSensitivityY * 2

        } else if (_pitchDown) {
            _lastZ -= _pitchSpeed

        } else if (_pitchUp) {
            _lastZ += _pitchSpeed
        }
        if (_lastZ < minZ) {
            _lastZ = minZ;
        } else if (_lastZ > maxZ) {
            _lastZ = maxZ
        }
        if (_lastZ - _target.z) {
            _target.z += (_lastZ - _target.z) / _easingSeparator;
        }
        
        //lookAt制御
        if (_lastLookAtX - _lookAtX) {
            _lookAtX += (_lastLookAtX-_lookAtX) / _easingSeparator;
        }
        
        if (_lastLookAtY - _lookAtY) {
            _lookAtY += (_lastLookAtY-_lookAtY) / _easingSeparator;
        }
        
        if (_lastLookAtZ - _lookAtZ) {
            _lookAtZ += (_lastLookAtZ-_lookAtZ) / _easingSeparator;
        }
        
        //super.update()
        updateObjectTransform()
        lookAtXYZ(_lookAtX, _lookAtY, _lookAtZ);
    }
    
    override public function startMouseLook():void {
        _oldAngle = _lastAngle
        _oldZ = _lastZ
        _mouseX = _eventSource.mouseX;
        _mouseY = _eventSource.mouseY;
        _mouseMove = true;
        
    }

    override public function stopMouseLook():void {
        _mouseMove = false;
    }
    
    /**
     * Zoomスピード
     * 初期値は10(px)
     */
    public function set zoomSpeed(value:Number):void
    {
        _zoomSpeed = value;
    }
    
    /**
     * 回転スピード
     * 初期値は5(度)
     */
    public function set yawSpeed(value:Number):void {
        _yawSpeed = value*Math.PI/180;
    }

    /**
     * 上下スピード
     * 初期値は30(px)
     */
    public function set pitchSpeed(value:Number):void
    {
        _pitchSpeed = value
    }
    
    /**
     * マウスのX方向の感度
     */
    public function set mouseSensitivityX(value:Number):void
    {
        _mouseSensitivityX = value;
    }
    
    /**
     * マウスのY方向の感度
     */
    public function set mouseSensitivityY(value:Number):void
    {
        _mouseSensitivityY = value;
    }

    
    /**
     * イージング時の現在の位置から最後の位置までの分割係数
     * フレームレートと相談して使用
     * 1~
     * 正の整数のみ。0を指定しても1になります。
     * 1でイージング無し。数値が高いほど、遅延しぬるぬるします
     */
    public function set easingSeparator(value:uint):void
    {
        if (value) {
            _easingSeparator = value;
        } else {
            _easingSeparator = 1;
        }
    }
    
    /**
     * Cameraの向く方向
     * mode=trueで、イージングしないで変更
     * lookAtやlookAtXYZとの併用は不可
     */
    public function lookAtPosition(x:Number, y:Number, z:Number,mode:Boolean=false):void {
        if (mode)
        {
            _lookAtX = x
            _lookAtY = y
            _lookAtZ = z
        }
        _lastLookAtX = x
        _lastLookAtY = y
        _lastLookAtZ = z
    }
    
    /**
     * Cameraの初期位置
     * value=0で、正面から中央方向(lookAtPosition)を見る
     * mode=trueで、イージングしないで変更
     */
    public function angle(value:Number,mode:Boolean=false):void
    {
        if (mode)
        {
            _angle = value+90;
        }
        _lastAngle = value+90;
    }
    
    /**
     * Cameraから、targetObjectまでの距離
     * mode=trueで、イージングしないで変更
     */
    public function length(value:Number,mode:Boolean=false):void
    {
        if (mode)
        {
            _length = value;
        }
        _lastLength = value;
    }
    /**
     * Cameraの高さ
     * mode=trueで、イージングしないで変更
     */
    public function posZ(value:Number,mode:Boolean=false):void
    {
        if (mode)
        {
            _target.z = value;
        }
        _lastZ = value;
    }
    

    

    
}




/**
 * BasicTemplate for Alternativa3D 7.6
 * Alternativa3D 7.6を扱いやすくするためのテンプレートです
 * @author narutohyper & clockmaker
 *
 */
import alternativ7.engine3d.containers.BSPContainer;
import alternativ7.engine3d.containers.ConflictContainer;
import alternativ7.engine3d.containers.DistanceSortContainer;
import alternativ7.engine3d.containers.KDContainer;
import alternativ7.engine3d.containers.LODContainer;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.core.View;
import flash.display.DisplayObject;

import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;

import flash.events.Event;

class AlternativaTemplate extends Sprite
{
        /**
         * 子オブジェクトを最適な方法でソートするコンテナ
         * (ConflictContainer)
         */
        public static const CONFLICT:String = 'conflict';
        /**
         * 子オブジェクトをBSP(バイナリ空間分割法)によってソートするコンテナ
         * (BSPContainer)
         */
        public static const BSP:String = 'bsp';
        
        /**
         * 子オブジェクトをカメラからのZ値でソートするコンテナ
         * (DistanceSortContainer)
         */
        public static const ZSORT:String = 'zsort';
        /**
         * KDツリー(http://ja.wikipedia.org/wiki/Kd%E6%9C%A8)によってソートするコンテナ
         * (KDContainer)
         */
        public static const KD:String = 'kd';
        /**
         * detalizationと子オブジェクトの距離でソートするコンテナ(詳細は調査中)
         * (LODContainer)
         */
        public static const LOD:String = 'lod';
        
        /**
         * 3dオブジェクト格納するコンテナインスタンス。
         */
        public var container:Object3DContainer;

        /**
         * ビューインスタンスです。
         */
        public var view:View
        
        /**
         * カメラインスタンスです。
         */
        public var camera:Camera3D;
        
        /**
         * カメラコントローラーです。
         */
        public var cameraController:SimpleObjectController
        
        private var _mc:DisplayObjectContainer
        private var _viewWidth:int;
        private var _viewHeight:int;
        private var _scaleToStage:Boolean;
        private var _containerType:String
        
        /**
         * 新しい Alternativa3DTemplate インスタンスを作成します。
         * @param        mc
         * @param        containerType
         * @param        viewWidth
         * @param        viewHeight
         * @param        scaleToStage
         */
        public function AlternativaTemplate(mc:DisplayObjectContainer,containerType:String=CONFLICT,viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true)
        {
                _mc = mc
                _mc.addChild(this)

                _containerType = containerType
                _viewWidth = viewWidth;
                _viewHeight = viewHeight;
                _scaleToStage = scaleToStage;
                
                if (stage) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
        }


        /**
         * 初期化されたときに実行されるイベントです。
         * 初期化時に実行したい処理をオーバーライドして記述します。
         */
        protected function atInit():void {}


        /**
         * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
         * レンダリング前に実行したい処理をオーバーライドして記述します。
         */
        protected function atPreRender():void {}
        
        /**
         * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
         * レンダリング前に実行したい処理をオーバーライドして記述します。
         */
        private var _onPreRender:Function = function():void{};
        public function get onPreRender():Function { return _onPreRender; }
        public function set onPreRender(value:Function):void
        {
                _onPreRender = value;
        }
        
        /**
         * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
         * レンダリング後に実行したい処理をオーバーライドして記述します。
         */
        protected function atPostRender():void {}
        
        /**
         * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
         * レンダリング後に実行したい処理を記述します。
         */
        private var _onPostRender:Function = function():void{};
        public function get onPostRender():Function { return _onPostRender; }
        public function set onPostRender(value:Function):void
        {
                _onPostRender = value;
        }
        
        
        /**
         * レンダリングを開始します。
         */
        public function startRendering():void
        {
                addEventListener(Event.ENTER_FRAME, onRenderTick);
        }

        /**
        * レンダリングを停止します。
        */
        public function stopRendering():void
        {
                removeEventListener(Event.ENTER_FRAME, onRenderTick);
        }

        /**
         * シングルレンダリング(レンダリングを一回だけ)を実行します。
         */
        public function singleRender():void
        {
                onRenderTick();
        }

        /**
         * @private
         */
        private function init(e:Event = null):void
        {
                removeEventListener(Event.ADDED_TO_STAGE, init);
                // entry point
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
                stage.quality = StageQuality.HIGH;
                
                //Root objectの作成
                if (_containerType == CONFLICT) {
                        container = new ConflictContainer();
                } else if (_containerType == BSP) {
                        container = new BSPContainer();
                } else if (_containerType == ZSORT) {
                        container = new DistanceSortContainer();
                } else if (_containerType == KD) {
                        container = new KDContainer();
                } else if (_containerType == LOD) {
                        container = new LODContainer();
                }
                //Viewの作成
                view = new View(stage.stageWidth, stage.stageHeight);
                _mc.addChild(view);

                //cameraの作成
                camera = new Camera3D();
                camera.view = view;
                camera.x = 0;
                camera.y = -500;
                camera.z = 0;
                container.addChild(camera);
                
                // Camera controller
                cameraController = new SimpleObjectController(stage, camera, 10);
                cameraController.mouseSensitivity = 0
                cameraController.unbindAll()
                cameraController.lookAtXYZ(0, 0, 0)
                
                onResize();
                stage.addEventListener(Event.RESIZE, onResize);
                
                atInit();
        }
        
        /**
         * @private
         */
        private function onResize(e:Event = null):void
        {
                if (_scaleToStage)
                {
                    view.width = stage.stageWidth;
                    view.height = stage.stageHeight;
                }
                else
                {
                    view.width = _viewWidth;
                    view.height = _viewHeight;
                }
        }
        
        /**
         * @private
         */
        private function onRenderTick(e:Event = null):void
        {
                atPreRender();
                _onPreRender()
                cameraController.update();
                camera.render();
                atPostRender();
                _onPostRender();
        }


}