javascript实现俄罗斯方块

原创 2013年07月14日 22:23:48

以前一直想写俄罗斯方块,连连看,坦克大战等经典的小游戏,不过本人太浮躁,每次写一半遇到问题就放弃了。

这次是自己第一次坚持写完了这个俄罗斯方块。

对javascript不是很熟,所以一些编程的格式,用法什么的不太规范,还需继续努力,加油,学习学习在学习,练习练习在练习。


<html>
	<head>
	</head>
	<body onkeydown="keydown(event)">
		<canvas id="tetrisCanvas" width="250" height="500" style="border-style:solid;">
			您的浏览器不支持canvas标签
		</canvas>
		<input type="button" value="开始游戏" onClick="startGame()">
		score:<input type="text" id="score"></input>
		level:<input type="text" id="level"></input>
		<p id = "log"></p>
		<script type="text/javascript" src="TetrisV2_1.js"></script>
	</body>
</html>



var gameCanvas = document.getElementById("tetrisCanvas");	// 得到画布对象

var cxt = gameCanvas.getContext("2d"); // 得到对象的context,这里我理解为得到一支没有颜色的笔cxt	

var GAME_WIDTH = 10; // 游戏的宽度,可以放10个方块

var GAME_HEIGHT = 20; // 游戏的高度,可以放20个方块

var BOX_SIZE = 25; // 每个方块的大小

var ADJUST_LOCATION = 3; // 调整新图形放入时的位置

var score = 0; // 游戏得分

var level = 0; // 游戏等级

var showLevel = document.getElementById("level"); // 显示等级

var speed = 1000; // 游戏速度 1000表示 1000毫秒也就是1秒移动一次

var timer; // 游戏定时器,周期性调用方法

var currentShapeNumber = 0; // 游戏中当前可移动的形状号码

currentShapeRotated = false; // 图形是否旋转过

var nextShapeNumber = 0; // 下一个即将出现的形状号码

var shapeCanMove = false; // 游戏是否有可移动图形

var rotatePointX = 0; // 图形当前旋转中心X坐标

var rotatePointY = 0; // 图形当前旋转中心Y坐标

var log = document.getElementById("log"); // log

var scoreHandle = document.getElementById("score"); // 显示分数

var isGameOver = false; // 标记游戏是否结束

/*
用一个2维数组来管理整个游戏
		0		- 没有方块
		1 		- 可移动方块
		大于1 	- 不可移动的方块
*/ 
var gameArray = new Array;

// O形状
var O_SHAPE = [[0,0,0,0],
			   [1,1,0,0],
			   [1,1,0,0],
			   [0,0,0,0]];	
// L形状
var L_SHAPE = [[0,1,0,0],
			   [0,1,0,0],
			   [1,1,0,0],
			   [0,0,0,0]];
L_SHAPE.ROTATE_POINT_X = 1;
L_SHAPE.ROTATE_POINT_Y = 1;
// J形状	
var J_SHAPE = [[1,1,0,0],
			   [0,1,0,0],
			   [0,1,0,0],
			   [0,0,0,0]];	
J_SHAPE.ROTATE_POINT_X = 1;
J_SHAPE.ROTATE_POINT_Y = 1;
// S形状	
var S_SHAPE = [[0,1,0,0],
			   [1,1,0,0],
			   [1,0,0,0],
			   [0,0,0,0]];
S_SHAPE.ROTATE_POINT_X = 1;
S_SHAPE.ROTATE_POINT_Y = 1;				   
// Z形状	
var Z_SHAPE = [[1,0,0,0],
			   [1,1,0,0],
			   [0,1,0,0],
			   [0,0,0,0]];
Z_SHAPE.ROTATE_POINT_X = 1;
Z_SHAPE.ROTATE_POINT_Y = 1;				   
// T形状	
var T_SHAPE = [[1,0,0,0],
			   [1,1,0,0],
			   [1,0,0,0],
			   [0,0,0,0]];	
T_SHAPE.ROTATE_POINT_X = 1;
T_SHAPE.ROTATE_POINT_Y = 0;			   
// I形状	
var I_SHAPE = [[1,0,0,0],
			   [1,0,0,0],
			   [1,0,0,0],
			   [1,0,0,0]];
I_SHAPE.ROTATE_POINT_X = 1;
I_SHAPE.ROTATE_POINT_Y = 0;			   
			   
// 存放所有的图形,数组中的位置可以用来标示其颜色位置
var shapes = [O_SHAPE, L_SHAPE, J_SHAPE, S_SHAPE, Z_SHAPE, T_SHAPE, I_SHAPE];

/*
存放颜色信息,在数组中的位置跟在图形数组中的位置对应
	#FF0000 红色
	#FF8800 橙色
	#FFFF00 黄色
	#00FF99 绿色
	#00BBFF 蓝色
	#9900FF 紫色
	#FF00FF 淡紫
*/
var COLORS = ["#FF0000", "#FF8800", "#FFFF00", "#00FF99", "#00BBFF", "#9900FF", "#FF00FF"];
// 每种形状代表的颜色
O_SHAPE.COLOR = COLORS[0];
L_SHAPE.COLOR = COLORS[1];
J_SHAPE.COLOR = COLORS[2];
S_SHAPE.COLOR = COLORS[3];
Z_SHAPE.COLOR = COLORS[4];
T_SHAPE.COLOR = COLORS[5];
I_SHAPE.COLOR = COLORS[6];

/*
绑定键盘按下时事件
	keyCode:38	↑ - 变形
	keyCode:37	← - 向左移动
	keyCode:39	→ - 向右移动 
	keyCode:40	↓ - 快速下降
*/
function keydown(evt) {
  var evt = evt || event;
	if(evt.keyCode == 37) {
		moveLeft();	
	}
	if(evt.keyCode == 38) {		
		rotate();	
	}
	if(evt.keyCode == 39) {
		moveRight();	
	}
	if(evt.keyCode == 40) {		
		moveDown();
	}
}

// 游戏初始化
function init() {
	/*
		给游戏数组值都设为0		
	*/
	gameArray = new Array(GAME_WIDTH);
	for(var x = 0; x < GAME_WIDTH; x++) {
		gameArray[x] = new Array(GAME_HEIGHT);
		for(var y = 0; y < GAME_HEIGHT; y++) {			
			gameArray[x][y] = 0;				
		}
	}
	score = 0; // 开始分数为0
	scoreHandle.value = score; //显示分数
	level = 1; // 游戏开始等级为1
	showLevel.value = level;
	speed = 1000; // 开始游戏速度为1秒运行一次
	isGameOver = false; // 游戏没有结束
	currentShapeNumber = randomNewShapeNumber();	
	putShape();
	drawGame();
	nextShapeNumber = randomNewShapeNumber();	
}

// 开始游戏
function startGame() {	
	init(); // 执行初始化方法	
	setTimeout("gameTimer()", speed/level);
}

function gameTimer() {
	if(isGameOver) {
		clearTimeout(timer);
		alert("Game Over");
		return;
	}
	if(shapeCanMove) {
		moveDown();
	}else {		
		removeFullLines();
		currentShapeNumber = nextShapeNumber;
		putShape();
		drawGame();
		nextShapeNumber = randomNewShapeNumber();
	}	
	timer = setTimeout("gameTimer()", speed/level);	
}

// 产生一个随机图形,并返回在shapes里的这个图形号码
function randomNewShapeNumber() {
	/*
		随机产生一个0到shapes.length的数
		Math.random() // 产生一个0到1的随机数
		Math.floor(number) // number的值向下舍入,比如0 - 0.9都表示为0
	*/
	shapeNumber = Math.floor(Math.random()*shapes.length);
	return 	shapeNumber;
}

// 把产生的图形放入游戏中
function putShape() {
	// log.innerHTML += currentShapeNumber;
	var currentShape = shapes[currentShapeNumber];
	rotatePointX = currentShape.ROTATE_POINT_X + ADJUST_LOCATION; // 图形在游戏中的中心点X坐标
	rotatePointY = currentShape.ROTATE_POINT_Y; // 图形在游戏中的中心点Y坐标
	for(var x = 0; x < currentShape.length; x++) {
		for(var y = 0; y < currentShape[x].length; y++) {
			if(currentShape[x][y] == 1) {
				if(gameArray[x + ADJUST_LOCATION][y] == 2){
					isGameOver = true;
				}
				gameArray[x + ADJUST_LOCATION][y] = 1; //放入gameArray里并调整其位置						
			}		
		}
	}	
	shapeCanMove = true; // 新加入一个形状,可移动
}

// 下移
function moveDown() {
	var action = "down";
	if(ifCanMove(action)) {
		for(var y = GAME_HEIGHT - 1; y >= 0; y--) {		
			for(var x = 0; x < GAME_WIDTH; x++) {
				if(gameArray[x][y] == 1) { // 图形从下面开始每个方块依次下移
					gameArray[x][y] = 0;
					gameArray[x][y + 1] = 1;
				}
			}
		}
		rotatePointY++; //旋转点也下移一格
	} else {
		// 如果不能下移,则设置图形所有值为2,表示此图形不能再移动
		for(var y = GAME_HEIGHT - 1; y >= 0; y--) {		
			for(var x = 0; x < GAME_WIDTH; x++) {
				if(gameArray[x][y] == 1) {
					gameArray[x][y] = 2;					
				}
			}
		}
		shapeCanMove = false; // 没有可以移动的图形了
	}
	drawGame();
}

// 左移
function moveLeft() {
	var action = "left";
	if(ifCanMove(action)) {
		for(var y = GAME_HEIGHT - 1; y >= 0; y--) {		
			for(var x = 0; x < GAME_WIDTH; x++) {
				if(gameArray[x][y] == 1) { // 图形从左边开始每个方块依次左移
					gameArray[x][y] = 0;
					gameArray[x - 1][y] = 1;
				}
			}
		}
		rotatePointX--; //旋转点也左移一格
	}
	drawGame();
}
// 右移
function moveRight() {
	var action = "right";
	if(ifCanMove(action)) {
		for(var y = GAME_HEIGHT - 1; y >= 0; y--) {		
			for(var x = GAME_WIDTH - 1; x >= 0; x--) {
				if(gameArray[x][y] == 1) { // 图形从右边开始每个方块依次右移
					gameArray[x][y] = 0;
					gameArray[x + 1][y] = 1;
				}
			}
		}	
		rotatePointX++; //旋转点也左移一格
	}
	drawGame();
}

// 是否能移动,action表示移动方向
function ifCanMove(action) {
	switch(action) {
		case "down":
			for(var x = 0; x < GAME_WIDTH; x++) {		
				for(var y = 0; y < GAME_HEIGHT; y++) {
					if(gameArray[x][y] == 1) {						
						if( y == (GAME_HEIGHT -1)) { // 如果图形到底部了,返回false不能移动		
							return false;
						} else if (gameArray[x][y + 1] == 2){	// 图形每一个方块下面那块如果有其它已有方块,返回false不能移动
							return false;					
						} 	
					}
				}
			}
			return true;
			
		case "left":
			for(var x = 0; x < GAME_WIDTH; x++) {		
				for(var y = 0; y < GAME_HEIGHT; y++) {
					if(gameArray[x][y] == 1) { // 如果图形到最左边了,返回false不能移动		
						if( x == 0) {		
							return false;
						} else if (gameArray[x - 1][y] == 2){	// 图形每一个方块左边那块如果有其它已有方块,返回false不能移动
							return false;					
						} 	
					}
				}
			}
			return true;
			
		case "right":
			for(var x = 0; x < GAME_WIDTH; x++) {		
				for(var y = 0; y < GAME_HEIGHT; y++) {
					if(gameArray[x][y] == 1) { // 如果图形到最右边了,返回false不能移动
						if( x == (GAME_WIDTH -1)) {		
							return false;
						} else if (gameArray[x + 1][y] == 2){	// 图形每一个方块右边那块如果有其它已有方块,返回false不能移动
							return false;					
						} 	
					}
				}
			}
			return true;
		
		default:
		alert("wrong action");
	} 	
}

/*
	变形
	变形公式:
	顺时针
		X = Y - deltY + deltX;
		y = - (X - deltX) + deltY;
	逆时针
		X = -(Y - deltY) + deltX;
		y = X - deltX + deltY;
*/
function rotate() {
	var tempShape = [[0,0],[0,0],[0,0],[0,0]];
	var tempCount = 0;
	for ( var y = 0; y < GAME_HEIGHT; y++) {
		for( var x = 0; x < GAME_WIDTH; x++) {
			if(gameArray[x][y] == 1) {
				tempShape[tempCount][0] = x;
				tempShape[tempCount][1] = y;
				tempCount++;						
			}
		}
	}
	if(currentShapeNumber == 0) {
	
	}
	if(currentShapeNumber == 1 || currentShapeNumber == 2 || currentShapeNumber == 5) {
		if(ifCanRotate(tempShape)) {
			for ( var y = 0; y < GAME_HEIGHT; y++) {
				for( var x = 0; x < GAME_WIDTH; x++) {
					if(gameArray[x][y] == 1) {												
						gameArray[x][y] = 0;				
					}
				}
			}
			for ( var i = 0; i < tempShape.length; i++) {
				var tempX = -(tempShape[i][1] - rotatePointY) + rotatePointX;
				var tempY = (tempShape[i][0] - rotatePointX) +rotatePointY;
				gameArray[tempX][tempY] = 1;
			}					
		}			
	}
	if(currentShapeNumber == 3 || currentShapeNumber == 4 || currentShapeNumber == 6) {
		if(ifCanRotate(tempShape)) {
			for ( var y = 0; y < GAME_HEIGHT; y++) {
				for( var x = 0; x < GAME_WIDTH; x++) {
					if(gameArray[x][y] == 1) {												
						gameArray[x][y] = 0;				
					}
				}
			}
			if(currentShapeRotated) {
				for ( var i = 0; i < tempShape.length; i++) {
					var tempX = (tempShape[i][1] - rotatePointY) + rotatePointX;
					var tempY = -(tempShape[i][0] - rotatePointX) +rotatePointY;
					gameArray[tempX][tempY] = 1;
				}			
			}else{
				for ( var i = 0; i < tempShape.length; i++) {
					var tempX = -(tempShape[i][1] - rotatePointY) + rotatePointX;
					var tempY = (tempShape[i][0] - rotatePointX) +rotatePointY;
					gameArray[tempX][tempY] = 1;
				}			
			}
			if(currentShapeRotated) {
				currentShapeRotated = false;
			}else {
				currentShapeRotated = true;
			}
		}
	}	
	drawGame();
}

// 是否能旋转
function ifCanRotate(rotatedShape) {
	if(currentShapeNumber == 1 || currentShapeNumber == 2 || currentShapeNumber == 5) {
		for(var i = 0; i < rotatedShape.length; i++) {
			var tempX = rotatedShape[i][1] - rotatePointY + rotatePointX;
			var tempY = -(rotatedShape[i][0] - rotatePointX) + rotatePointY;
			if(tempX < 0 || tempX >= GAME_WIDTH) {
				return false;
			}else if(gameArray[tempX][tempY] == 2 ) {
				return false;
			}else if(tempY < 0 || tempY >= GAME_HEIGHT) {
				return false;
			}		
		}	
		return true;
	}
	if(currentShapeNumber == 3 || currentShapeNumber == 4 || currentShapeNumber == 6) {
		if(currentShapeRotated) {
			for(var i = 0; i < rotatedShape.length; i++) {
				var tempX = (rotatedShape[i][1] - rotatePointY) + rotatePointX;
				var tempY = -(rotatedShape[i][0] - rotatePointX) + rotatePointY;
				if(tempX < 0 || tempX >= GAME_WIDTH) {
					return false;
				}else if(gameArray[tempX][tempY] == 2 ) {
					return false;
				}else if(tempY < 0 || tempY >= GAME_HEIGHT) {
					return false;
				}		
			}			
			return true;
		}else {
			for(var i = 0; i < rotatedShape.length; i++) {
				var tempX = -(rotatedShape[i][1] - rotatePointY) + rotatePointX;
				var tempY = (rotatedShape[i][0] - rotatePointX) + rotatePointY;
				if(tempX < 0 || tempX >= GAME_WIDTH) {
					return false;
				}else if(gameArray[tempX][tempY] == 2 ) {
					return false;
				}else if(tempY < 0 || tempY >= GAME_HEIGHT) {
					return false;
				}		
			}			
			return true;
		}
	}
	
}

// 删除所有满的行
function removeFullLines() {
	var removeLines = 0;
	for( var y = 0; y < GAME_HEIGHT; y++) {
		for ( var x = 0; x < GAME_WIDTH; x++) {			
			if(gameArray[x][y] == 0) {
				break;			
			}else if( x == (GAME_WIDTH - 1)) {	
				removeLines++;
				for ( var ry = y;  ry >= 0 ; ry--) {
					for ( var x = 0; x < gameArray.length; x++) {
						if(ry == 0) {
							gameArray[x][ry] = 0; // 第一行都设为零
						} else {
							gameArray[x][ry] = gameArray[x][ry-1]; // 所有行下移
						}						
					}
				}
			}	
		}
	}
	switch(removeLines) {
		case 1:
			score += 100;
			scoreHandle.value = score;
			break;
		case 2:
			score += 200;
			scoreHandle.value = score;
			break;
		case 3:
			score += 400;
			scoreHandle.value = score;
			break;
		case 4:
			score += 800;
			scoreHandle.value = score;
			break;
	}
	if(score >= 200 && score < 500) {
		level = 2;	
		showLevel.value = level;
	}else if(score >= 500 && score < 1000) {
		level = 3;
		showLevel.value = level;
	}else if(score >= 1000 && score < 1600) {
		level = 4;
		showLevel.value = level;
	}else if(score >= 1600 && score < 2200) {
		level = 5;
		showLevel.value = level;
	}else if(score >= 2200 && score < 2900) {
		level = 6;
		showLevel.value = level;
	}else if(score >= 2900 && score < 3600) {
		level = 7;
		showLevel.value = level;
	}else if(score >= 3600 && score < 4400) {
		level = 8;
		showLevel.value = level;
	}else if(score >= 4400 && score < 5000) {
		level = 9;
		showLevel.value = level;
	}else if(score >= 5000 && score < 5700) {
		level = 10;
		showLevel.value = level;
	}else if(score >= 5700 && score < 6400) {
		level = 11;
		showLevel.value = level;
	}else if(score >= 6400 && score < 7200) {
		level = 12;
		showLevel.value = level;
	}else if(score >= 7200 && score < 8000) {
		level = 13;
		showLevel.value = level;
	}else if(score >= 8000 && score < 8800) {
		level = 14;
		showLevel.value = level;
	}	
	
}

// 有游戏数组画到画布上
function drawGame() {
	for( var x = 0; x < GAME_WIDTH; x++) {
		for ( var y = 0; y < GAME_HEIGHT; y++) {	
			// 值为零的清除该方块
			if(gameArray[x][y] == 0) {
				cxt.clearRect(x * BOX_SIZE, y * BOX_SIZE, BOX_SIZE, BOX_SIZE);
			}	
			// 值大于零时画出该方块
			if(gameArray[x][y] >= 1) {
				// cxt.fillStyle = shapes[currentShape].COLOR;
				cxt.fillStyle = "FF8800";
				cxt.fillRect(x * BOX_SIZE, y * BOX_SIZE, BOX_SIZE, BOX_SIZE);							
			}		
		}
	}
}



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

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

纯js实现俄罗斯方块详解与源码

对于小白来说用js实现俄罗斯方块还是有难度的,网上找了很多代码看,有的很长难懂,有的短小精悍,但不只用到了js还用到了框架,对于还未接触框架的小白宝宝,也只能无奈自己是小白了,自己写不出来那就找一篇纯...
  • d1105260363
  • d1105260363
  • 2017-08-23 17:54:45
  • 863

js版俄罗斯方块设计思想及实现

俄罗斯方块方块是小时候的一个回忆,从最开始的掌上的黑白游戏机,到电视游戏机,到电脑,无不有它的痕迹,今天我们来一起重温它的一种实现方法,也算是整理一下我的思路吧...... 1.以中心点坐标代替整个...
  • luqin1988
  • luqin1988
  • 2013-01-18 09:50:33
  • 4417

Html5+js实现俄罗斯方块

代码测试地址:测试 1、使用的知识点 html5 javascript 2、需要实现的功能 俄罗斯方块普通玩法 3、分析功能实现 (1)组合方块,共7中形状,可静态指定(由4个方块组合)      ...
  • yixi524
  • yixi524
  • 2014-01-14 23:40:13
  • 1725

JavaScript canvas实现俄罗斯方块

JavaScript canvas实现俄罗斯方块。简洁逻辑清晰的代码,代码量少。要记录这些模型有很多种办法,可以用记录其相对位置,记录每一个方块的x,y坐标等。自己想了一种思路来记录这7种模型,很简洁...
  • cc_fys
  • cc_fys
  • 2017-09-12 10:20:33
  • 710

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

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

JS写俄罗斯方块完美注释版

JS写俄罗斯方块完美注释版/************************************************************* JS俄罗斯方块完美注释版 v 1.01* 作者:...
  • sunxing007
  • sunxing007
  • 2008-11-19 00:35:00
  • 15188

原生JS实现网页版俄罗斯方块

  • 2017年05月06日 22:41
  • 26KB
  • 下载

JavaScript jQuery实现Tetris(俄罗斯方块)游戏代码

原文:JavaScript jQuery实现Tetris(俄罗斯方块)游戏代码 源代码下载地址:http://www.zuidaima.com/share/1882054152457216....
  • yaerfeng
  • yaerfeng
  • 2016-12-15 10:17:55
  • 1413

一个javascript写的俄罗斯方块

自己写的,随便看看吧,最近在努力研究J2ME,正在自己开发一个类似泡泡堂的手机网络游戏,到时候把源代码发来交流一下.下面这个文档直接粘贴过去就能用.无标题文档 alert("欢迎您的使用!  A,S,...
  • wpcsboy007
  • wpcsboy007
  • 2007-07-02 20:39:00
  • 353
收藏助手
不良信息举报
您举报文章:javascript实现俄罗斯方块
举报原因:
原因补充:

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