"FLASH游戏开发示例"学习:俄罗斯方块

         在网上有很多俄罗斯方块的开源代码,作为一个AS的新手,俄罗斯方块也是有难度的,下面是我从这个例子中的一些粗见:

       大家都知道,在玩俄罗斯方块时,是有随机产生的四格拼板随机变换在空的游戏区域垒起来的,然后消除一行行满的格子。

      所以要考虑的就有(我是把tetrominoes称为四格拼板):

     1.四格拼板有多少种类,每个种类有不同的变换方式。

     2. 如何处理四格拼板到达棋盘底部:不能移动它,产生新的四格拼板;

     3.如何处理四格拼板的碰撞:两个四格拼板间碰撞;

     4.四格拼板的变形:该例子不是使用旋转;

     5.移除掉形成一条线的格子:要把上面四格拼板落下,

     6,游戏结束就是,四格拼板到顶。

     这个游戏的设计充分的利用了数组,特别是四格拼板的类别,以及四格拼板的变形;

四格拼板应用4*4的数组,用0表示不填充任何颜色,用1表示填充颜色,如此,便可以更加容易的

表达出各种不同类似的四格拼板。

下面是完整的代码,我实在Flash Builder里面做的

package
{
	import flash.display.*;
	import flash.display.Sprite;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.text.TextField;
	import flash.utils.Timer;

	[SWF(framerate = "30" ,backgroundColor = "0xFFFFFF" , width="400", height="490")]
	public class Tetris extends Sprite
	{
		private const TS:uint  = 24;//每格的大小
		private var fieldArray : Array;
		private var fieldSprite : Sprite;
		//四个拼板
		private var tetrominoes:Array = new Array();
		private var colors:Array = new Array();
		//放置第一个四个拼板
		private  var tetromino:Sprite;
		private var currentTetromino:uint;//代表游戏中的七种四个拼板
		private var currentRotation:uint;//代表每种四个拼板的变换形式
		private var tRow:int;// 可以等于-1,为了把某些一开始位置不在顶部的四格拼板放置在顶部               四格拼板在游戏区域的水平
		private var tCol:int;//                   垂直位置
		
		//间隔时间自动向下
		private var  timeCount:Timer = new Timer(500);
		
		//游戏状态
		private var gameOver:Boolean = false;
		
		//显示下一个四个拼版
		private var nextTetromino:uint;
		
		
		private var playAgainBtn:Sprite;
		
		public function Tetris()
		{
			startTetrisGame();
			//timeCount.addEventListener(TimerEvent.TIMER,onTime);
			//timeCount.start();
		}
		//开始游戏
		private function startTetrisGame():void{
			generateField();
			initTetrominoes();
			
			nextTetromino = Math.floor(Math.random()*7);
			
			generateTetromino();
			stage.addEventListener(KeyboardEvent.KEY_DOWN,onKDown);
		}
		//及时间隔
		private function onTime(e:TimerEvent):void{
			if(canFit(tRow+1,tCol,currentRotation)){
				
				tRow++;
				placeTetromino();
			}else{
				landTetromino();
				generateTetromino();
			}
		}
		private function drawNext():void{
			if(getChildByName("next")!=null){
				removeChild(getChildByName("next"));
			}
			var next_t:Sprite = new Sprite();
			next_t.x = 300;
			next_t.name = "next";
			addChild(next_t);
			next_t.graphics.lineStyle(0,0x000000);
			for(var i:int=0;i<tetrominoes[nextTetromino][0].length;i++){
				for(var j:int=0;j<tetrominoes[nextTetromino][0][i].length;j++){
					if(tetrominoes[nextTetromino][0][i][j] == 1){
						next_t.graphics.beginFill(colors[nextTetromino]);
						next_t.graphics.drawRect(TS*j,TS*i,TS,TS);
						next_t.graphics.endFill();
					}
				}
				
			}
		}
		private function generateField():void{
			//画上好的游戏背景
			var color:Array= new Array("0x444444","0x555555");
			//建立游戏背景格子 20*10
			fieldArray = new Array();
			fieldSprite = new Sprite();
			addChild(fieldSprite);
			fieldSprite.graphics.lineStyle(0,0x000000);
			for(var i:uint=0;i<20;i++){
				fieldArray[i] = new Array();
				for(var j:uint=0;j<10;j++){
					fieldArray[i][j] = 0;
					//fieldSprite.graphics.beginFill(0x444444);//单一颜色
					fieldSprite.graphics.beginFill(color[(j%2+i%2)%2]);
					//按模计算画棋盘
					fieldSprite.graphics.drawRect(TS*j,TS*i,TS,TS);
					fieldSprite.graphics.endFill();
				}
			}
		}
		//四个拼版
		private function initTetrominoes():void{
			//I   0代表没颜色,1代表有颜色,两行说明  条状的拼板有横竖两种类型
			tetrominoes[0] = [[[0,0,0,0],[1,1,1,1],[0,0,0,0],[0,0,0,0]],
				[[0,1,0,0],[0,1,0,0],[0,1,0,0],[0,1,0,0]]];
			colors[0] = 0x00ffff;
			//T    四种旋转模式
			tetrominoes[1] = [[[0,0,0,0],[1,1,1,0],[0,1,0,0],[0,0,0,0]],
				[[0,1,0,0],[1,1,0,0],[0,1,0,0],[0,0,0,0]],
				[[0,1,0,0],[1,1,1,0],[0,0,0,0],[0,0,0,0]],
				[[0,1,0,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]]];
			colors[1] = 0xAA00FF;
			//L
			tetrominoes[2] = [[[0,0,0,0],[1,1,1,0],[1,0,0,0],[0,0,0,0]],
				[[1,1,0,0],[0,1,0,0],[0,1,0,0],[0,0,0,0]],
				[[0,0,1,0],[1,1,1,0],[0,0,0,0],[0,0,0,0]],
				[[0,1,0,0],[0,1,0,0],[0,1,1,0],[0,0,0,0]]];
			colors[2] = 0xFFA500;
			// J
			tetrominoes[3]=[[[1,0,0,0],[1,1,1,0],[0,0,0,0],[0,0,0,0]],
				[[0,1,1,0],[0,1,0,0],[0,1,0,0],[0,0,0,0]],
				[[0,0,0,0],[1,1,1,0],[0,0,1,0],[0,0,0,0]],
				[[0,1,0,0],[0,1,0,0],[1,1,0,0],[0,0,0,0]]];
			colors[3]=0x0000FF;
			//z
			tetrominoes[4] = [[[0,0,0,0],[1,1,0,0],[0,1,1,0],[0,0,0,0]],
				[[0,0,1,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]]];
			colors[4] = 0xFF0000;
			//s
			tetrominoes[5] = [[[0,0,0,0],[0,1,1,0],[1,1,0,0],[0,0,0,0]],
				[[0,1,0,0],[0,1,1,0],[0,0,1,0],[0,0,0,0]]];
			colors[5] = 0x00FF00;
			//o
			tetrominoes[6] = [[[0,1,1,0],[0,1,1,0],[0,0,0,0],[0,0,0,0]]];
			colors[6] = 0xFFFF00;
		}
		private function generateTetromino():void{
			if(! gameOver){
				currentTetromino = nextTetromino;
				nextTetromino = Math.floor(Math.random()*7);
				drawNext();
				currentTetromino = Math.floor(Math.random()*7);
				//随机获取任意一种四格拼板 即(0-6 )七个数字
				currentRotation = 0;
				tRow = 0;//在顶部
				if(tetrominoes[currentTetromino][0][0].indexOf(1) == -1){
					tRow = -1;
				}
				tCol = 3;//第三行
				drawTetromino();//根据获取的四格拼板类型进行绘制
			}
			if(canFit(tRow,tCol,currentRotation)){
				timeCount.addEventListener(TimerEvent.TIMER,onTime);
				timeCount.start();
			}else{
				gameOver = true;
				playAgainTetris();
			}
		}
		private function playAgainTetris():void{
			playAgainBtn = new Sprite();
			playAgainBtn.graphics.beginFill(0x00ffff);
			playAgainBtn.graphics.drawRect(100,200,100,30);
			playAgainBtn.graphics.endFill();
			addChild(playAgainBtn);
			var playAgainText:TextField = new TextField();
			playAgainText.text = "再玩一次";
			playAgainBtn.addChild(playAgainText);
			playAgainText.x = 130;
			playAgainText.y = 205;
			playAgainBtn.addEventListener(MouseEvent.CLICK,playAgainHandler);
			playAgainBtn.buttonMode = true;
		}
		private function playAgainHandler(e:MouseEvent):void{
			removeChild(playAgainBtn);
			gameOver = false;
			startTetrisGame();
		}
		private function drawTetromino():void{
			var ct:uint = currentTetromino;
			tetromino = new Sprite();
			addChild(tetromino);
			tetromino.graphics.lineStyle(0,0x000000);
			for(var i: int = 0;i<tetrominoes[ct][currentRotation].length;i++){
				//tetrominoes[ct] 最大为四,最小为一
				//tetrominoes[ct][currentRotation] 每一个有四行
				for(var j:int = 0;j<tetrominoes[ct][currentRotation][i].length;j++){
					//每行有四个,都要遍历一遍,查询每一行中得每个数值
					if(tetrominoes[ct][currentRotation][i][j] == 1){
						//如果值为1,填色
						tetromino.graphics.beginFill(colors[ct]);
						tetromino.graphics.drawRect(TS*j,TS*i,TS,TS);
					}
				}
			}
			placeTetromino();
		}
		//摆放的位置
		private function placeTetromino():void{
			tetromino.x = tCol * TS;
			tetromino.y = tRow * TS;
		}
		private function onKDown(e:KeyboardEvent):void{
			//trace("go");
			if(!gameOver){
				switch(e.keyCode){
					case 37 :
						if(canFit(tRow,tCol-1,currentRotation)){
							//为true是执行
							tCol--;
							placeTetromino();
						}
						break;
					
					//变形处理
					case 38:
						var ct:uint = currentRotation;
						//rot取决与【currentTetromino】
						var rot:uint = (ct+1)%tetrominoes[currentTetromino].length;
						if(canFit(tRow,tCol,rot)){
							currentRotation = rot;
							removeChild(tetromino);
							drawTetromino();
							placeTetromino();
						}
						break;
					case 39:
						if(canFit(tRow,tCol+1,currentRotation)){
							tCol++;
							placeTetromino();
						}
						break;
					case 40:
						if(canFit(tRow+1,tCol,currentRotation)){
							tRow++;
							placeTetromino();
						}else{
							landTetromino();
							generateTetromino();
						}
						break;
				}
			}
			
		}
		//检测两个四格拼板的碰撞情况,以及不超出游戏区域
		private function canFit(row:int,col:int,side:uint):Boolean{
			var ct:uint = currentTetromino;
			for(var i:int=0;i<tetrominoes[ct][side].length;i++){
				for(var j:int=0;j<tetrominoes[ct][side][i].length;j++){
					if(tetrominoes[ct][side][i][j] == 1){
						//超过左边边界
						if(col+j<0){
							return false;
						}
						//超过右边边界
						if(col+j>9){
							return false;
						}
						//超出底部
						if(row+i>19){
							return false;
						}
						
						//解决碰撞
						
						//到了另一个四个拼版
						if(fieldArray[row+i][col+j] == 1){
							return false;
						}
					}
				}
			}
			return true;
		}
		
		//着落
		private function landTetromino():void{
			var ct:uint = currentTetromino;
			var landed:Sprite;
			for(var i:int=0;i<tetrominoes[ct][currentRotation].length;i++){
				for(var j:int=0;j<tetrominoes[ct][currentRotation][i].length;j++){
					if(tetrominoes[ct][currentRotation][i][j] == 1){
						landed = new Sprite();
						addChild(landed);
						landed.graphics.lineStyle(0,0x000000);
						landed.graphics.beginFill(colors[currentTetromino]);
						landed.graphics.drawRect(TS*(tCol+j),TS*(tRow+i),TS,TS);
						landed.graphics.endFill();
						
						landed.name = "r"+(tRow+i)+"c"+(tCol+j);
						fieldArray[tRow+i][tCol+j] = 1;
					}
				}
			}
			removeChild(tetromino);
			timeCount.removeEventListener(TimerEvent.TIMER,onTime);
			timeCount.stop();
			checkForLines();
			
		}
//检测是否形成一条线
  private function checkForLines():void{ for(var i:int=0;i<20;i++){ if(fieldArray[i].indexOf(0) == -1){ for(var j:int=0;j<10;j++){ fieldArray[i][j] = 0; removeChild(getChildByName("r"+i+"c"+j)); } //***************************************** for(j=i;j>=0;j--){ for(var k:int=0;k<10;k++){ if(fieldArray[j][k] == 1){ fieldArray[j][k] = 0; fieldArray[j+1][k] =1; getChildByName("r"+j+"c"+k).y += TS; getChildByName("r"+j+"c"+k).name = "r"+(j+1)+"c"+k; } } } } } } } }

 

 

注:第一次写这种日志,请见谅。。。。。

Clience

 

  

posted on 2011-11-20 12:56  Clience.Kang  阅读(409)  评论(0)    收藏  举报