标签:
---恢复内容开始---
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