JavaScript, 实现俄罗斯方块小游戏

原创 2012年06月30日 09:25:52
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>俄罗斯方块</title>
<style type="text/css">
	body{ width:530px; background:#F7F7F7; margin:20px auto}
	table#gameBoard{ border:1px solid black; border-collapse: collapse; float:left;}
	table#gameBoard td{ width:30px; height:30px; border: 1px dotted #0cc;}
	div#gameControl{ widows:160; float:right; height: 200px;; line-height: 200px;}
	.font{ font-family:'微软雅黑'; font-size:18px; text-align:center;}
	div input { width: 60px; height:25px; }

</style>
<script type="text/javascript">
	

	var T = TETRIS = {
		aBoardGrids : [],
		aShapes: [
			[0xCC00], 
			[0x8888, 0xF00], 
			[0x8C40, 0x6C00], 
			[0x4C80, 0xC600], 
			[0x44C0, 0x8E00, 0xC880, 0xE200], 
			[0x88C0, 0xE800, 0xC440, 0x2E00], 
			[0x4E00, 0x8C80, 0xE400, 0x4C40]
		],																		//代表所有方块的形状数
		init : function(){
			this.oDomBoard = document.getElementById("gameBoard");
			this.oDomScore = document.getElementById("score");
			this.aBoardGrids = new Array(18);
			for (var rows = 0 ; rows < 18 ; rows++){
				this.aBoardGrids[rows] = new Array(10);
				var oDomTr = this.oDomBoard.insertRow(-1);
				for	(var cols = 0 ; cols < 10 ; cols++){
					this.aBoardGrids[rows][cols] = 0;
					oDomTr.insertCell(cols);
				}
			}

			document.onkeydown = function(keyEvent){
				keyEvent = keyEvent || window.event;
				var ikeyNum = keyEvent.which || keyEvent.keyCode;
				switch(ikeyNum){
					case 37://←
						T.oBlock.move("left");
						break;
					case 38://↑	
						T.oBlock.rotate((function (){
							var vShape 		= T.aShapes[T.iShapeIdx][ (++T.index)%T.aShapes[T.iShapeIdx].length];
							var sShape 		= vShape.toString(2);								
							sShape 			= new Array(17 - sShape.length).join(0) + sShape;	
							T.matrix		= sShape.match(/\d{4}/g);	
							return T.matrix;
						})());	//变形
						break;
					case 39://→
						T.oBlock.move("right");
						break;
					case 40://↓
						T.oBlock.move("down");
						break;
				}
			}
		},
		next : function (){
			
			this.iShapeIdx 	= parseInt(Math.random() * this.aShapes.length);
			this.index 		= 0;
			var vShape 		= this.aShapes[this.iShapeIdx][this.index];
			var sShape 		= vShape.toString(2);								//将16进制转换为二进制
			sShape 			= new Array(17 - sShape.length).join(0) + sShape;	//不够16位,在前面用0补全 
			this.matrix		= sShape.match(/\d{4}/g);							//利用正则表达式匹配

			this.oBlock = new TETRIS.Block(this.matrix);
					
			clearInterval(T.timer);
			//注册定时器
			T.timer = setInterval(function (){
				T.oBlock.move("down");
			}, 1000);
			
			
			if( !T.oBlock.checkBlock() ){
				alert("Game Over~");
				clearInterval(T.timer);
			
			}
			
		},
		updateBoard : function (){		//更新面板
			for(var i = 0 ; i < 4 ; i++){
				this.aBoardGrids[T.oBlock.shape[i].y][T.oBlock.shape[i].x] = 1;
			}
		},
		eraseLines : function (){
			var iLines = 0;
			for(var j = 17 ; j >= 0 ; j--){
				var num = 0;
				for(var i = 0 ; i< 10 ; i++){
					if(this.aBoardGrids[j][i] == 1)
						num ++;
				}
				if(num == 10){
					iLines ++;
					for(var m = 0 ; m < i ; m++){
						for(var n = j ; n > 0 ; n--){
							this.aBoardGrids[n][m] = this.aBoardGrids[n-1][m];
							T.oDomBoard.rows[n].cells[m].style.background = T.oDomBoard.rows[n-1].cells[m].style.background;
						}
						this.aBoardGrids[0][m] = 0;
					}
					j++;
				}
			}
			return iLines;
		},
		setScore : function (iLines){
			var iScore = parseInt(this.oDomScore.innerHTML);
			if(iLines == 1){
				iScore += 100;
			} else if(iLines == 2){
				iScore += 300;
			} else if(iLines == 3){
				iScore += 500;
			} else if(iLines == 4){
				iScore += 1000;
			}
			this.oDomScore.innerHTML = iScore;
		}
	}
	
	TETRIS.Block = function (matrix){

		this.shape = (function(){
			
			var aShape = [];
			for(var i = 0 ; i < matrix.length ; i++){
				var sValue = matrix[i];
				for(var j = 0 ; j < sValue.length ; j++){
					if(sValue.charAt(j) == "1"){
						aShape.push({ x : j+3 , y : i });
					}  
				}
			}
			
			return aShape;
			
		})();
		this.draw();
	}
	
	TETRIS.Block.prototype.move = function (direction){//移动
		if(this.checkBlock(this.shape,direction)){
			this.draw("clear");
			for(var i = 0 ; i < 4 ; i++){
				switch(direction){
					case "left"://←	
						this.shape[i].x--;
						break;
					case "right":
						this.shape[i].x++;
						break;
					case "down":
						this.shape[i].y++;
						break;
				}
			}
			this.draw();
		} else {
			if(direction == "down"){
				this.draw();
				T.updateBoard();	//更新面板
				var iLines = T.eraseLines();
				
				if(iLines > 0){
				
					T.setScore(iLines);
					
				}
				
				T.next();			//再生成一个新的方块
			}
		}
		
	}
	TETRIS.Block.prototype.rotate = function (matrix){//变形
		
		this.shape = (function(oBlock){
			
			var aX = [];
			var aY = [];

			for(var i = 0 ; i < 4 ; i++){
				aX.push(oBlock.shape[i].x);
				aY.push(oBlock.shape[i].y);
			}
			var iMinX = aX.getMin();
			var iMinY = aY.getMin();
			
			
			var aShape = [];
			for(var i = 0 ; i < matrix.length ; i++){
				var sValue = matrix[i];
				for(var j = 0 ; j < sValue.length ; j++){
					if(sValue.charAt(j) == "1"){
						aShape.push({ x : j+iMinX , y : i+iMinY });
					}  
				}
			}
			if( !( oBlock.checkBlock(aShape)) )
				return oBlock.shape;
			oBlock.draw("clear");
			return aShape;
			
		})(this);

		this.draw();
	}

	TETRIS.Block.prototype.draw = function (opt){//绘图
		for(var i = 0 ; i < this.shape.length ; i++){
			var oShape = this.shape[i];
			T.oDomBoard.rows[oShape.y].cells[oShape.x].style.background = (opt==undefined?"#09F":"");
		}
	}
	TETRIS.Block.prototype.checkBlock = function (shape, direction){
		shape = shape || this.shape;
		for(var i = 0 ; i < 4 ; i++){
			if(direction == "left"){
					if(shape[i].x == 0 || T.aBoardGrids[shape[i].y][shape[i].x - 1] == 1){
						return false;
					}
			} else if(direction == "right"){
					if(shape[i].x == 9 || T.aBoardGrids[shape[i].y][shape[i].x + 1] == 1){
						return false;
					}
			} else if(direction == "down"){
					if(shape[i].y == 17 || T.aBoardGrids[shape[i].y + 1][shape[i].x] ==1){
						return false;
					}
			}
			if(shape[i].x < 0 || shape[i].x > 9 || shape[i].y < 0 || shape[i].y > 17)
				return false;
			if(T.aBoardGrids[shape[i].y][shape[i].x] == 1){
				return false;
			}
		}
		return true;
		
	}
	Array.prototype.getMin = function (){
		var iMin = this[0];
		for(var i = 0 ; i < this.length ; i++){
			if(this[i] < iMin)
				iMin = this[i];
		}
		return iMin;
	}
	window.onload = function(){
	
		T.init();
		
		var oBtnPlay = document.getElementById("btnPlay");
		oBtnPlay.onclick = function(){
			if(this.value == "begin"){
				T.next();
				this.value = "over";
			} else {
				this.value = "begin";
				alert("Game Over~");
				clearInterval(T.timer);
			} 
		
		}	
		var oBtnPause = document.getElementById("btnPause");
		oBtnPause.onclick = function (){
			if(this.value == "pause"){
				clearInterval(T.timer);
				this.value = "resume";
			} else {
				T.timer = setInterval(function (){
					T.oBlock.move("down");
				}, 1000);
				this.value = "pause";
			}
		}

	}

</script>
</head>

<body>
    <table id="gameBoard"></table>
    <div id="gameControl">
        Score : <span id="score">0</span><br />
      <input type="button" id="btnPlay" value="begin" />
      <input type="button" id="btnPause" value="pause" /><br/>
        <span>俄罗斯方块</span>
    </div>
</body>
</html>

程序有待优化改进,欢迎大家批评指正
版权声明:本文为博主原创文章,未经博主允许不得转载。

[前端 3]纯Js制作俄罗斯方块游戏

导读:在别人文章里看到了,然后写了一遍。结果出错了,然后调出来了,然后理解了一下,加了点注释,有一些想法。忘了在 哪一篇上面看的了,就贴不出来链接地址。原谅。呃,真没自己的东西,权当练打字了吧。其实,...
  • u013034889
  • u013034889
  • 2016年04月10日 00:08
  • 1949

史上最短小精悍的javascript编写的俄罗斯方块游戏,仅仅60行代码

史上最短小精悍的javascript编写的俄罗斯方块游戏,仅仅60行代码,代码下载地址:http://www.zuidaima.com/share/1759652641295360.htm...
  • yaerfeng
  • yaerfeng
  • 2014年04月28日 09:52
  • 52134

使用Java实现小游戏:俄罗斯方块

使用Java实现小游戏:俄罗斯方块使用一个二维数组保存游戏的地图:// 游戏地图格子,每个格子保存一个方块,数组纪录方块的状态 private State map[][] = new State[ro...
  • zhliro
  • zhliro
  • 2015年05月15日 16:43
  • 3147

Qt小游戏开发:俄罗斯方块

作为一个即将步入游戏行业的新人,手写经典小游戏是必备技能哦。 预览 由于录屏软件的问题,颜色和帧率与实际有所出入,不过不影响。 步骤 1 新建工程 建一个基类为QWidget的QT gui...
  • u012234115
  • u012234115
  • 2015年05月25日 10:43
  • 2849

javascript俄罗斯方块小游戏

任务要求 用javascript实现一个经典的“俄罗斯方块小游戏” 要求:能计分,有不同关卡(速度不同),有高分榜, chrome 30+以上浏览器能正常玩,主流android,ipho...
  • xsp_Login
  • xsp_Login
  • 2015年07月14日 21:06
  • 480

Swift游戏开发之俄罗斯方块:No.2 准备工作

如果你已经成功建好了工程,运行之后你会发现是个小飞机的程序,如果我没记错的; 这个程序是spin-the-bottle:Space Edition,但是可惜的是,我们并不需要这些东西,我们需要一个干净...
  • u011156012
  • u011156012
  • 2015年01月27日 16:38
  • 2625

史上最短小精悍的javascript编写的俄罗斯方块游戏,仅仅60行代码

原创整理不易,转载请注明出处:史上最短小精悍的javascript编写的俄罗斯方块游戏,仅仅60行代码 代码下载地址:http://www.zuidaima.com/share/17596526...
  • oMingZi12345678
  • oMingZi12345678
  • 2014年05月08日 13:16
  • 739

(难度:40%)纯js的俄罗斯方块游戏(含源码)

第一次写这么大的js程序, 代码量首破300的页面...
  • lj654548718
  • lj654548718
  • 2014年06月06日 23:27
  • 767

github上的一个html5俄罗斯方块小游戏做了些简化

html 俄罗斯方块 --> --> html, body { background: #3b3d3b; ...
  • infinitewall
  • infinitewall
  • 2016年02月25日 10:23
  • 1324

Swift游戏开发之俄罗斯方块:No.10 最后一步!美化你的程序

好了,本节是我们这系列教程的最后一篇。经过之前的代码磨练,到了最后一步,基本已经没有什么太多的知识点和难点了。最后,我们的程序看起来是非常酷炫的: 从图里可以看到,我们添加了分数和关卡,然后...
  • u011156012
  • u011156012
  • 2015年02月06日 16:24
  • 1849
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JavaScript, 实现俄罗斯方块小游戏
举报原因:
原因补充:

(最多只允许输入30个字)