码迷,mamicode.com
首页 > 其他好文 > 详细

前端作品五之——完美俄罗斯方块

时间:2015-10-28 22:37:42      阅读:397      评论:0      收藏:0      [点我收藏+]

标签:

---恢复内容开始---

1、功能概述

  实现传统的俄罗斯方块的功能。有几种固定形状和颜色的方块随机下落,满一行则此行消除。并让积分增加100,使用本地存储功能将方块的状态和得分存起来。在下次进行游戏的时候载入数据,并在游戏中进行存储操作。

技术分享

2、选材布局

  用canvas组件画方格图。用JavaScript语言实现逻辑功能。

3、功能实现与体会  

  源码中本人发现了几处bug,
1、测试发现在旋转操作频繁的时候,会出现方块严重错位,或丢失,出现一些匪夷所思的现象。
经分析,是旋转操作的处理出现的问题。
旋转中心的定义问题。原文中将第三方块的左上角作为旋转中心,每次逆时针旋转90度后,通过原先的方块左上角来绘制矩形并填充颜色。
但是正方形的原先的左上角角在旋转后,就变到左下角下面去了,这样画出来的旋转后的第三方块其实相当于向下移了一格。
感觉失去了旋转原本想要达到的目的,而且实践中发现的确会出现在旋转快速时,方块错位丢失现象。
处理方法:
(1)、将原本的旋转中心换成了第三方块的中心点;
(2)、不再按照左上角来绘制方块,而是根据中心点来绘制方块,不过。到时候的俩坐标得相应剪掉1/2个方块宽度和高度。
这样在旋转的时候第三方块还是会在原本的位置。而且中心点没变,旋转后绘制出来的方块还是原先位置。
于是我重新修改了,原文中的旋转中心,

2、在moveDown()的else语句中,原文将lineFull()消除方块语句放到了判断是否方块到达顶端的语句后面,显然不符合,
消除后可能会出现的方块没到达顶端。
处理方法:
(1)、将两者顺序颠倒过来。
(2)、通过改为检查顶层有无方块状态来判断是否到达顶端、游戏是否结束。

  本人新增的原创功能。
俄罗斯方块,小时候曾在电子游戏机上玩过很多,对此还是很熟悉的,用户体验方面,还算了解。
于是,我在原游戏的方格窗口右上方新增了一个4*4的方格,目的是:显示即将到来的方块。这样在游戏速度加快的时候,
有更多的反应时间。

最后:本人修改的数据痕迹,比如说“1+1/2”这类算式仍然保留在文中。可以供日后自己参考当时的思路。

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title> 完美俄罗斯方块  原作:李刚  Debuged By:ChenZz~ </title>
	<script type="text/javascript">

/*
	说明:

 *本游戏原型出自《疯狂HTML5CSS3JavaScript讲义》作者:李刚,出版时间:2012年5月

  *Debuged By:ChenZz~

 *一、源码中本人发现了几处bug,
     1、测试发现在旋转操作频繁的时候,会出现方块严重错位,或丢失,出现一些匪夷所思的现象。
 经分析,是旋转操作的处理出现的问题。
     旋转中心的定义问题。原文中将第三方块的左上角作为旋转中心,每次逆时针旋转90度后,通过原先的方块左上角来绘制矩形并填充颜色。
 但是正方形的原先的左上角角在旋转后,就变到左下角下面去了,这样画出来的旋转后的第三方块其实相当于向下移了一格。
 感觉失去了旋转原本想要达到的目的,而且实践中发现的确会出现在旋转快速时,方块错位丢失现象。
 *
 *处理方法:
 (1)、将原本的旋转中心换成了第三方块的中心点;
 (2)、不再按照左上角来绘制方块,而是根据中心点来绘制方块,不过。到时候的俩坐标得相应剪掉1/2个方块宽度和高度。
 这样在旋转的时候第三方块还是会在原本的位置。而且中心点没变,旋转后绘制出来的方块还是原先位置。
 *于是我重新修改了,原文中的旋转中心,

	2、在moveDown()的else语句中,原文将lineFull()消除方块语句放到了判断是否方块到达顶端的语句后面,显然不符合,
消除后可能会出现的方块没到达顶端。
 *处理方法:
 (1)、将两者顺序颠倒过来。
 (2)、通过改为检查顶层有无方块状态来判断是否到达顶端、游戏是否结束。	
 
 二、本人新增的原创功能。
 	俄罗斯方块,小时候曾在电子游戏机上玩过很多,对此还是很熟悉的,用户体验方面,还算了解。
	于是,我在原游戏的方格窗口右上方新增了一个4*4的方格,目的是:显示即将到来的方块。这样在游戏速度加快的时候,
有更多的反应时间。

最后:本人修改的数据痕迹,比如说“1+1/2”这类算式仍然保留在文中。可以供日后自己参考当时的思路。

 * 基于HTML 5、JavaScript来完成。
 * 本游戏主要使用了canvas组件来绘制游戏界面,
 * 使用了Local Storage记录游戏状态
 *
 */

var TETRIS_ROWS = 20;
var TETRIS_COLS = 14;
var CELL_SIZE = 24;
// 没方块是0
//在tetris_status[]存储颜色,用来区分是否NO_BLOCK
var NO_BLOCK = 0;
var tetris_canvas;

var tetris_canvas2;

var tetris_ctx;
var tetris_ctx2;
// 记录当前积分
var curScore = 0;
// 记录当前速度
var curSpeed = 1;
// 记录曾经的最高积分
var maxScore = 0;
var curScoreEle , curSpeedEle , maxScoreEle;
var curTimer;
// 记录当前是否游戏中的旗标
var isPlaying = true;
// 记录正在下掉的四个方块
var currentFall;
var currentFall2;
// 初始化
var tetris_status = [];
for (var i = 0; i < TETRIS_ROWS ; i++ )
{
	tetris_status[i] = [];
	for (var j = 0; j < TETRIS_COLS ; j++ )
	{
		tetris_status[i][j] = NO_BLOCK;
	}
}
var tetris_status2 = [];
for (var i = 0; i < 4 ; i++ )
{
	tetris_status2[i] = [];
	for (var j = 0; j < 4 ; j++ )
	{
		tetris_status2[i][j] = NO_BLOCK;
	}
}

// 定义方块的颜色
colors = ["#fff", "#f00" , "#0f0" , "#00f"
	, "#c60" , "#f0f" , "#0ff" , "#609"];
// 定义几种可能出现的方块组合,a1[ a2[json]	 ]
var blockArr = [
	// 代表第一种可能出现的方块组合:Z
	[
		{x: TETRIS_COLS / 2 - 1/2 , y:-1 +1/2+1, color:1},
		{x: TETRIS_COLS / 2+1/2 , y:-1+1/2 +1,color:1},
		{x: TETRIS_COLS / 2+1/2 , y:0 +1/2+1,color:1},
		{x: TETRIS_COLS / 2 + 1+1/2 , y:0+1/2+1 , color:1}
	],
	// 代表第二种可能出现的方块组合:反Z
	[
		{x: TETRIS_COLS / 2 + 1+1/2 , y:-1+1/2 +1, color:2},
		{x: TETRIS_COLS / 2 +1/2, y:-1 +1/2+1, color:2},
		{x: TETRIS_COLS / 2 +1/2, y:0+1/2 +1, color:2},
		{x: TETRIS_COLS / 2 - 1+1/2 , y:0 +1/2+1, color:2}
	],
	// 代表第三种可能出现的方块组合: 田
	[
		{x: TETRIS_COLS / 2 - 1 +1/2, y:-1+1/2+1 , color:3},
		{x: TETRIS_COLS / 2 +1/2, y:-1 +1/2+1,  color:3},
		{x: TETRIS_COLS / 2 - 1 +1/2, y:0 +1/2+1, color:3},
		{x: TETRIS_COLS / 2 +1/2, y:0 +1/2+1, color:3}
	],
	// 代表第四种可能出现的方块组合:L
	[
		{x: TETRIS_COLS / 2 - 1 +1/2, y:-1+1/2 +1, color:4},
		{x: TETRIS_COLS / 2 - 1+1/2, y:0 +1/2+1, color:4},
		{x: TETRIS_COLS / 2 - 1+1/2 , y:1+1/2+1 , color:4},
		{x: TETRIS_COLS / 2+1/2 , y:1+1/2+1 , color:4}
	],
	// 代表第五种可能出现的方块组合:J
	[
		{x: TETRIS_COLS / 2+1/2  , y:-1+1/2+1 , color:5},
		{x: TETRIS_COLS / 2 +1/2, y:0+1/2+1, color:5},
		{x: TETRIS_COLS / 2 +1/2 , y:1+1/2+1, color:5},
		{x: TETRIS_COLS / 2 - 1+1/2, y:1+1/2+1, color:5}
	],
	// 代表第六种可能出现的方块组合 : 条
	[
		{x: TETRIS_COLS / 2 +1/2, y:-1+1/2+1 , color:6},
		{x: TETRIS_COLS / 2+1/2 , y:0+1/2 +1, color:6},
		{x: TETRIS_COLS / 2 +1/2, y:1+1/2 +1, color:6},
		{x: TETRIS_COLS / 2+1/2 , y:2 +1/2+1, color:6}
	],
	// 代表第七种可能出现的方块组合 : ┵
	[
		{x: TETRIS_COLS / 2 +1/2, y:-1 +1/2+1, color:7},
		{x: TETRIS_COLS / 2 - 1 +1/2, y:0+1/2+1 , color:7},
		{x: TETRIS_COLS / 2 +1/2, y:0+1/2+1 , color:7},
		{x: TETRIS_COLS / 2 + 1+1/2, y:0 +1/2+1, color:7}
	]
];

var value1 = Math.floor(Math.random() * blockArr.length);
var value2= Math.floor(Math.random() * blockArr.length);
var initBlock2 = function(rand)
{	//Math.floor()用来向下取整,返回小于等于的最接近的整数。Math.random()返回0到1之间的随机数。
	// var rand = Math.floor(Math.random() * blockArr.length);
	// var rand=5;
	// 随机生成正在下掉的方块,a[json],取之前方块的x,y数值。x,y单位是/格子。
	currentFall2 = [
		{x: blockArr[rand][0].x-5 , y: blockArr[rand][0].y
			, color: blockArr[rand][0].color},
		{x: blockArr[rand][1].x-5 , y: blockArr[rand][1].y
			, color: blockArr[rand][1].color},
		{x: blockArr[rand][2].x-5 , y: blockArr[rand][2].y
			, color: blockArr[rand][2].color},
		{x: blockArr[rand][3].x-5 , y: blockArr[rand][3].y
			, color: blockArr[rand][3].color}
	];
};

// 定义初始化正在下掉的方块
var initBlock = function(rand)
{	//Math.floor()用来向下取整,返回小于等于的最接近的整数。Math.random()返回0到1之间的随机数。
	// var rand = Math.floor(Math.random() * blockArr.length);
	// var rand=5;
	// 随机生成正在下掉的方块,a[json],取之前方块的x,y数值。x,y单位是/格子。
	currentFall = [
		{x: blockArr[rand][0].x , y: blockArr[rand][0].y
			, color: blockArr[rand][0].color},
		{x: blockArr[rand][1].x , y: blockArr[rand][1].y
			, color: blockArr[rand][1].color},
		{x: blockArr[rand][2].x , y: blockArr[rand][2].y
			, color: blockArr[rand][2].color},
		{x: blockArr[rand][3].x , y: blockArr[rand][3].y 
			, color: blockArr[rand][3].color}
	];
};




// 定义一个创建canvas组件的函数,cellwidth在后面通过window赋值cellsize
var createCanvas = function(rows , cols , cellWidth, cellHeight)
{
	tetris_canvas = document.createElement("canvas");
	// 设置canvas组件的高度、宽度
	tetris_canvas.width = cols * cellWidth;
	tetris_canvas.height = rows * cellHeight;
	// 设置canvas组件的边框
	tetris_canvas.style.border = "1px solid black";
	// 获取canvas上的绘图API
	tetris_ctx = tetris_canvas.getContext(‘2d‘);
	// 开始创建路径  
	tetris_ctx.beginPath();
	// 绘制横向网络对应的路径
	for (var i = 1 ; i < TETRIS_ROWS ; i++)
	{
		tetris_ctx.moveTo(0 , i * CELL_SIZE);
		tetris_ctx.lineTo(TETRIS_COLS * CELL_SIZE , i * CELL_SIZE);
	}
	// 绘制竖向网络对应的路径
	for (var i = 1 ; i < TETRIS_COLS ; i++)
	{
		tetris_ctx.moveTo(i * CELL_SIZE , 0);
		tetris_ctx.lineTo(i * CELL_SIZE , TETRIS_ROWS * CELL_SIZE);
	}
	tetris_ctx.closePath(); 
	// 设置笔触颜色
	tetris_ctx.strokeStyle = "#aaa";
	// 设置线条粗细
	tetris_ctx.lineWidth = 0.3;
	// 绘制线条
	tetris_ctx.stroke();
}
var createCanvas2 = function(rows , cols , cellWidth, cellHeight)
{
	 tetris_canvas2 = document.createElement("canvas");
	// 设置canvas组件的高度、宽度
	tetris_canvas2.width = cols * cellWidth;
	tetris_canvas2.height = rows * cellHeight;
	// 设置canvas组件的边框
	tetris_canvas2.style.border = "1px solid black";
	// 获取canvas上的绘图API
	tetris_ctx2 = tetris_canvas2.getContext(‘2d‘);
	// 开始创建路径  
	tetris_ctx2.beginPath();
	// 绘制横向网络对应的路径
	for (var i = 1 ; i < 4 ; i++)
	{
		tetris_ctx2.moveTo(0 , i * CELL_SIZE);
		tetris_ctx2.lineTo(4 * CELL_SIZE , i * CELL_SIZE);
	}
	// 绘制竖向网络对应的路径
	for (var i = 1 ; i < 4 ; i++)
	{
		tetris_ctx2.moveTo(i * CELL_SIZE , 0);
		tetris_ctx2.lineTo(i * CELL_SIZE , 4 * CELL_SIZE);
	}
	tetris_ctx2.closePath(); 
	// 设置笔触颜色
	tetris_ctx2.strokeStyle = "#aaa";
	// 设置线条粗细
	tetris_ctx2.lineWidth = 0.3;
	// 绘制线条
	tetris_ctx2.stroke();
}

// 绘制之前cookie里的俄罗斯方块的状态
var drawBlock = function()
{
	for (var i = 0; i < TETRIS_ROWS ; i++ )
	{
		for (var j = 0; j < TETRIS_COLS ; j++ )
		{
			// 有方块的地方绘制颜色
			if(tetris_status[i][j] != NO_BLOCK)
			{
				// 设置填充颜色,这里是属于cookie里的颜色。
				tetris_ctx.fillStyle = colors[tetris_status[i][j]];
				// 绘制矩形
				tetris_ctx.fillRect(j * CELL_SIZE + 1 
					, i * CELL_SIZE + 1, CELL_SIZE - 2 , CELL_SIZE - 2);
			}
			// 没有方块的地方绘制白色
			else
			{
				// 设置填充颜色
				tetris_ctx.fillStyle = ‘white‘;
				// 绘制矩形
				tetris_ctx.fillRect(j * CELL_SIZE + 1 
					, i* CELL_SIZE + 1 , CELL_SIZE - 2 , CELL_SIZE - 2);
			}
		}
	}
}
var drawBlock2 = function()
{
	for (var i = 0; i < 4 ; i++ )
	{
		for (var j = 0; j < 4 ; j++ )
		{
				tetris_ctx2.fillStyle = ‘white‘;
				// 绘制矩形
				tetris_ctx2.fillRect(j * CELL_SIZE + 1 
					, i* CELL_SIZE + 1 , CELL_SIZE - 2 , CELL_SIZE - 2);
			
		}
	}
}
var drawBlock3 = function()
{
	for (var i = 0 ; i < currentFall2.length ; i++)
	{
		var cur2 = currentFall2[i];
		// 设置填充颜色
		tetris_ctx2.fillStyle = colors[cur2.color];
		// 绘制矩形
		tetris_ctx2.fillRect((cur2.x -1/2)* CELL_SIZE + 1 , (cur2.y -1/2)* CELL_SIZE + 1 , CELL_SIZE - 2 , CELL_SIZE - 2);
	}
}
// var drawBlock4 = function()
// {
// 	for (var i = 0; i < 4 ; i++ )
// 	{
// 		tetris_status2[i] = [];
// 		for (var j = 0; j < 4 ; j++ )
// 		{
// 			tetris_status2[i][j] = NO_BLOCK;
// 		}
// }


// 当页面加载完成时,执行该函数里的代码。
window.onload = function()
{
	var oDiv1=document.getElementById(‘div1‘);
	// 创建canvas组件
	createCanvas(TETRIS_ROWS , TETRIS_COLS , CELL_SIZE , CELL_SIZE);


// 创建canvas2组件
	createCanvas2(4 , 4 , CELL_SIZE , CELL_SIZE);

	oDiv1.appendChild(tetris_canvas);
	// var oDiv=document.createElement(‘div‘);
	// tetris_canvas.style.position=‘relative‘;
	 // oDiv.style.position= ‘relative‘;
	 // oDiv.style.float=‘right‘;
	// oDiv.style.margin = ‘50px auto 0‘;
	// document.body.appendChild(oDiv);
	createCanvas2(4 , 4 , CELL_SIZE , CELL_SIZE);
	oDiv1.appendChild(tetris_canvas2);
	tetris_canvas.style.float=‘left‘;
	tetris_canvas2.style.float=‘left‘;
	// oDiv.appendChild(tetris_canvas2);



	curScoreEle = document.getElementById("curScoreEle");
	curSpeedEle = document.getElementById("curSpeedEle");
	maxScoreEle = document.getElementById("maxScoreEle");
	// 读取Local Storage里的tetris_status记录
	var tmpStatus = localStorage.getItem("tetris_status");
        //将JSON字符串转换为对象(字符串转对象)
	tetris_status = tmpStatus == null ? tetris_status : JSON.parse(tmpStatus);
	// 把方块状态绘制出来
	drawBlock();
	// 读取Local Storage里的curScore记录
	curScore = localStorage.getItem("curScore");
	curScore = curScore == null ? 0 : parseInt(curScore);
	curScoreEle.innerHTML = curScore;
	// 读取Local Storage里的maxScore记录
	maxScore = localStorage.getItem("maxScore");
	maxScore = maxScore == null ? 0 : parseInt(maxScore);
	maxScoreEle.innerHTML = maxScore;
	// 读取Local Storage里的curSpeed记录
	curSpeed = localStorage.getItem("curSpeed");
	curSpeed = curSpeed == null ? 1 : parseInt(curSpeed);
	curSpeedEle.innerHTML = curSpeed;

//预测正要下掉的方块
// initpredict();
	// 初始化正在下掉的方块
	initBlock(value1);
	initBlock2(value2);
	drawBlock3(); 
	// 控制每隔固定时间执行一次向下”掉“
	curTimer = setInterval("moveDown();" ,  500 / curSpeed);
}
// 判断是否有一行已满
var lineFull = function()
{
	// 依次遍历每一行
	for (var i = 0; i < TETRIS_ROWS ; i++ )
	{
		var flag = true;
		// 遍历当前行的每个单元格
		for (var j = 0 ; j < TETRIS_COLS ; j++ )
		{
			if(tetris_status[i][j] == NO_BLOCK)
			{
				flag = false;
				break;
			}
		}
		// 如果当前行已全部有方块了
		if(flag)
		{
			// 将当前积分增加100
			curScoreEle.innerHTML = curScore+= 100;
			// 记录当前积分
			localStorage.setItem("curScore" , curScore);
			// 如果当前积分达到升级极限。
			if( curScore >= curSpeed * curSpeed * 500)
			{
				curSpeedEle.innerHTML = curSpeed += 1;
				// 使用Local Storage记录curSpeed。
				localStorage.setItem("curSpeed" , curSpeed);
				clearInterval(curTimer);
				curTimer = setInterval("moveDown();" ,  500 / curSpeed);
			}
			// 把当前行的所有方块下移一行。
			for (var k = i ; k > 0 ; k--)
			{
				for (var l = 0; l < TETRIS_COLS ; l++ )
				{
					tetris_status[k][l] =tetris_status[k-1][l];
				}
			}
			// 消除方块后,重新绘制一遍方块
			drawBlock();      //②
			//为了消除bug
			// moveDown();
		}
	}
}
// 控制方块向下掉。
var moveDown = function()
{
	// 定义能否下掉的旗标
	var canDown = true;    //①
	// 遍历每个方块,判断是否能向下掉
	for (var i = 0 ; i < currentFall.length ; i++)
	{
		// 判断是否已经到“最底下” x,y起点是0;
		if(currentFall[i].y >= TETRIS_ROWS-1/2 )
		{
			canDown = false;
			break;
		}
		// 判断下一格是否“有方块”, 如果下一格有方块,不能向下掉
		if(tetris_status[currentFall[i].y + 1/2][currentFall[i].x-1/2] != NO_BLOCK)
		{
			canDown = false;
			break;
		}
	}
	// 如果能向下“掉”
	if(canDown)
	{
		// 将下移前的每个方块的背景色涂成白色
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			// 设置填充颜色
			tetris_ctx.fillStyle = ‘white‘;
			// 绘制矩形
			tetris_ctx.fillRect((cur.x -1/2)* CELL_SIZE + 1 
				, (cur.y -1/2)* CELL_SIZE + 1 , CELL_SIZE - 2 , CELL_SIZE - 2);
		}
		// 遍历每个方块, 控制每个方块的y坐标加1。
		// 也就是控制方块都下掉一格
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			cur.y ++;
		}
		// 将下移后的每个方块的背景色涂成该方块的颜色值
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			// 设置填充颜色
			tetris_ctx.fillStyle = colors[cur.color];
			// 绘制矩形
			tetris_ctx.fillRect((cur.x -1/2)* CELL_SIZE + 1 
				, (cur.y -1/2)* CELL_SIZE + 1 , CELL_SIZE - 2 , CELL_SIZE - 2);
		}
	}
	// 不能向下掉
	else
	{
		//解决了一个bug,逻辑更严谨
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];

			// 把每个方块当前所在位置赋为当前方块的颜色值
			tetris_status[cur.y-1/2][cur.x-1/2] = cur.color;

		}

		// 判断是否有“可消除”的行
		 lineFull();

		// 遍历每个方块, 把每个方块的值记录到tetris_status数组中
		for (var i = 0 ; i < 4 ; i++)
		{

			// 如果有方块已经到最上面了,表明输了
			for (var j = 0 ; j < TETRIS_COLS ; j++ )
			{

				if(tetris_status[i][j] !=NO_BLOCK)
				{
					// 清空Local Storage中的当前积分值、游戏状态、当前速度
					localStorage.removeItem("curScore");
					localStorage.removeItem("tetris_status");
					localStorage.removeItem("curSpeed");
					if(confirm("您已经输了!是否参数排名?"))
					{
						// 读取Local Storage里的maxScore记录
						maxScore = localStorage.getItem("maxScore");
						maxScore = maxScore == null ? 0 : maxScore ;
						// 如果当前积分大于localStorage中记录的最高积分
						if(curScore >= maxScore)
						{
							// 记录最高积分
							localStorage.setItem("maxScore" , curScore);
						}
					}
					// 游戏结束
					isPlaying = false;
					// 清除计时器
					clearInterval(curTimer);
					return;
				}
			}
			// // 把每个方块当前所在位置赋为当前方块的颜色值
			// tetris_status[cur.y][cur.x] = cur.color;
		}
		//lineFull();

		// 使用Local Storage记录俄罗斯方块的游戏状态
		localStorage.setItem("tetris_status" , JSON.stringify(tetris_status));
		// 开始一组新的方块。
		drawBlock2();
		initBlock(value2);
		value2=Math.floor(Math.random() * blockArr.length);
		initBlock2(value2);
		drawBlock3();

	}
}
// 定义左移方块的函数
var moveLeft = function()
{
	// 定义能否左移的旗标
	var canLeft = true;
	for (var i = 0 ; i < currentFall.length ; i++)
	{
		// 如果已经到了最左边,不能左移
		if(currentFall[i].x <= 1/2)
		{
			canLeft = false;
			break;
		}
		// 或左边的位置已有方块,不能左移
		if (tetris_status[currentFall[i].y-1/2][currentFall[i].x-1/2-1]!= NO_BLOCK)
		{
			canLeft = false;
			break;
		}
	}
	// 如果能左移
	if(canLeft)
	{
		// 将左移前的每个方块的背景色涂成白色
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			// 设置填充颜色
			tetris_ctx.fillStyle = ‘white‘;
			// 绘制矩形
			tetris_ctx.fillRect((cur.x-1/2) * CELL_SIZE +1 
				, (cur.y-1/2) * CELL_SIZE + 1 , CELL_SIZE - 2, CELL_SIZE - 2);
		}
		// 左移所有正在下掉的方块
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			cur.x --;
		}
		// 将左移后的每个方块的背景色涂成方块对应的颜色
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			// 设置填充颜色
			tetris_ctx.fillStyle = colors[cur.color];
			// 绘制矩形
			tetris_ctx.fillRect((cur.x-1/2) * CELL_SIZE + 1  
				, (cur.y-1/2) * CELL_SIZE + 1, CELL_SIZE - 2 , CELL_SIZE - 2);
		}
	}
}
// 定义右移方块的函数
var moveRight = function()
{
	// 定义能否右移的旗标
	var canRight = true;
	for (var i = 0 ; i < currentFall.length ; i++)
	{
		// 如果已到了最右边,不能右移
		if(currentFall[i].x >= TETRIS_COLS - 1/2)
		{
			canRight = false;
			break;
		}
		// 如果右边的位置已有方块,不能右移
		if (tetris_status[currentFall[i].y-1/2][currentFall[i].x + 1-1/2] != NO_BLOCK)
		{
			canRight = false;
			break;
		}
	}
	// 如果能右移
	if(canRight)
	{		
		// 将右移前的每个方块的背景色涂成白色
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			// 设置填充颜色
			tetris_ctx.fillStyle = ‘white‘;
			// 绘制矩形
			tetris_ctx.fillRect((cur.x-1/2) * CELL_SIZE + 1  
				, (cur.y-1/2) * CELL_SIZE + 1 , CELL_SIZE - 2 , CELL_SIZE - 2);
		}
		// 右移所有正在下掉的方块
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			cur.x ++;
		}
		// 将右移后的每个方块的背景色涂成各方块对应的颜色
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			// 设置填充颜色
			tetris_ctx.fillStyle = colors[cur.color];
			// 绘制矩形
			tetris_ctx.fillRect((cur.x-1/2) * CELL_SIZE + 1 
				, (cur.y-1/2) * CELL_SIZE + 1 , CELL_SIZE - 2, CELL_SIZE -2);
		}
	}
}
// 定义旋转方块的函数
var rotate = function()
{
	// 定义记录能否旋转的旗标
	var canRotate = true;
	for (var i = 0 ; i < currentFall.length ; i++)
	{
		var preX = currentFall[i].x;
		var preY = currentFall[i].y;
		// 始终以第三个方块作为旋转的中心,
		// i == 2时,说明是旋转的中心
		if(i != 2)
		{
			// 计算方块旋转后的x、y坐标
			var afterRotateX = currentFall[2].x + preY - currentFall[2].y;
			var afterRotateY = currentFall[2].y + currentFall[2].x - preX;
			// 如果旋转后所在位置已有方块,表明不能旋转
			if(tetris_status[afterRotateY-1/2][afterRotateX-1/2 ] != NO_BLOCK||afterRotateX < 1/2||afterRotateX > TETRIS_COLS)
			{
			 	canRotate = false;
			 	break;
			 }
		}
	}
	// 如果能旋转
	if(canRotate)
	{
		// 将旋转移前的每个方块的背景色涂成白色
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			// 设置填充颜色
			tetris_ctx.fillStyle = ‘white‘;
			// 绘制矩形
			tetris_ctx.fillRect((cur.x-1/2) * CELL_SIZE + 1  
				, (cur.y-1/2) * CELL_SIZE + 1 , CELL_SIZE - 2, CELL_SIZE - 2);
		}
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var preX = currentFall[i].x;
			var preY = currentFall[i].y;
			// 始终以第三个方块作为旋转的中心,
			// i == 2时,说明是旋转的中心
			if(i != 2)
			{
				currentFall[i].x = currentFall[2].x + 
					preY - currentFall[2].y;
				currentFall[i].y = currentFall[2].y + 
					currentFall[2].x - preX;
			}
		}
		// 将旋转后的每个方块的背景色涂成各方块对应的颜色
		for (var i = 0 ; i < currentFall.length ; i++)
		{
			var cur = currentFall[i];
			// 设置填充颜色
			tetris_ctx.fillStyle = colors[cur.color];
			// 绘制矩形
			tetris_ctx.fillRect((cur.x-1/2) * CELL_SIZE + 1 
				, (cur.y-1/2) * CELL_SIZE + 1 , CELL_SIZE - 2, CELL_SIZE - 2);
		}
	}
}
window.focus();
// 为窗口的按键事件绑定事件监听器
window.onkeydown = function(evt)
{
	switch(evt.keyCode)
	{
		// 按下了“向下”箭头
		case 40:
			if(!isPlaying)
				return;
			moveDown();
			break;
		// 按下了“向左”箭头
		case 37:
			if(!isPlaying)
				return;
			moveLeft();
			break;
		// 按下了“向右”箭头
		case 39:
			if(!isPlaying)
				return;
			moveRight();
			break;
		// 按下了“向上”箭头
		case 38:
			if(!isPlaying)
				return;
			rotate();
			break;
	}
}





	</script>
	<style type="text/css">
		@font-face {}
		body>div {
			font-size:13pt;
			padding-bottom: 8px;
			position: auto;
			float: left;
			margin-left:100px;
		}
		span {
			font-family: tmb;
			font-size:18pt;
			color: green;
		}
		h5{float: right; margin-top: 430px;margin-right:200px;}
		#div1{  height:500px;width:436px;float: left;margin-left:500px;}
*/	</style>
</head>
<body>
<h2 style=‘ height:50px;line-height:50px;overflow:hidden;text-align:center‘> 完美俄罗斯方块</h2>
<h5>原作:李刚<br>Debuged By:ChenZz~<br>增添右上角4*4的预测框功能</h5>
			<div style="width:336px; border:1px solid black;background:#ff9;float: left;margin-left:500px;"> 
				<div style="float:left;">速度:<span id="curSpeedEle"></span>
				当前积分:<span id="curScoreEle"></span></div>
				<div style="float:right;">最高积分:<span id="maxScoreEle"></span></div>
			</div>
<div id="div1">

</div>
</body>
</html>

  

前端作品五之——完美俄罗斯方块

标签:

原文地址:http://www.cnblogs.com/ChenZz-blog/p/4918717.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!