一边练习一下javascript,一边搞的稍微有趣一点。
这次的界面就是个table表格。其实所有的操作只要操作tabel的class就可以了。我这里把颜色直接用 cell.style.backgroundColor
来设置内联样式的属性了。
完整代码如下,预先显示下一个方块的功能没做。Game Over也没有写。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>俄罗斯方块</title> <style> p.tips {margin-top: 20px; text-align: center;} table#gameUI {margin: 30px auto;} td {width: 20px; height: 20px; border: 1px solid red;} td.wall {background-color: red;} </style></head><body><p class="tips">按回车开始游戏</p><table id="gameUI"></table></body><script> // 参数设置 var rows = 22, cells = 14; // 界面的高度和宽度 // 获取元素 var tab = document.getElementById('gameUI'); var tips = document.getElementsByClassName('tips')[0]; // 设置变量 var control; // 当前控制的方块 var score = 0; // 分数 var scoreConf = [100, 200, 300, 350]; // 一次小几行,分数不同 init(); function init() { // 为了页面时的初始化 createTab(); bindKeyEnter(); // gameStart() } function bindKeyEnter() { // 按下回车处理的事件 document.onkeydown = function (ev) { if (ev.keyCode===13){ tips.innerHTML ='游戏开始'; document.onkeydown = null; gameStart(); } } } function gameStart() { // 开始游戏 bindKeysForGame(); tips.innerHTML = '按 Z 或 X 旋转方块'; control = createSqu(); control.position = [1, 4]; // 添加blocks[0]的位置属性 map(control); setInterval("move('down')", 500) } function createSqu() { // 创建一个方块 var types = [ {'name': "方块", 'color': 'saddlebrown', 'blocks': [[0, 0], [0, 1], [1, 0], [1, 1]], 'styleIndex': 0, 'styles': [ [[0, 0], [0, 1], [1, 0], [1, 1]] ]}, {'name': "7形", 'color': 'green', 'blocks': [[0, 0], [0, 1], [1, 1], [2, 1]], 'styleIndex': 0, 'styles': [ [[0, 0], [0, 1], [1, 1], [2, 1]], [[1, 0], [1, 1], [1, 2], [0, 2]], [[0, 0], [1, 0], [2, 0], [2, 1]], [[0, 0], [1, 0], [0, 1], [0, 2]] ]}, {'name': "反7", 'color': 'green', 'blocks': [[0, 0], [0, 1], [1, 0], [2, 0]], 'styleIndex': 0, 'styles': [ [[0, 0], [0, 1], [1, 0], [2, 0]], [[0, 0], [0, 1], [0, 2], [1, 2]], [[0, 1], [1, 1], [2, 0], [2, 1]], [[0, 0], [1, 0], [1, 1], [1, 2]] ]}, {'name': "长条", 'color': 'darkorange', 'blocks': [[0, 0], [0, 1], [0, 2], [0, 3]], 'styleIndex': 0, 'styles': [ [[0, 0], [0, 1], [0, 2], [0, 3]], [[0, 0], [1, 0], [2, 0], [3, 0]] ]}, {'name': "丁字", 'color': 'blue', 'blocks': [[0, 0], [0, 1], [1, 1], [0, 2]], 'styleIndex': 0, 'styles': [ [[0, 0], [0, 1], [1, 1], [0, 2]], [[1, 0], [0, 1], [1, 1], [2, 1]], [[1, 0], [1, 1], [0, 1], [1, 2]], [[0, 0], [1, 0], [1, 1], [2, 0]] ]}, {'name': "Z字", 'color': 'gold', 'blocks': [[0, 0], [0, 1], [1, 1], [1, 2]], 'styleIndex': 0, 'styles': [ [[0, 0], [0, 1], [1, 1], [1, 2]], [[0, 1], [1, 0], [1, 1], [2, 0]] ]}, {'name': "反Z", 'color': 'gold', 'blocks': [[1, 0], [1, 1], [0, 1], [0, 2]], 'styleIndex': 0, 'styles': [ [[1, 0], [1, 1], [0, 1], [0, 2]], [[0, 0], [1, 0], [1, 1], [2, 1]] ]} ]; var index = Math.floor(Math.random()*types.length+1); return types[index-1] } function map(square) { // 把方块画在表格里 var rubber = arguments[1] ? arguments[1] : false; for (var i=0; i<square.blocks.length; i++) { var cell = tab.rows[square.blocks[i][0]+square.position[0]].cells[square.blocks[i][1]+square.position[1]]; if (rubber){ cell.style.backgroundColor = ''; cell.classList.remove('control') } else { cell.style.backgroundColor = square.color; cell.classList.add('control') } } } function fixed(square){ // 固定方块 for (var i=0; i<square.blocks.length; i++) { var cell = tab.rows[square.blocks[i][0]+square.position[0]].cells[square.blocks[i][1]+square.position[1]]; cell.classList.remove('control'); cell.classList.add('fixed') } } function bindKeysForGame() { // 游戏时候需要绑定的按键 document.onkeydown = function (ev) { switch (ev.keyCode) { case 37: // 向左 move('left'); break; case 38: // 向上 // move('up'); change(); break; case 39: // 向右 move('right'); break; case 40: // 向下 move('down'); break; case 90: // 字母Z change(true); break; case 88: // 字母X change(); break; // default: // tips.innerHTML = ev.keyCode; } } } function change() { // 改变形状 var contrarotate = arguments[0] ? arguments[0] : false; if (contrarotate) { control.styleIndex -= 1; if (control.styleIndex < 0) { control.styleIndex = control.styles.length-1; } } else { control.styleIndex += 1; if (control.styleIndex > control.styles.length-1){ control.styleIndex = 0; } } var target = [[0,0],[0,0],[0,0],[0,0]]; for (var i=0; i<control.styles[control.styleIndex].length; i++){ target[i][0] = control.styles[control.styleIndex][i][0]+control.position[0]; target[i][1] = control.styles[control.styleIndex][i][1]+control.position[1]; } if (canMove(target)){ map(control, true); for (var j=0; j<control.blocks.length; j++){ control.blocks[j][0] = control.styles[control.styleIndex][j][0]; control.blocks[j][1] = control.styles[control.styleIndex][j][1]; } map(control) } } function move(mode) { var row, cell; switch (mode){ case 'left': row = 0; cell = -1; break; case 'right': row = 0; cell = 1; break; case 'up': row = -1; cell = 0; break; case 'down': row = 1; cell = 0; break; } var target = [[0,0],[0,0],[0,0],[0,0]]; for (var i=0; i<control.blocks.length; i++){ target[i][0] = control.blocks[i][0]+control.position[0]+row; target[i][1] = control.blocks[i][1]+control.position[1]+cell; } if (canMove(target)){ map(control, true); control.position[0] += row; control.position[1] += cell; map(control) } else { if (mode==='down') { // 向下移动,并且判定为不可移动,则固定 fixed(control); // 固定住方块 checkAndClean(control); // 检查消行 control = createSqu(); control.position = [1, 4]; // 添加blocks[0]的位置属性 map(control); } } } function checkAndClean(square) { // 检查并消除 var checked = []; var cleaned = []; var row; for (var i=0; i<square.blocks.length; i++){ row = square.blocks[i][0] + square.position[0]; if (checked.indexOf(row) === -1){ checked.push(row); var needClean = true; for (var j=1; j<cells-1; j++ ) { var cell = tab.rows[row].cells[j]; if(cell.className.search(/\b(fixed)\b/) === -1){ needClean = false; break; } } if (needClean) { // 消除一行 cleaned.push(row); for (var k=1; k<cells-1; k++) { cell = tab.rows[row].cells[k]; cell.classList.remove('fixed'); cell.style.backgroundColor = ''; } } } } cleaned.length && addScore(cleaned.length) && goDown(cleaned); // 结算分数,然后下沉 } function addScore(n) { n = n<=scoreConf.length ? n : scoreConf[scoreConf.length-1]; score += scoreConf[n-1]; tips.innerHTML = "分数:" + score; return true } function goDown(list) { // 消行后的沉降 var count = 0; for (var i=list.length; i--;){ for (var r=list[i]-1; r--;){ tab.rows[r+2+count].innerHTML = tab.rows[r+1+count].innerHTML } count += 1; } } function canMove(target) { // 是否可以移动 for (var j=0; j<target.length; j++){ var cell = tab.rows[target[j][0]].cells[target[j][1]]; if(cell.className.search(/\b(wall|fixed)\b/) > -1){ return false } } return true } function createTab() { // 绘制游戏界面 for (var r=rows; r--;){ var row = tab.insertRow(); for (var c=cells; c--;){ var cell = row.insertCell(); if (r===0 || r===rows-1 || c===0 || c===cells-1){ cell.classList.add('wall'); } } } }</script></html>