テトリス25周年おめ

by junki
09'06.14ワールドルール(SRS)を追記
時間かかったあげくコード汚いけどAS3.0の練習ついでにテトリス25周年おめでと記念。消されてもしらね
♥0 | Line 888 | Modified 2009-06-14 23:21:06 | MIT License
play

ActionScript3 source code

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

// 09'06.14ワールドルール(SRS)を追記
// 時間かかったあげくコード汚いけどAS3.0の練習ついでにテトリス25周年おめでと記念。消されてもしらね
package 
{
	import flash.desktop.ClipboardTransferMode;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;

	import net.hires.debug.Stats; 

	[SWF(width="400",height="300",frameRate="60",backgroundColor="0x000000")] 
	/**
	 * ...
	 * @author junki
	 */
	public class Main extends Sprite 
	{
		
		/****************************************
		 * 変数とか宣言とか
		 *****************************************/
		
		// ブロックややこしすぎ\(^o^)/
		private const mino:Vector.<Vector.<Vector.<Boolean>>> = 
			Vector.<Vector.<Vector.<Boolean>>>([
				Vector.<Vector.<Boolean>>([
				Vector.<Boolean>([false, false, false, false]), 
				Vector.<Boolean>([true, true, true, true]), 
				Vector.<Boolean>([false, false, false, false]), 
				Vector.<Boolean>([false, false, false, false])
				]),
				Vector.<Vector.<Boolean>>([
				Vector.<Boolean>([true, false, false]), 
				Vector.<Boolean>([true, true, true]), 
				Vector.<Boolean>([false, false, false])
				]),
				Vector.<Vector.<Boolean>>([
				Vector.<Boolean>([false, false, true]), 
				Vector.<Boolean>([true, true, true]), 
				Vector.<Boolean>([false, false, false])
				]),
				Vector.<Vector.<Boolean>>([
				Vector.<Boolean>([true, true]), 
				Vector.<Boolean>([true, true])
				]),
				Vector.<Vector.<Boolean>>([
				Vector.<Boolean>([false, true, true]), 
				Vector.<Boolean>([true, true, false]), 
				Vector.<Boolean>([false, false, false])
				]),
				Vector.<Vector.<Boolean>>([
				Vector.<Boolean>([true, true, false]), 
				Vector.<Boolean>([false, true, true]), 
				Vector.<Boolean>([false, false, false])
				]),
				Vector.<Vector.<Boolean>>([
				Vector.<Boolean>([false, true, false]), 
				Vector.<Boolean>([true, true, true]), 
				Vector.<Boolean>([false, false, false])
				])
			]);
			
		// 回転法則。32(回転方向)と8(回転状態)と2(XY)を駆使汁。
		private const offsetRule:Vector.<int> = 
			Vector.<int>([
			 //左回転
			  1,  0,  1, -1,  0,  2,  1,  2,	//↑ > ←
			  1,  0,  1,  1,  0, -2,  1, -2,	//→ > ↑
			 -1,  0, -1, -1,  0,  2, -1,  2,	//↓ > →
			 -1,  0, -1,  1,  0, -2, -1, -2,	//← > ↓
			//右回転
			 -1,  0, -1, -1,  0,  2, -1,  2,	//↑ > →
			  1,  0,  1,  1,  0, -2,  1, -2,	//→ > ↓
			  1,  0,  1, -1,  0,  2,  1,  2,	//↓ > ←
			 -1,  0, -1,  1,  0, -2, -1, -2,	//← > ↑
			 0
			]);
		private const offsetRuleI:Vector.<int> = 
			Vector.<int>([
			 //左回転
			 -1,  0,  2,  0, -1, -2,  2,  1,	//↑ > ←
			  2,  0, -1,  0,  2, -1, -1,  2,	//→ > ↑
			 -2,  0,  1,  0, -2, -1,  1,  1,	//↓ > →
			 -2,  0,  1,  0,  1, -2, -2,  1,	//← > ↓
			 //右回転
			 -2,  0,  1,  0, -2, -1,  1,  2,	//↑ > →
			  2,  0, -1,  0,  2, -1, -1,  1,	//→ > ↓
			  2,  0, -1,  0, -1, -2,  2,  1,	//↓ > ←
			 -2,  0,  1,  0,  1, -2, -2,  1,	//← > ↑
			 0
			]);
		
		// ブロック色のインデックス( 0:I, 1:J, 2:L, 3:O, 4:S, 5:Z, 6:T )
		private const boxColor:Vector.<int> = 
			Vector.<int>([0x88ddff, 0x4444ee, 0xee8822, 0xeeee44, 0x44ee44, 0xff2222, 0xee22ee]);
		
		private const boxSize:int = 14;
		
		// 当たり判定用の2次元bool配列
		private var stageField:Vector.<Vector.<Boolean>> = new Vector.<Vector.<Boolean>>();
		
		// NEXT表示のint配列 pushで入れて shiftで出す。
		private const nextDisplayDigit:int = 5;
		private var nextBlock:Vector.<int> = new Vector.<int>(nextDisplayDigit);
		
		// 設置したブロックを描画する為のSprite配列
		private var stageSprite:Vector.<Sprite> = new Vector.<Sprite>(23);
		
		// ステージの横一列に存在するブロックの数を保持するint配列
		private var stageBoxCnt:Vector.<int> = new Vector.<int>(23);
		
		// ステータス
		private var level:int;
		private var score:int;
		private var fileLineCnt:int;
		private var fileLine:int;
		
		private var nextView:Sprite;
		private var gameStatus:String;
		private var fallinBlockNum:int;
		private var fallinBlock:Sprite;
		private var fallinBlockX:int;
		private var fallinBlockY:int;
		private var fallinBlockRot:int;
		private var fallinBlockAry:Vector.<Vector.<Boolean>> = new Vector.<Vector.<Boolean>>();
		
		private const moveSpeed:int = 1;
		private const moveInterval:int = 10;
		private var moveCnt:int;
		private const nextInterval:int = 10;
		private var nextCnt:int;
		private const onSpeed:int = 5;
		private var onCnt:int;
		private const fallSpeed:int = 30;
		private var fallCnt:int;
		private const eraseInterval:int = 5;
		private var eraseCnt:int;
		private var holdFlag:Boolean;
		
		private var keyHandleMoveL:int;
		private var keyHandleMoveR:int;
		private var keyHandleRotL:int;
		private var keyHandleRotR:int;
		private var keyHandleFallS:int;
		private var keyHandleFallQ:int;
		private var keyHandleHold:int;
		
		// gameStatus表示用
		private var debugf:TextField;
		
		private var kl:KeyListner;
		
		/**
		 * コンストラクタ
		 */
		public function Main():void 
		{
			stage.addChild(new Stats()); 
			createStage();
			// initStage();
			initEventListner();
			kl = new KeyListner(stage);
			
		}
		
		/****************************************
		 * 初期化とか
		 *****************************************/
		
		/**
		 * コンストラクタから一回だけ呼び出されるステージの構築メソッド
		 */
		private function createStage():void
		{
			// テキストの描画
			var startButton:Sprite = new Sprite();
			startButton = createButton("start");
			startButton.x = 30;
			startButton.y = 250;
			addChild(startButton);
			startButton.addEventListener(MouseEvent.CLICK, gameStart);
			
			var text_hold:TextField = new TextField();
			text_hold = createTextField("HOLD", 10, 15, 20, "center");
			text_hold.x = 38;
			text_hold.y = 5;
			addChild(text_hold);
			
			var text_next:TextField = new TextField();
			text_next = createTextField("NEXT", 10, 15, 20, "center");
			text_next.x = 300;
			text_next.y = 5;
			addChild(text_next);
			
			debugf = new TextField();
			debugf = createTextField("gameStatus", 20, 15, 14, "left");
			debugf.x = 30;
			debugf.y = 270;
			addChild(debugf);
			
			// ラインの描画
			var lines:Sprite = new Sprite();
			var cx:int = 130
			var cy:int = 10
			lines.graphics.lineStyle(0.5, 0xffffff);
			// lines.graphics.moveTo(cx, cy);
			// lines.graphics.lineTo(cx, box * 20);
			for (var i:int = 0; i < 21; i++ )
			{
				lines.graphics.moveTo(cx, cy + boxSize * i);
				lines.graphics.lineTo(cx+boxSize*10, cy+boxSize*i);
			}
			for (i = 0; i < 11; i++ )
			{
				lines.graphics.moveTo(cx+boxSize*i, cy);
				lines.graphics.lineTo(cx+boxSize*i, cy+boxSize*20);
			}
			addChild(lines)
			
			// 23段分のSprite
			for (i = 0; i < 23; i++ )
			{
				stageSprite[i] = new Sprite();
				// stageSprite[i].x = 130;
				// stageSprite[i].y = -32 + i * boxSize;
				addChild(stageSprite[i]);
			}
			
			// new
			level = 1;
			score = 0;
			fileLine = 0;
			fileLineCnt = 0;
			gameStatus = "pushStart";
			fallinBlockX = 0;
			fallinBlockY = 0;
			fallinBlockRot = 0;
			
			moveCnt = moveInterval;
			nextCnt = nextInterval;
			onCnt = onSpeed;
			fallCnt = fallSpeed;
			eraseCnt = eraseInterval;
			holdFlag = true;
			
			keyHandleMoveL = 0;
			keyHandleMoveR = 0;
			keyHandleRotL = 0;
			keyHandleRotR = 0;
			keyHandleFallS = 0;
			keyHandleFallQ = 0;
			keyHandleHold = 0;
			
			nextView = new Sprite();
			addChild(nextView);
			
		}
		
		/**
		 * ブロックの配置を記憶するステージの初期化
		 */
		private function initStage():void
		{
			stageField = 
				Vector.<Vector.<Boolean>>([
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]),
				
				Vector.<Boolean>([false, true, true, true, true, true, true, true, true, true, true, true, true, true]),
				Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true])
			]);
			
			for (var i:int = stageSprite.length-1; i >= 0; i-- )
			{
				removeChild(stageSprite[i]);
				stageSprite[i] = new Sprite();
				stageSprite[i].x = 130;
				stageSprite[i].y = -32 + i * boxSize;
				addChild(stageSprite[i]);
			}
		}
		
		/**
		 * ゲーム酢太ートするごとに呼び出す、諸々のステータスの初期化
		 */
		private function initGameStatus():void
		{
		
			level = 1;
			score = 0;
			fileLine = 0;
			fileLineCnt = 0;
			fallinBlockX = 0;
			fallinBlockY = 0;
			fallinBlockRot = 0;
			
			moveCnt = moveInterval;
			nextCnt = nextInterval;
			onCnt = onSpeed;
			fallCnt = fallSpeed;
			eraseCnt = eraseInterval;
			holdFlag = true;
			
			keyHandleMoveL = 0;
			keyHandleMoveR = 0;
			keyHandleRotL = 0;
			keyHandleRotR = 0;
			keyHandleFallS = 0;
			keyHandleFallQ = 0;
			keyHandleHold = 0;
			
			for (var i:int = stageBoxCnt.length; i >= 0; i--)
			{
				stageBoxCnt[i] = 0;
			}
			
			// next表示数の倍だけgetNextBlockすると初期ブロックのバラ付きがなくなる
			for (i = 0; i < 10; i++ )
			{
				getNextBlock();
			}
			displayNextBlock();
			gameStatus = "getNext";
		}
		
		/**
		 * イベントリスナー初期化
		 */
		private function initEventListner():void
		{
			
		}
		
		/****************************************
		 * ゲーム進行でよく呼ぶメソッドとか
		 *****************************************/
		
		/**
		 * 次のブロックを呼び出す
		 * @param chance 抽選回数
		 * @return num
		 */
		private function getNextBlock():int
		{
			var num:int = 0;
			var uniq:Boolean = false;
			
			for (var i:int = 0; i < 3 && !uniq; i++ )
			{
				num = Math.floor(Math.random() * 7);
				uniq = true;
				for (var j:int = 0; j < nextDisplayDigit; j++ )
				{
					if (nextBlock[j] == num)
						uniq = false;
				}
			}
			nextBlock.push(num);
			return nextBlock.shift();
		}
		
		/**
		 * ブロックの回転
		 * @param	num ブロックの種類
		 * @param	x ブロックのステージx座標
		 * @param	y ブロックのステージy座標
		 * @param	rot 回転方向(右:1 左:-1)
		 */
		private function rotate(num:int, x:int, y:int, r:int):void
		{
			var rot:int = (fallinBlockRot + r + 4) % 4;
			if (!hitBlockTest(num, x, y, rot))
			{
				removeChild(fallinBlock);
				fallinBlock = new Sprite();
				fallinBlock = createBlock(num, 102 + (x * boxSize), -32 + (y * boxSize) , rot);
				addChild(fallinBlock);
				fallinBlockRot = rot;
				
				return;
			}
			else if (r != 0)
			{
				var i:int;
				var rx:int;
				var ry:int;
				r = (r + 1) * 16 + fallinBlockRot * 8;
				//trace("SR!");
				if (num != 3) //o型以外のの回転法則
				{
					if (num != 0) //普通の回転法則
					{
						for (i = 0; i < 4; i++ )
						{
							rx = offsetRule[r + (i * 2)];
							ry = offsetRule[r + (i * 2) + 1];
							trace(r,"rot:",rot,"rx:",rx,"ry:",ry);
							if(!hitBlockTest(num, x + rx, y + ry, rot))
							{
								//trace("まわった!蔵らがまわった! : ",i);
								removeChild(fallinBlock);
								fallinBlock = new Sprite();
								fallinBlock = createBlock(num, 102 + (x * boxSize), -32 + (y * boxSize) , rot);
								fallinBlockX += rx;
								fallinBlockY += ry;
								fallinBlock.x += rx*boxSize;
								fallinBlock.y += ry*boxSize;
								addChild(fallinBlock);
								fallinBlockRot = rot;
								break;
							}
						}
					}
					else //Iの回転法則
					{
						for (i = 0; i < 4; i++ )
						{
							rx = offsetRuleI[r + (i * 2)];
							ry = offsetRuleI[r + (i * 2) + 1];
							//trace(rx,ry);
							if(!hitBlockTest(num, x + rx, y + ry, rot))
							{
								//trace("まわった!蔵らがまわった! : ",i);
								removeChild(fallinBlock);
								fallinBlock = new Sprite();
								fallinBlock = createBlock(num, 102 + (x * boxSize), -32 + (y * boxSize) , rot);
								fallinBlockX += rx;
								fallinBlockY += ry;
								fallinBlock.x += rx*boxSize;
								fallinBlock.y += ry*boxSize;
								addChild(fallinBlock);
								fallinBlockRot = rot;
								break;
							}
						}
					}
				}
			}
		}
		
		/**
		 * 当たり判定
		 * @param	num ブロックの種類
		 * @param	x ブロックのステージx座標
		 * @param	y ブロックのステージy座標
		 * @param	rot 回転状態
		 * @return	hit
		 */
		private function hitBlockTest(num:int, x:int, y:int, rot:int):Boolean
		{
			var hit:Boolean = false;
			var lng:int = new int(mino[num].length - 1);
			var i:int = 0;
			var j:int = 0;
			for (i = lng; i >= 0; i-- )
			{
				for (j = lng; j >= 0; j-- )
				{
					var xx:int = 0;
					var yy:int = 0;
					switch(rot)
					{
						case 0:
							xx = i;
							yy = j;
							break;
							
						case 1:
							xx = -j + lng;
							yy = i;
							break;
							
						case 2:
							xx = -i + lng;
							yy = -j + lng;
							break;
							
						default:
							xx = j;
							yy = -i + lng;
							break;
					}
					if ((stageField.length <= (i+y)) || (stageField[0].length <= (j+x)) || (i+y)<0 || (j+x)<0)
					{
						return true;
					}
					if (mino[num][xx][yy] && stageField[i + y][j + x])
					{
						return true;
					}
				}
			}
			return false;
		}
		
		/**
		 * ステージ(とSprite)に書き込む
		 * @param	spr ブロックのスプライト
		 * @param	num ブロックの種類
		 * @param	x ブロックのx座標
		 * @param	y ブロックのy座標
		 * @param	rot 回転状態
		 * @return	hit
		 */
		private function writeStageField(num:int, x:int, y:int, rot:int):void
		{
			var lng:int = mino[num].length - 1;
			
			var i:int = 0;
			var j:int = 0;
			var xx:int = 0;
			var yy:int = 0;
			
			for (i = lng; i >= 0; i-- )
			{
				for (j = lng; j >= 0; j-- )
				{
					switch(rot)
					{
						case 0:
							xx = i;
							yy = j;
							break;
							
						case 1:
							xx = -j + lng;
							yy = i;
							break;
							
						case 2:
							xx = -i + lng;
							yy = -j + lng;
							break;
							
						default:
							xx = j;
							yy = -i + lng;
							break;
					}
					if (mino[num][xx][yy])
					{
						var sp:Sprite = new Sprite();
						sp = createBox(num);
						stageField[i + y][j + x] = true;
						stageBoxCnt[i + y]++;
						sp.x = (j + x ) * boxSize - 28;
						sp.y = 0;
						stageSprite[i + y].addChild(sp);
					}
				}
			}
			
			gameStatus = "interval";
			nextCnt = nextInterval;
			removeChild(fallinBlock);
			eraseLine();
			gameOver();
		}
		
		/**
		 * 特定のラインにブロックが10個出来たらライン消去する
		 */
		private function eraseLine():void
		{
			var lineCnt:int = 0;
			for (var i:int = stageBoxCnt.length-1; i >= 0; i-- )
			{
				// trace("stageboxcnt : " + i + "  " + stageBoxCnt[i]);
				if (stageBoxCnt[i] > 9)
				{
					trace("eraseLine! : " + i);
					// stageBoxCnt[i] = 0;
					fileLine ++;
					
					// ラインを消しーの
					removeChild(stageSprite[i]);
					stageSprite[i] = null;
					stageSprite.splice(i, 1);
					stageField[i] = null;
					stageField.splice(i, 1); //これは比較用の真偽配列
					stageBoxCnt[i] = null;
					stageBoxCnt.splice(i, 1); //
					// 新しいスプライトを用意しーの
					//stageSprite.unshift(new Sprite());
					stageSprite.splice(0, 0, new Sprite());
					// 上に積み重ねーの
					stageSprite[0] = new Sprite();
					stageSprite[0].x = 130;
					//stageSprite[0].y = -32 - (fileLine * boxSize);
					//stageField.unshift(Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true])); //これは比較用のの真偽配列
					stageField.splice(0, 0, Vector.<Boolean>([true, true, false, false, false, false, false, false, false, false, false, false, true, true]));
					//stageBoxCnt.unshift(0);
					stageBoxCnt.splice(0, 0, 0);
					
					// addChild
					addChild(stageSprite[0]);
					
					gameStatus = "erase";
					i++;
				}
			}
		}
		
		/**
		 * 時間差をつけて空白を詰めるためだけに生まれたfunction
		 */
		private function trimDown():void
		{
			var current:int = stageSprite.length - 1;
			for (var i:int = current; i >= 0; i-- )
			{
				stageSprite[i].y = -32 + i * boxSize;
				//if (stageBoxCnt[i] > 9)
				//{
					//
					//stageBoxCnt[current] = stageBoxCnt[i];
					//stageBoxCnt[i] = 0;
					//
					//for (var j:int = stageField[current].length-3; j > 1; j-- )
					//{
						//stageField[current][j] = stageField[current][j];
						//stageField[i][j] = false;
					//}
				//}
				//else
				//{
					//current --;
				//}
			}
		}
		
		
		/**
		 * ゲームオーバーとか
		 */
		private function gameOver():void
		{
			
		}
		
		/**
		 * メインループ
		 * @param	event
		 */
		private function mainLoop(event:Event):void
		{
			switch(gameStatus)
			{
				// nextBlockから次のブロックを取得、
				// nextを再表示してブロックを初期座標に配置する。
				case "getNext":
					fallinBlock = new Sprite();
					fallinBlockNum = getNextBlock();
					
					// 落下中のブロックのセット
					fallinBlockAry = mino[fallinBlockNum];
					
					fallinBlockX = (fallinBlockNum != 3 ? 5:6); // O型ブロックの場合は出現位置がズレる。
					fallinBlockY = 1;
					displayNextBlock();
					fallinBlock = createBlock(fallinBlockNum, 102 + fallinBlockX * boxSize, -18, 0);
					addChild(fallinBlock);
					
					gameStatus = "fall";
					fallCnt = fallSpeed;
					onCnt = onSpeed;
					fileLine = 0;
					fallinBlockRot = 0;
					// break; // 走りぬけおいしいです
				// fallIntervalフレーム待ってブロックを落下させ
				// 下にブロックがあったらonSpeedフレーム待ってブロックをstageSpriteに書き込む
				// あとキー入力の受け付け
				case "fall":
					fallCnt--;
					if (fallCnt < 0)
					{
						// trace(fallinBlockX,fallinBlockY);
						fallCnt = fallSpeed;
						if (!hitBlockTest(fallinBlockNum, fallinBlockX, fallinBlockY+1, fallinBlockRot))
						{
							fallinBlockY ++;
							fallinBlock.y += boxSize;
							onCnt = onSpeed;
						}
						else
						{
							onCnt --;
							if (onCnt < 0)
							{
								onCnt = onSpeed;
								writeStageField(fallinBlockNum, fallinBlockX, fallinBlockY, fallinBlockRot);
								
								// 簡易ゲームオーバー
								if (fallinBlockY < 2)
								{
									gameStatus = "gameOver";
									break;
								}
							}
						}
					}
					// キー入力の受け付け
					key();
					break;
					
				// 一列消して詰める
				case "erase":
					if (eraseCnt < 0)
					{
						trimDown();
						gameStatus = "interval";
						eraseCnt = eraseInterval;
					}
					eraseCnt--;
					break;
					
				// ブロックが設置(or消)されてから次のブロックを降らせるまでの間
				case "interval":
					nextCnt--;
					if (nextCnt < 0)
					{
						gameStatus = "getNext";
						// 先行入力受付
						// key();
						keyHandleRotL = 1;
						keyHandleRotR = 1;
						holdFlag = true;
					}
					break;
					
				case "pause":
					
					break;
					
				case "gameOver":
					gameStatus = "pushStart";
					break;
					
				default:
					break;
			}
			debugf.text = gameStatus;
			
			function key():void
			{
				var kf:int = new int(kl.keyFlag);
				
				kf = kf << 25;
				// 左移動
				if (kf < 0)
				{
					keyHandleMoveL--;
					if (keyHandleMoveL < 0 )
					{
						if (!hitBlockTest(fallinBlockNum, fallinBlockX-1, fallinBlockY, fallinBlockRot))
						{
							fallinBlockX--;
							fallinBlock.x -= boxSize;
						}
						keyHandleMoveL = moveInterval;
					}
					if (keyHandleMoveL < 1)
					{
						if (!hitBlockTest(fallinBlockNum, fallinBlockX-1, fallinBlockY, fallinBlockRot))
						{
							fallinBlockX--;
							fallinBlock.x -= boxSize;
						}
						keyHandleMoveL = moveSpeed;
					}
				}
				else
				{
					keyHandleMoveL = -1;
				}
				
				kf = kf << 1;
				// 右移動
				if (kf < 0)
				{
					keyHandleMoveR--;
					if (keyHandleMoveR < 0 )
					{
						if (!hitBlockTest(fallinBlockNum, fallinBlockX+1, fallinBlockY, fallinBlockRot))
						{
							fallinBlockX++;
							fallinBlock.x += boxSize;
						}
						keyHandleMoveR = moveInterval;
					}
					if (keyHandleMoveR < 1)
					{
						if (!hitBlockTest(fallinBlockNum, fallinBlockX+1, fallinBlockY, fallinBlockRot))
						{
							fallinBlockX++;
							fallinBlock.x += boxSize;
						}
						keyHandleMoveR = moveSpeed;
					}
				}
				else
				{
					keyHandleMoveR = -1;
				}
				
				kf = kf << 1;
				// 左回転
				if (kf < 0)
				{
					keyHandleRotL = (keyHandleRotL < 2)?0:2;
					if (!keyHandleRotL)
					{
						rotate(fallinBlockNum, fallinBlockX, fallinBlockY, -1);
						keyHandleRotL = 2;
					}
				}
				else
				{
					keyHandleRotL = 1;
				}
				
				kf = kf << 1;
				// 右回転
				if (kf < 0)
				{
					keyHandleRotR = (keyHandleRotR < 2)?0:2;
					if (!keyHandleRotR)
					{
						rotate(fallinBlockNum, fallinBlockX, fallinBlockY, 1);
						keyHandleRotR = 2;
					}
				}
				else
				{
					keyHandleRotR = 1;
				}
				
				kf = kf << 1;
				// 落下速度上昇
				if (kf < 0)
				{
					if (keyHandleFallS < 0)
					{
						onCnt = 0;
					}
					keyHandleFallS = 0;
					if (keyHandleFallS == 0)
					{
						fallCnt -= 3;
					}
				}
				else
				{
					keyHandleFallS = -1;
				}
				
				kf = kf << 1;
				// 即時落下
				if (kf < 0)
				{
					keyHandleFallQ = (keyHandleFallQ < 2)?0:2;
					if ((!keyHandleFallQ) && (gameStatus == "fall"))
					{
						// 1fとか待ってらんないのでさっさとブロックを固定する作業に
						for (var y:int = 1; !hitBlockTest(fallinBlockNum, fallinBlockX, fallinBlockY + y, fallinBlockRot); y++ )
						{
							
						}
						fallinBlockY += y - 1;
						keyHandleFallQ = 2;
						
						writeStageField(fallinBlockNum, fallinBlockX, fallinBlockY, fallinBlockRot);
				
						// 簡易ゲームオーバー
						if (fallinBlockY < 2)
						{
							gameStatus = "gameOver";
						}
					}
				}
				else
				{
					keyHandleFallQ = 1;
				}
				kf = kf << 1;
				// ホールド
				if (kf < 0)
				{
					keyHandleHold = (keyHandleHold < 2)?0:2;
				}
				else
				{
					keyHandleHold = 1;
				}
			}
		}
		
		
		/****************************************
		 * イベントリスナとか
		 *****************************************/
		
		 /**
		  * マウスクリックで呼びだされる。initializeしてゲームスタート。
		  * @param	event
		  */
		private function gameStart(event:MouseEvent):void
		{
			if (gameStatus == "pushStart")
			{
				initStage();
				initGameStatus();
				trace("gamestart!");
				addEventListener(Event.ENTER_FRAME, mainLoop);
			}
		}
		
		/****************************************
		 * 描画とか担当のメソッド。出来る子。
		 *****************************************/
		
		/**
		 * ディスプレイにNEXTを表示する
		 */
		private function displayNextBlock():void
		{
			removeChild(nextView);
			nextView = new Sprite();
			addChild(nextView);
			var nextSprite:Vector.<Sprite> = new Vector.<Sprite>(5);
			for (var i:int = 0; i < nextDisplayDigit; i++ )
			{
				nextSprite[i] = createBlock(nextBlock[i], 300, 30+(i*32), 0);
				nextView.addChild(nextSprite[i]);
			}
		}
		
		/**
		 * テキストフィールドの作成
		 * @param	str String
		 * @param	wid width
		 * @param	hei height
		 * @param	size textSize
		 * @param	type textAlign
		 * @return
		 */
		private function createTextField(str:String, wid:int, hei:int, size:int, type:String):TextField
		{
			var format:TextFormat = new TextFormat();
			format.color = 0xffffff;
			format.size = size;
			
			var tf:TextField = new TextField;
			tf.defaultTextFormat = format;
			tf.text = str;
			tf.type = TextFieldType.DYNAMIC;
			tf.width = wid;
			tf.height = hei;
			tf.selectable = false;
			tf.border = false;
			tf.autoSize = type;
			
			return tf;
		}
		
		/**
		 * 引数の文字を入れたボタンのムービークリップを返す
		 * @param	str
		 * @return	button
		 */
		private function createButton(str:String):Sprite
		{
			var btn:Sprite = new Sprite();
			btn.buttonMode = true;
			
			var format:TextFormat = new TextFormat();
			format.size = 14;
			format.color = 0xffffff;
			
			var tf:TextField = new TextField();
			tf.text = str;
			tf.setTextFormat(format);
			tf.type = TextFieldType.DYNAMIC;
			tf.x = 0;
			tf.y = 0;
			tf.width = 80;
			tf.height = 14;
			tf.selectable = false;
			tf.autoSize = "center";
			
			var btnB:Sprite = new Sprite();
			btnB.graphics.beginFill(0x888888);
			btnB.graphics.drawRoundRect( 0, 0, 80, 18, 8);
			btnB.graphics.endFill();
			
			// テキストフィールドがボタンだと反応しなくなるのでmouseEnabledをfalseに。
			tf.mouseEnabled = false;
			
			btn.addChild(btnB);
			btn.addChild(tf);
			
			return btn;
		}
		
		/**
		 * ミノの種類を受け取ったら対応するスプライトを返す
		 * @param	colorNum 0:I, 1:J, 2:L, 3:O, 4:S, 5:Z, 6:T 
		 * @param	x 	flash内のx座標
		 * @param	y	flash内のy座標
		 * @param	rot	回転状態
		 * @return
		 */
		private function createBlock(colorNum:int, x:int, y:int, rot:int):Sprite
		{
			// trace("受け取った : " + rot);
			var sp:Sprite = new Sprite();
			var spr:Sprite = new Sprite();
			var lng:int = mino[colorNum].length - 1;
			var i:int;
			var j:int;
			for (i = lng; i >= 0; i-- )
			{
				for (j = lng; j >= 0; j-- )
				{
					if (mino[colorNum][i][j]) {
						spr = new Sprite();
						spr = createBox(colorNum);
						switch(rot)
						{
							case 0:
								spr.x = x + j * boxSize;
								spr.y = y + i * boxSize;
								break;
								
							case 1:
								spr.x = x + (-i + lng) * boxSize;
								spr.y = y + j * boxSize;
								break;
								
							case 2:
								spr.x = x + (-j + lng) * boxSize;
								spr.y = y + (-i + lng) * boxSize;
								break;
								
							default:
								spr.x = x + i * boxSize;
								spr.y = y + (-j + lng) * boxSize;
								break;
						}
						sp.addChild(spr);
					}
				}
			}
			
			return sp;
		}
		
		private function createBox(colorNum:int):Sprite
		{
			var sp:Sprite = new Sprite();
				sp.graphics.lineStyle(0.5, 0xaaaaaa);
				sp.graphics.drawRect(0 , 0, boxSize, boxSize);
				sp.graphics.beginFill(boxColor[colorNum]);
				sp.graphics.drawRect(0, 0, boxSize, boxSize);
				sp.graphics.endFill();
				sp.graphics.lineStyle(1, 0xffffff);
				sp.graphics.moveTo(1 , 13);
				sp.graphics.lineTo(2 , 2);
				sp.graphics.lineTo(13, 1);
			return sp;
		}
		
	}// end class
	
}// end package


import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;

/******************************************************************************************
 * キーの入力状態を更新するクラス
 * get KeyFlag()で8ビットのキー入力状況をget!
 * 憧れのあの子のハートもget!
 ******************************************************************************************/
class KeyListner
{
	/**
	 * 変数とか宣言しちゃう
	 */
	private var _keyFlag:int = new int(0x00);
	
	private var moveL:int = new int(37);	// 左移動
	private var moveR:int = new int(39);	// 右移動
	private var lotL:int = new int(29);		// 左回転
	private var lotR:int = new int(32);		// 右回転
	private var fallS:int = new int(40);	// 落下
	private var fallQ:int = new int(38);	// 即時落下
	private var hold:int = new int(67);		// ホールド
	 
	 
	/**
	 * コンストラクタ
	 */
	public function KeyListner(myStage:Stage):void
	{
		myStage.addEventListener(KeyboardEvent.KEY_DOWN, keyOn);
		myStage.addEventListener(KeyboardEvent.KEY_UP, keyOff);
		myStage.addEventListener(Event.DEACTIVATE, keyReset);
	}
	
	private function keyOn(event:KeyboardEvent):void
	{
		switch(event.keyCode)
		{
		case moveL:
			_keyFlag = _keyFlag | 0x40;
			break;
		case moveR:
			_keyFlag = _keyFlag | 0x20;
			break;
		case lotL:
			_keyFlag = _keyFlag | 0x10;
			break;
		case lotR:
			_keyFlag = _keyFlag | 0x08;
			break;
		case fallS:
			_keyFlag = _keyFlag | 0x04;
			break;
		case fallQ:
			_keyFlag = _keyFlag | 0x02;
			break
		case hold:
			_keyFlag = _keyFlag | 0x01;
			break;
		}
	}
	private function keyOff(event:KeyboardEvent):void
	{
		switch(event.keyCode)
		{
		case moveL:
			_keyFlag = _keyFlag & 0xbf;
			break;
		case moveR:
			_keyFlag = _keyFlag & 0xdf;
			break;
		case lotL:
			_keyFlag = _keyFlag & 0xef;
			break;
		case lotR:
			_keyFlag = _keyFlag & 0xf7;
			break;
		case fallS:
			_keyFlag = _keyFlag & 0xfb;
			break;
		case fallQ:
			_keyFlag = _keyFlag & 0xfd;
			break
		case hold:
			_keyFlag = _keyFlag & 0xfe;
			break;
		}
	}
	
	private function keyReset(event:Event):void
	{
		_keyFlag = 0;
	}
	
	public function get keyFlag():int { return _keyFlag; }
	
}// end class