package {
    import flash.display.*;
    import flash.events.*;
    import flash.ui.Keyboard;

    import org.papervision3d.scenes.*;
    import org.papervision3d.objects.*;
    import org.papervision3d.cameras.*;
    import org.papervision3d.materials.*;
 
    public class ClearCube extends Sprite
    {
        private var container  : Sprite;
        private var scene      : MovieScene3D;
        private var camera     : Camera3D;
        private var rootNode   : DisplayObject3D;
        
        //操作オブジェクト座標管理用
        private var opCubeX    : Number;
        private var opCubeZ    : Number;

        //キューブ削除管理用配列
        //                               →→→→→→→X軸→→→→→→→
        private var opCubeMap  : Array = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //1列目  ↓
                                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //2列目  ↓
                                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //3列目  ↓
                                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //4列目  ↓
                                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //5列目  Z
                                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //6列目  軸
                                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //7列目  ↓
                                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //8列目  ↓
                                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //9列目  ↓
                                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //10列目 ↓
                                         ];

        private var cubeObj    : Cube; //土台用キューブ作成に使用
        private var material   : ColorMaterial; //土台用キューブのためのマテリアル

        private var cubeObjOp  : Cube; //操作用キューブ
        private var materialOp : ColorMaterial; //操作用キューブのためのマテリアル

        private var left_flg   : Boolean = false; //LEFTキー押しっぱなしチェック
        private var right_flg  : Boolean = false; //RIGHTキー押しっぱなしチェック
        private var up_flg     : Boolean = false; //UPキー押しっぱなしチェック
        private var down_flg   : Boolean = false; //DOWNキー押しっぱなしチェック

        //---------------------------------------------Constructor
        public function ClearCube():void
        {
            stage.frameRate = 60;
            stage.quality   = "MEDIUM";
            stage.scaleMode = "noScale";
            stage.align = StageAlign.TOP_LEFT;
 
            //コンテナ生成
            container = new Sprite();
            container.x = stage.stageWidth / 2;
            container.y = stage.stageHeight / 2;
            stage.addChild( container );
 
            //シーン生成
            scene = new MovieScene3D( container );
 
            //rootNode生成
            rootNode = new DisplayObject3D();
            scene.addChild( rootNode );

            //100キューブ使用して土台を作る
            var materialColorCheck:Number = 0; //マテリアル色判定用 1の場合白色、0の場合灰色

            //1列10キューブの列を10列分作成
            for (var h:Number = 0; h < 10; h++){

                if (h%2 == 0) { //偶数列の場合最初に灰色を設定
                    materialColorCheck = 0;
                } else { //奇数列の場合最初に白色を設定
                    materialColorCheck = 1;
                }

                //1列分の10キューブを作成
	            for (var i:Number = 0; i < 10; i++){
                    //同じ列のキューブの色に白色と灰色を交互に設定
                    if (materialColorCheck == 1) { //1の場合、白色マテリアル設定後、0を設定
                        material = new ColorMaterial( 0xffffff, 1 );
                        materialColorCheck = 0;
                    } else { //0の場合、灰色マテリアル設定後、1を設定
                        material = new ColorMaterial( 0xdddddd, 1 );
                        materialColorCheck = 1;
                    }
	                material.doubleSided = true;
	                material.smooth = true;
	                //Cubeオブジェクト生成
	                cubeObj = new Cube(material, 400, 400, 400, 2, 2, 2);
	                cubeObj.x = -1800 + (400 * i);
	                cubeObj.z = 400 * h;
                    //キューブオブジェクトに名前を割り振り
	                rootNode.addChild(cubeObj, "cubeZ" + h + "_X" + i); //オブジェクト名の例:"cubeZ7_X3"
            	}
            }

            //操作用オブジェクト設定(青色)
            materialOp = new ColorMaterial( 0x0000ff, 1 );
            materialOp.doubleSided = true
            materialOp.smooth = true;
            //操作用オブジェクト生成
            cubeObjOp = new Cube(materialOp, 400, 400, 400, 2, 2, 2);
            cubeObjOp.x = -1800;
            cubeObjOp.y = 400;
            rootNode.addChild(cubeObjOp);
            //操作用オブジェクト座標を初期化
            opCubeX = 0; //0〜9
            opCubeZ = 0; //0〜9

            //camera設定
            camera = new Camera3D();
            camera.zoom = 1;
            camera.x = 0;
            camera.y = 2000;

            stage.addEventListener(Event.ENTER_FRAME, loop);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); //キーが押された状態を保持
            stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); //キーが押されてから後、キーが離されたときのみオブジェクト操作可
            stage.addEventListener(MouseEvent.CLICK, onClick); //
            stage.addEventListener(Event.DEACTIVATE, onDeactivate);
            stage.addEventListener(Event.RESIZE, onStageResize);
        }

        //---------------------------------------------loop
        private function loop(event:Event):void{
            scene.renderCamera( camera );
        }

        //---------------------------------------------onKeyDown
        //キーが押された場合、押された状態を保持(trueで押された状態)
        private function onKeyDown(event:KeyboardEvent):void{       
            if( event.keyCode == Keyboard.LEFT ) {
                left_flg = true;
            } else if ( event.keyCode == Keyboard.RIGHT ) {
                right_flg = true;
            } else if ( event.keyCode == Keyboard.UP ) {
                up_flg = true;
            } else if ( event.keyCode == Keyboard.DOWN ) {
                down_flg = true;
            }
        }

        //---------------------------------------------onKeyUp
        //キーが押されてから後、キーが離された場合にオブジェクト操作を行う
        private function onKeyUp(event:KeyboardEvent):void{       
            if( event.keyCode == Keyboard.LEFT ) {
               if (cubeObjOp.x >= -1400) {
                   cubeObjOp.x -= 400;
                   opCubeX -= 1; //0〜9
                   clearCube();
               }
               left_flg = false;
            } else if ( event.keyCode == Keyboard.RIGHT ) {
               if (cubeObjOp.x <= 1400) {
                   cubeObjOp.x += 400;
                   opCubeX += 1; //0〜9
                   clearCube();
               }
               right_flg = false;
            } else if ( event.keyCode == Keyboard.UP ) {
               if (cubeObjOp.z <= 3200) {
                   cubeObjOp.z += 400;
                   opCubeZ += 1; //0〜9
                   clearCube();
               }
               up_flg = false;
            } else if ( event.keyCode == Keyboard.DOWN ) {
               if (cubeObjOp.z >= 400) {
                   cubeObjOp.z -= 400;
                   opCubeZ -= 1; //0〜9
                   clearCube();
               }
               down_flg = false;
            }

            scene.renderCamera( camera );
        }

        //---------------------------------------------onClick
        //クリックされる毎にカメラの座標を変更
        private function onClick(event:MouseEvent):void{       
            camera.y -= 500;
            if (camera.y < 0) {
                camera.y = 2000;
            }
            scene.renderCamera( camera );
        }

        //---------------------------------------------clearCube
        //操作オブジェクトが通過したキューブを削除
        private function clearCube():void{
            if (opCubeMap[opCubeZ][opCubeX] == 0) { //すでに削除されているチェック
                opCubeMap[opCubeZ][opCubeX] == 1; //削除フラグをたてる
                var tempName:String = "cubeZ" + opCubeZ + "_X" + opCubeX;
                rootNode.removeChildByName(tempName); //指定キューブ削除
            }
        }

        //---------------------------------------------onDeactivate
        //キーボードを押しながらFlashを非アクティブにすると押しっぱなしになってしまう状態を避ける
		private function onDeactivate(event:Event):void{
		    left_flg = false;
		    right_flg = false;
		    up_flg = false;
		    down_flg = false;
		}

        //---------------------------------------------onStageResize
        private function onStageResize(event:Event):void{
             container.x = this.stage.stageWidth  / 2;
             container.y = this.stage.stageHeight / 2;
        }
    }
}