as3 俄罗斯方块 优化 美化版

最近在研究俄罗斯方块(主要用于怀旧~大笑))。下载了别人的代码来参考,发现一些bug,修改后再进行了一些美化(就是改改颜色,改改格子的形状)。
有问题可以回帖提问!!尽力回答!!希望对你有用。

要点
0.用timer或者enterframe等来计时,每过一定时间就向下移动!
1.数组保存整个游戏的格子。

2.每种形状的格子用数组写死,定义好。另一个数组保存正在下落的形状格子。

3.我通过graphic来绘制整个游戏的格子。
5.剩下的主要就是一些能否旋转,能否移动,游戏是否结束的逻辑判断
6.如果你要用的话需要做一些简单的修改,把报错的地方删掉就行。不影响游戏逻辑和运行

贴上 demo演示地址 (个人网站,还在优化中。欢迎吐槽)。。


package Core  {
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.TimerEvent;
	import flash.system.System;
	import flash.text.TextField;
	import flash.ui.Keyboard;
	import flash.utils.Timer;
	import flash.utils.getTimer;
	import flash.utils.setTimeout;
	
	public class Tetris extends Sprite 
	{
		
		/**
		 * 游戏每多少秒移动一次
		 */		
		private var _gameSpeed:Number ;
		/**
		 * 总分数 
		 */		
		private var _totalPoint:int;
		/**分数的基数*/
		private var _pointBase:Number;
		/**当前消除的积分*/
		private var _curPoint:int;
		
		private var _totalPointLabel:TextField;
		
		private var _cellDistance:Number;
		
		private var _cellSize:Number;//边长
		private var numRows:int;//行数
		private var numCols:int;//列数
		private var _sceneArr:Array;//场景(格子的世界)
		
		/**网格偏移值*/
		private var _netOffsetX:int;
		/**网格偏移值*/
		private var _netOffsetY:int;
		/**正在下落的砖头数组*/
		private var _movingBrickArr:Array;//砖头数组
		private var brickX:int;//砖头的坐标(格子世界数组下标)
		private var brickY:int;
		private var downSpeed:int = 1;//向下移动速度
		private var xSpeed:int = 1;
		private var ticker:Timer;//计时器
		private var moveType:String = "down"; //移动类型
		private var canMove:Array = new Array(); //该方向上可否移动 数组索引012分别表示为左右下,
		
		private var p_stage:Stage;

		private var curNum:int;
		
		public function Tetris(_stage:Stage) 
		{
			p_stage = _stage;
			_totalPointLabel = new TextField();
			_totalPointLabel.x = 50;
			_totalPointLabel.y = 10;
			addChild(_totalPointLabel);
			
			_cellDistance = 3;
			
			init();
			
		}
		
		//初始化数据
		private function init():void
		{
			_totalPoint = 0;
			_pointBase = 100;
			
			_cellSize = 30
			_gameSpeed = 0.5;
			
			
			
			
			//行值=舞台高/边长
			numRows = 20//Math.floor(p_stage.stageHeight / side);
			numCols = 10//Math.floor(p_stage.stageWidth / side);
			
				var netWidth:int = numCols * (_cellSize + _cellDistance);
				var netHeight:int = numRows * (_cellSize + _cellDistance);
			_netOffsetX = p_stage.stageWidth - netWidth >> 1;
			_netOffsetY = p_stage.stageHeight - netHeight >> 1;
				
			//初始化世界
			_sceneArr = new Array();
			for (var i:int=0; i<numRows; i++) 
				
			{
				_sceneArr[i] = [];
				for (var j:int=0; j<numCols; j++) 
				{
					_sceneArr[i][j] = 0;
					
				}
			}
			p_stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);//监听按下
			
			
			//创建计时器
			ticker = new Timer(500);
//			ticker.addEventListener(TimerEvent.TIMER, onTick);//用这个玩久了会出bug..
			ticker.start();
						this.addEventListener(Event.ENTER_FRAME,onTick);
			createBrick();
			initScene();
		}
		
		private function onTick(ev:Event):void {
			//trace("D"+blankD+" U"+blankU+" L"+blankL+" R"+blankR);
			
			
			if(curNum == p_stage.frameRate / (1 / _gameSpeed) )
			{
				curNum = 0;
				checkHit("down");
				moveBrick("down");
			}
			else
			{
				curNum ++;
			}
			
		}
		
		//刷新场景
		private function initScene():void 
		{
			graphics.clear();
			for (var i:int=0; i<numRows; i++) 
			{
				for (var j:int=0; j<numCols; j++) 
				{
					graphics.lineStyle(0,0,0);
					if (_sceneArr[i][j] == 0) 
					{
						graphics.beginFill(0xf8f8f8);
					} 
					else if (_sceneArr[i][j] == 1) 
					{
						graphics.beginFill(0x04B3D3);
					} 
					else if (_sceneArr[i][j]==2) 
					{
						graphics.beginFill(0x575657);
					}
					graphics.drawRoundRect(j*(_cellSize + _cellDistance) + _netOffsetX, i*(_cellDistance+_cellSize) + _netOffsetY, _cellSize, _cellSize,8,8);
				}
				graphics.endFill();
			}
		}
		
		
		//创建砖块
		private function createBrick():void {
			//砖块数组
			_movingBrickArr= new Array();
			var randNum:Number = Math.random();
			_movingBrickArr = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
			if (randNum < 0.2) {
				_movingBrickArr = [
					[0,0,0,0],
					[0,1,0,0],
					[0,1,0,0],
					[0,1,1,0]
				];
			} else if (randNum <0.4) {
				_movingBrickArr = [
					[0,0,0,0],
					[0,1,1,0],
					[0,1,1,0],
					[0,0,0,0],
				];
			} else if (randNum <0.6) {
				_movingBrickArr = [
					[0,1,0,0],
					[0,1,0,0],
					[0,1,0,0],
					[0,1,0,0]
				];
			} else if (randNum <0.7) {
				_movingBrickArr = [
					[0,0,0,0],
					[0,1,0,0],
					[1,1,1,0],
					[0,0,0,0]
				];
			} else if (randNum<0.8) {
				_movingBrickArr = [
					[0,0,0,0],
					[1,1,0,0],
					[0,1,1,0],
					[0,0,0,0],
				];
			} else {
				_movingBrickArr = [
					[0,0,0,0],
					[0,1,1,0],
					[1,1,0,0],
					[0,0,0,0]
				];
			}
			brickX = 5;
			brickY = 0;
			
			updateToScene();
		}
		//===================控制砖块移动模块=========================================================
		//键盘按下控制方向
		private function onKeyDown(ev:KeyboardEvent):void 
		{
			switch (ev.keyCode) 
			{
				case Keyboard.UP ://旋转
					//trace(canRoll());
					moveType = "roll";
					break;
				case Keyboard.DOWN :
					moveType = "down";
					break;
				case Keyboard.LEFT :
					moveType = "left";
					break;
				case Keyboard.RIGHT :
					moveType = "right";
					break;
				default :
					break;
				
			}
			checkHit(moveType);
			moveBrick(moveType);
		}
		
		//移动砖块
		private function moveBrick(moveType:String):void 
		{
			//trace("canMove "+canMove);
			switch (moveType) 
			{
				case "roll" ://旋转整个砖块数组
					if(canRoll())
					{
						_movingBrickArr = roll(_movingBrickArr);
						for (var i:int=0; i<4; i++) 
						{
							for (var j:int=0; j<4; j++) 
							{
								_sceneArr[brickY + i][brickX + j] = _movingBrickArr[i][j];
							}
						}
					}
					break;
				
				case "down" ://下
					if (canMove[2] == 1) 
					{
						clearBrick();
						brickY += downSpeed;
						//trace(getTimer());
						updateToScene();
					}
					break;
				case "left" ://左
					if (canMove[0]==1) 
					{
						clearBrick();
						brickX-=downSpeed;
						updateToScene();
					}
					break;
				case "right" ://右
					if (canMove[1]==1) 
					{
						clearBrick();
						brickX+=downSpeed;
						updateToScene();
					}
					break;
				
				default :
					break;
			}
			initScene();
		}
		
		//砖块数组的里的 1 更新到场景里
		private function updateToScene():void 
		{
			//trace(blankD,blankR);
			for (var i:int=blankU; i<4/*-blankD*/; i++) 
			{
				for (var j:int=blankL; j<4/*-blankR*/; j++) 
				{
					if (_movingBrickArr[i][j]==1) 
					{
						_sceneArr[brickY+i][brickX+j]=_movingBrickArr[i][j];
						//trace("brickY",brickY);
					}
				}
			}
		}
		
		//清楚移动前的砖块
		private function clearBrick():void 
		{
			for (var i:int=blankU; i<4/*-blankD*/; i++) 
			{
				for (var j:int=blankL; j<4/*-blankR*/; j++) 
				{
					if (_movingBrickArr[i][j]==1) 
					{
						_sceneArr[brickY+i][brickX+j]=0;
					}
				}
			}
		}
		
		//旋转矩阵
		private function roll(oldArr:Array):Array 
		{
			var newArr:Array = new Array();
			for (var i:int=0; i<4; i++) 
			{
				newArr[i]=new Array(4);
				for (var j:int=0; j<4; j++) 
				{
					newArr[i][j]=oldArr[j][3-i];
				}
			}
			return newArr;
		}
		//======================================检测模块===========================
		//------------检测空白行数---------------------------
		//检测砖块数组下方的空白行数
		private function get blankD():int {
			var blankD:int=0;
			for (var i:int=3; i>1; i--) {
				for (var j:int=0; j<4; j++) {
					if (_movingBrickArr[i][j]==1) {
						return blankD;
					}
				}
				blankD++;
			}
			return blankD;
		}
		//检测砖块数组上方的空白行数
		private function get blankU():int {
			var blankU:int=0;
			for (var i:int=0; i<4; i++) {
				for (var j:int=0; j<4; j++) {
					if (_movingBrickArr[i][j]==1) {
						return blankU;
					}
				}
				blankU++;
			}
			return blankU;
		}
		
		/**
		 * //检测砖块数组右方的空白行数
		 * @return 
		 * 
		 */		
		private function get blankR():int {
			var blankR:int=0;
			for (var j:int=3; j>1; j--) {
				for (var i:int=0; i<4; i++) {
					if (_movingBrickArr[i][j]==1) {
						return blankR;
					}
				}
				blankR++;
			}
			return blankR;
		}
		
		//检测砖块数组左方的空白行数
		private function get blankL():int {
			var blankL:int=0;
			for (var j:int=0; j<3; j++) {
				for (var i:int=0; i<4; i++) {
					if (_movingBrickArr[i][j]==1) {
						return blankL;
					}
				}
				blankL++;
			}
			return blankL;
		}
		
		
		//------------碰撞检测模块---------------------------
		//碰撞检测
		public function checkHit(moveType:String):void 
		{
			canMove=[1,1,1];//先初始化1,全能移动。哪个方向检测到将碰撞,则该方向为0
			for (var i:int=blankU; i<4-blankD; i++) 
			{
				for (var j:int=blankL; j<4-blankR; j++) 
				{
					if (_movingBrickArr[i][j]==1) 
					{//检测砖块里1的单元格附近的单元格
						switch (moveType) 
						{
							case "left" :
								var hitL:Boolean=checkCell(brickY+i,brickX+j-1,"hitL");//左
								break;
							case "right" :
								var hitR:Boolean=checkCell(brickY+i,brickX+j+1,"hitR");//右
								break;
							case "down" :
								var hitD:Boolean=checkCell(brickY+i+1,brickX+j,"hitD");//下
								break;
							default :
								break;
						}
						if (hitL) 
						{
							canMove[0]=0;
						}//左 只要砖块中有一个说左不能走,就不能走 
						if (hitR) 
						{
							canMove[1]=0;
						}//右
						if (hitD) 
						{
							canMove[2]=0;
						}//下
					}
				}
			}
		}
		
		//检测该单元格可否移动
		private function checkCell(i:int,j:int,hitType:String):Boolean 
		{
			switch (hitType) 
			{
				case "hitL" :
					if (j<0||_sceneArr[i][j]==null||_sceneArr[i][j]==2) 
					{
						//trace("hitL");
						return true;
					}
					return false;
					break;
				
				case "hitR" :
					if (j>=numCols||_sceneArr[i][j]==null||_sceneArr[i][j]==2) 
					{
						//trace("hitR");
						return true;
					}
					return false;
					break;
				
				case "hitD" :
					if (i>=numRows||_sceneArr[i][j]==null||_sceneArr[i][j]==2) {
						//trace("hitD");
						floor();
						return true;
					}
					return false;
					break;
				default :
					
					break;
			}
			return false;
		}
		
		//砖块着陆后的各种反应,玩过的懂的
		private function floor():void 
		{
			for (var i:int=blankU; i<4-blankD; i++) 
			{
				for (var j:int=blankL; j<4-blankR; j++) 
				{
					if (_movingBrickArr[i][j]==1) 
					{
						_movingBrickArr[i][j]=2;
						1;
						_sceneArr[brickY+i][brickX+j]=_movingBrickArr[i][j];
					}
				}
			}
			checkLine(); //检测消行
			createBrick(); //创建新的方块
			checkLose(); //检测游戏结束
		}
		
		//---------------检测可否旋转----------------------
		
		//检测砖块可否旋转
		private function canRoll():Boolean 
		{
			if(brickX<=0 || brickX+3 >=numCols || brickY+3 >= numRows || brickX <= 0) {//靠近边缘
				return false;
			} 
			for(var i:int=0; i<4; i++) 
			{
				if(brickY+4 >= numRows ||  _sceneArr[brickY+4][brickX+i]==2){ //下  ps brickY+4 >= numRows ||  增加了上下边缘的判断。
					return false;
				} 
			}
			for(i=0; i<4; i++) 
			{
				if(_sceneArr[brickY+i][brickX-1]==2){ //左
					return false;
				} 
			}
			for(i=0; i<4; i++) 
			{
				if(_sceneArr[brickY+i][brickX+4]==2){ //右
					return false;
				}
			}
			for(i=0; i<4; i++) 
			{
				if(brickY <= 0 || _sceneArr[brickY-1][brickX+i]==2){ //上   ps brickY+4 >= numRows ||  增加了上下边缘的判断。
					return false;
				} 
			}
			return true;
		}
		
		//=====================游戏规则模块======================================================
		
		//-------------------------消行-------------------------
		
		//行检测,检测出哪些行要消
		private function checkLine():void 
		{
			var totalLine:int = 0;
			_curPoint = 0;
			for (var i:int=numRows-1; i>=0; i--) 
			{
				var canClear:Boolean=true;
				for (var j:int=0; j<numCols; j++) 
				{
					if (_sceneArr[i][j]!=2) {
						canClear=false;   //这行只要有一个不是2,则不消,全是2才消行
					}
				}
				if (canClear) 
				{
					totalLine ++;
					clearLine(i);
					i++; //这个i++很必要,这行被消,上面那行下来,必须重新检测这行
				}
			}
			
			_curPoint = totalLine * totalLine * _pointBase;
			_totalPoint += _curPoint;
			_totalPointLabel.text = "" + _totalPoint;
		}
		//得到该行,消之;上面的2都下降index行
		private function clearLine(index:int):void 
		{
			for (var k:int=0; k<numCols; k++) 
			{
				_sceneArr[index][k]=0;
			}
			for (var i:int=index-1; i>=0; i--) 
			{
				for (var j:int=0; j<numCols; j++) 
				{
					if (_sceneArr[i][j]==2) 
					{
						_sceneArr[i+1][j]=_sceneArr[i][j];
						_sceneArr[i][j]=0;
					}
				}
			}
		}
		//-------------------------游戏结束-------------------------
		private function checkLose():void {
			var isLost:Boolean = false;
			for (var i:int=3; i>=0; i--) {
				for (var j:int=0; j<numCols; j++) {
					if (_sceneArr[i][j]==2) {
						isLost = true;
					}
				}
			}
			if(isLost) 
			{
				PhpCC.UpdateNewRank("testnew"+Math.round(Math.random()*100),_totalPoint);
				init();
			} 
		}
		
	}
}


贴上 demo演示地址 (个人网站,还在优化中。欢迎吐槽)。。

















评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫叔大鸭梨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值