Switch Cameras [Alternativa3D 7.6 TIPS]
2台のカメラを使用して、視点の切り替えを行います。
やり方は、
Viewとカメラを2セット用意して、SPACEキーでViewの表示をカメラのレンダリングの有無を切り替えるといった感じ。
ちなみに、Ver7.5.1では1つのViewを複数のカメラで共有し、カメラのレンダリングの有無を切り替えるだけで、出来るようになります。
なお、全角入力になっていると、スペースキーが利かない場合があります。
2011/01/12 7.5から7.6仕様に変更
/**
* Copyright narutohyper ( http://wonderfl.net/user/narutohyper )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/52Ll
*/
// 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.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 = 50;
//車載カメラ用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();
//spaceキーでカメラの切り替え
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
var cameraSwitch:uint = 0;
var switchFlag:Boolean = true;
function onKeyDown(e:KeyboardEvent = null):void {
if (e.keyCode == Keyboard.SPACE && switchFlag) {
if (cameraSwitch==0) {
view.visible = true;
scene.view.visible = false;
cameraSwitch=1;
} else {
view.visible = false;
scene.view.visible = true;
cameraSwitch=0;
}
switchFlag=false;
}
}
function onKeyUp(e:KeyboardEvent = null):void {
if (e.keyCode == Keyboard.SPACE) {
switchFlag=true;
}
}
stage.addEventListener(Event.RESIZE, onResize);
function onResize(e:Event = null):void
{
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}
scene.onPreRender = function():void {
objectController.update();
//cameraのレンダリングを切り替える為、Templateでのレンダリングは切っておく
if (cameraSwitch==0) {
scene.camera.render();
} else {
camera.render();
}
}
//描画開始
scene.startRendering();
}
}
}
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();
}
}