Switch Cameras & SpringCamera [Alternativa3D 7.6 TIPS]

by narutohyper forked from Switch Cameras [Alternativa3D 7.6 TIPS] (diff: 148)
Switch Cameras & SpringCamera  [Alternativa3D 7.6 TIPS]

fork元Cameraの切り替えにSpringCameraも追加したVer

十字キー上下、またはWSキーで前進後退
十字キー左右、またはADで回転(ただし進行中のみ)

SPACEキーでCameraが切り替わります

2011/01/12 7.5から7.6仕様に変更
♥0 | Line 442 | Modified 2012-10-23 16:11:36 | MIT License
play

ActionScript3 source code

/**
 * Copyright narutohyper ( http://wonderfl.net/user/narutohyper )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/qKJY
 */

// forked from narutohyper's Switch Cameras  [Alternativa3D 7.5 TIPS]
// forked from narutohyper's CarController    [Alternativa3D 7.5 TIPS]
// forked from narutohyper's YawController    [Alternativa3D 7.5 TIPS]
// forked from narutohyper's SimpleObjectController DefaultBindings [Alternativa3D 7.5 TIPS]
// forked from narutohyper's Alternativa3D 7.5 Template
package
{
    import alternativ7.engine3d.controllers.SimpleObjectController;
    import alternativ7.engine3d.core.Camera3D;
    import alternativ7.engine3d.core.Object3DContainer;
    import alternativ7.engine3d.core.Sorting;
    import alternativ7.engine3d.core.View;
    import alternativ7.engine3d.materials.FillMaterial;
    import alternativ7.engine3d.primitives.Box;
    import alternativ7.engine3d.primitives.Plane;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.geom.Vector3D;
    import flash.ui.Keyboard;

    
    /**
     * Alternativa3D 7.6
     *
     * Cameraの切り替え
     *
     * ...
     * @author narutohyper
     */
    [SWF(backgroundColor="#FFFFFF", 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);

            addChild(scene.camera.diagram);
            
            var RADIAN:Number = Math.PI / 180;
            
            
            //床を作成
            var material1:FillMaterial = new FillMaterial(0x0, 0.5, 0,0x666666);
            
            var plane:Plane = new Plane(5000, 5000, 25, 25);
            plane.setMaterialToAllFaces(material1);
            scene.container.addChild(plane);
            plane.z=0;
            
            
            //Controllerで動かす空のObject3DContainerを作成
            //中に、箱とカメラを入れる
            var animeObj:Object3DContainer=new Object3DContainer();
            scene.container.addChild(animeObj);
            animeObj.z = 30;

            //material
            var material2:FillMaterial = new FillMaterial(0xCCCCFF,1,0,0x333333);
            var box:Box = new Box(100,200,50,1,1,1);
            box.setMaterialToAllFaces(material2);
            box.sorting = Sorting.AVERAGE_Z;
            animeObj.addChild(box);
            //後輪の位置で回転するように、少し前へ(タイヤ無いけどw)
            box.y = 75;

            //車載カメラ用Viewの作成
            var view:View = new View(stage.stageWidth, stage.stageHeight);
            view.visible=false;
            addChild(view);

            //もう一台カメラ(車載カメラ)を作成
            var camera:Camera3D = new Camera3D();

            camera.view = view;
            camera.x = 0;
            camera.y = -300;
            camera.z = 100;
            camera.rotationX=-100*Math.PI/180;
            animeObj.addChild(camera);

            //ObjectControllerの作成
            var objectController:CarController = new CarController(stage,animeObj,500);
            //デフォルトで有効になってる、マウス操作を無効にする
            objectController.mouseSensitivity = 0;
            

            //デフォルトのキーバインドを使用する
            
            //Keyの調整
            objectController.unbindAll();

            objectController.bindKey(Keyboard.UP,        SimpleObjectController.ACTION_FORWARD);
            objectController.bindKey(Keyboard.DOWN,  SimpleObjectController.ACTION_BACK);
            objectController.bindKey(Keyboard.LEFT,  SimpleObjectController.ACTION_YAW_LEFT);
            objectController.bindKey(Keyboard.RIGHT, SimpleObjectController.ACTION_YAW_RIGHT);
            //加速装置
            objectController.bindKey(Keyboard.SHIFT, SimpleObjectController.ACTION_ACCELERATE);

            objectController.bindKey(87, SimpleObjectController.ACTION_FORWARD);
            objectController.bindKey(90, SimpleObjectController.ACTION_BACK);
            objectController.bindKey(65, SimpleObjectController.ACTION_YAW_LEFT);
            objectController.bindKey(68, SimpleObjectController.ACTION_YAW_RIGHT);

            
            //カメラの調整
            //カメラはControllerに関連付けている為、x,y,zで直接位置を指定できないので
            //SimpleController.setObjectPosXYZを使用
            scene.cameraController.setObjectPosXYZ(0, -2500, 500);
            scene.cameraController.lookAtXYZ(0, 0, 500);
            scene.cameraController.update();


            //Springカメラ用Viewの作成
            var springCameraView:View = new View(stage.stageWidth, stage.stageHeight);
            springCameraView.visible=false;
            addChild(springCameraView);
            
            // SpringCameraController
            var springCamera:Camera3D = new Camera3D();

            springCamera.view = springCameraView;
            scene.container.addChild(springCamera);
            
            
            var cameraContoller:SpringCameraController=new SpringCameraController(this,springCamera,100);
            cameraContoller.target=animeObj;

            springCamera.fov=100*Math.PI/180;

            cameraContoller.mass = 30;
            cameraContoller.damping = 30;
            cameraContoller.stiffness = 1;
            cameraContoller.positionOffset = new Vector3D(50, 200, 100);
            cameraContoller.lookOffset = new Vector3D(0, 0, 0);
            
            
            
            //spaceキーでカメラの切り替え

            stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
            
            var cameraSwitch:uint = 0;
            function onKeyUp(e:KeyboardEvent = null):void {
                if (e.keyCode == Keyboard.SPACE) {
                    if (cameraSwitch==0) {
                        view.visible = true;
                        scene.view.visible = false;
                        cameraSwitch = 1;
                    } else if (cameraSwitch == 1) {
                        springCameraView.visible = true;
                        view.visible = false;
                        scene.view.visible = false;
                        cameraSwitch=2;
                    } else {
                        springCameraView.visible = false;
                        view.visible = false;
                        scene.view.visible = true;
                        cameraSwitch=0;
                    }
                }
            }
            
            stage.addEventListener(Event.RESIZE, onResize);
            function onResize(e:Event = null):void
            {
                view.width = stage.stageWidth;
                view.height = stage.stageHeight;
                
                springCameraView.width = stage.stageWidth;
                springCameraView.height = stage.stageHeight;
            }
                
            
            
            scene.onPreRender = function():void {

                objectController.update();
                cameraContoller.update();
                
                //cameraのレンダリングを切り替える為、Templateでのレンダリングは切っておく
                if (cameraSwitch==0) {
                    scene.camera.render();
                } else if (cameraSwitch == 1) {
                    camera.render();
                } else {
    
                    springCamera.render();
                }
            }
            
            
            //描画開始
            scene.startRendering();
        }

    }
    
}





import alternativ7.engine3d.controllers.SimpleObjectController;
import flash.display.InteractiveObject;
import alternativ7.engine3d.core.Object3D;
import flash.geom.Vector3D;
/**
 *
 * SpringCameraControl
 *
 * @author narutohyper
 */
class SpringCameraController extends SimpleObjectController
{
    
    private var _camTarget:Object3D;
    private var _zrot:Number = 0;

    public var mass:Number = 40;
    public var damping:Number = 4;
    public var stiffness:Number = 1;
    public var positionOffset:Vector3D = new Vector3D(0, -50, 5);
    public var lookOffset:Vector3D = new Vector3D(0, 10, 2);

    public function SpringCameraController(eventSource:InteractiveObject, object:Object3D, speed:Number, speedMultiplier:Number = 3, mouseSensitivity:Number = 1) {
        super(eventSource, object, speed, speedMultiplier, mouseSensitivity);
    }

    public function set target(t:Object3D):void {
            _camTarget=t;
    }

    public function get target():Object3D {
            return _camTarget;
    }

    public function set zrot(n:Number):void {
            _zrot = n;
            if(_zrot < 0.001) n = 0;
    }

    public function get zrot():Number {
            return _zrot;
    }

    private var _velocity:Vector3D = new Vector3D();
    private var _dv:Vector3D = new Vector3D();
    private var _stretch:Vector3D = new Vector3D();
    private var _force:Vector3D = new Vector3D();
    private var _acceleration:Vector3D = new Vector3D();

    private var _desiredPosition:Vector3D = new Vector3D();
    private var _lookAtPosition:Vector3D = new Vector3D();
    private var _xPosition:Vector3D = new Vector3D();

    override public function update():void {
        if(_camTarget != null) {

            _desiredPosition = new Vector3D(_camTarget.x,_camTarget.y,_camTarget.z);
            _desiredPosition=_desiredPosition.add(positionOffset.clone());

            _stretch.x = (object.x - _desiredPosition.x) * -stiffness;
            _stretch.y = (object.y - _desiredPosition.y) * -stiffness;
            _stretch.z = (object.z - _desiredPosition.z) * -stiffness;

            _dv.x = _velocity.x * damping;
            _dv.y = _velocity.y * damping;
            _dv.z = _velocity.z * damping;

            _force.x = _stretch.x - _dv.x;
            _force.y = _stretch.y - _dv.y;
            _force.z = _stretch.z - _dv.z;

            _acceleration.x = _force.x * (1 / mass);
            _acceleration.y = _force.y * (1 / mass);
            _acceleration.z = _force.z * (1 / mass);

            _velocity=_velocity.add(_acceleration);
            _xPosition=new Vector3D(object.x,object.y,object.z);
            _xPosition=_xPosition.add(_velocity);
            
            setObjectPos(_xPosition);

            _lookAtPosition= new Vector3D(_camTarget.x,_camTarget.y,_camTarget.z);
            _lookAtPosition=_lookAtPosition.add(lookOffset.clone());
            lookAt(_lookAtPosition);
            if(Math.abs(_zrot) > 0) object.rotationY = _zrot;
            updateObjectTransform()
        }
    }
}


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

/**
 * 車コントローラー
 * @author narutohyper
 */
class CarController extends SimpleObjectController
{
    private var _yawSpeed:Number= 1.5;
    private var _pitchSpeed:Number = 2;
        
    private var _target:Object3D;
    private var _pitchDown:Boolean;
    private var _pitchUp:Boolean;
    private var _yawLeft:Boolean;
    private var _yawRight:Boolean;

        private var _forwardKeys:Array;
        private var _backKeys:Array;
        
        private var _forward:Boolean = false;
        private var _back:Boolean = false;
    
        public function CarController(eventSource:InteractiveObject, object:Object3D, speed:Number, speedMultiplier:Number = 3, mouseSensitivity:Number = 1)
        {
                _target=object;
                _forwardKeys = [];
                _backKeys = [];
                
                super(eventSource, object, speed, speedMultiplier, mouseSensitivity);
                eventSource.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
                eventSource.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
        }
        


    public function onKeyDown(e:KeyboardEvent):void {
            var count:int = _forwardKeys.length;
            var i:int = 0;
            for (i = 0; i < count; i++)
            {
                if (_forwardKeys[i] == e.keyCode) {
                    _forward = true;
                    break;
                }
            }
            count = _backKeys.length;
            for (i = 0; i < count; i++)
            {
                if (_backKeys[i] == e.keyCode) {
                    _back = true;
                    break;
                }
            }

    }

    public function onKeyUp(e:KeyboardEvent = null):void {
            var count:int = _forwardKeys.length;
            var i:int = 0;
            for (i = 0; i < count; i++)
            {
                if (_forwardKeys[i] == e.keyCode) {
                    _forward = false;
                    break;
                }
            }
            count = _backKeys.length;
            for (i = 0; i < count; i++)
            {
                if (_backKeys[i] == e.keyCode) {
                    _back = false;
                    break;
                }
            }

    }


    override public function bindKey(keyCode:uint, action:String): void {
        switch (action) {
                    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;
                    case ACTION_FORWARD:
                        _forwardKeys.push(keyCode);
                    break;
                    case ACTION_BACK:
                        _backKeys.push(keyCode);
                    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;
    }
    public function yawRight(value:Boolean,near:Boolean=false):void {
        _yawRight = value;
    }


    override public function update(): void {
        //現在のVector3D
        var nowVector:Vector3D=new Vector3D(_target.x,_target.y,_target.z);
        if (_forward || _back) {

            if (_yawLeft) {
                    _target.rotationZ = (((_target.rotationZ / Math.PI * 180) - _yawSpeed) % 360) *    Math.PI/180;
            } else if (_yawRight) {
                    _target.rotationZ = (((_target.rotationZ / Math.PI * 180) + _yawSpeed) % 360) *    Math.PI/180;
            }
            
            if (_pitchDown) {
                    _target.rotationX=(((_target.rotationX / Math.PI * 180) + _pitchSpeed) % 360) *    Math.PI/180;
            }
            if (_pitchUp) {
                    _target.rotationX=(((_target.rotationX / Math.PI * 180) - _pitchSpeed) % 360) *    Math.PI/180;
            }
            
        }
        updateObjectTransform()
        super.update();
    }


    public function set yawSpeed(value:Number):void {
        _yawSpeed = value*Math.PI/180;
    }

    public function set pitchSpeed(value:Number):void
    {
        _pitchSpeed = value*Math.PI/180;
    }
        
        ;
}





/**
 * BasicTemplate for Alternativa3D 7.5
 * Alternativa3D 7.5を扱いやすくするためのテンプレートです
 * @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();
    }
    
    
}

Forked