前端学习|回归前端学习第25天-实现俄罗斯方块小游戏8(实现单机版4—设置计时、消行加分、游戏结束标志)


增改game.js与local.js代码,实现对游戏的设置计时、消行加分、游戏结束标志等环节的设计

  • 计时
  • 计分
  • 游戏结束
  • 完整代码
    • local.js
    • game.js
  • 注意

前端学习|回归前端学习第25天-实现俄罗斯方块小游戏8(实现单机版4—设置计时、消行加分、游戏结束标志)
文章图片

计时 1.定义显示时间的div,并通过init赋值到dom中(在game.js中

2.通过local.js传入doms
3.game.js中写函数setTime,显示到界面
4.在local.js设置计时函数
1.定义显示时间的div,并通过init赋值到dom中(在game.js中 ) var timeDiv; 2.通过local.js传入doms timeDiv = doms.timeDiv; timeDiv: document.getElementById('time')3.game.js中写函数setTime,实现计时 var setTime = function (time) { timeDiv.innerHTML = time; }4.在local.js设置计时函数 // 时间计数器 var timeConut = 0; var time = 0; // 计时函数 var timeFunc = function () { timeConut = timeConut + 1; if (timeConut == 5) { timeConut = 0; time = time + 1; // 将更新的时间传入界面 game.setTime(time); } }

计分 1.反馈消行数目,从而switch来判断分数
2.addScore函数判断消行,实现加分,添加div模块,添加变量并显示到界面,通过doms传入
1.反馈消行数目,从而switch来判断分数,checkClear函数里添加line变量记录消行数目 var line = 0; if (clear) { line = line + 1; …… } 2.addScore函数判断消行,实现加分 move函数中添加判断,若游戏不结束且消行了,则函数判断并显示加分 if (line) { // 行数不为0,则传入addScore函数 game.addScore(line); } 计分函数 var addScore = function (line) { var s = 0; switch (line) { // 消除一行十分 case 1: s = 10; break; case 2: s = 40; break; case 3: s = 60; break; case 4: s = 80; break; default: break; } score = score + s; scoreDiv.innerHTML = score; }

游戏结束 gameover函数通过传入参数,判断是否获胜,并显示到界面
//添加游戏结束的div var resultDiv; // 游戏结束函数 var gameOver = function (win) { // 赢了 if (win) { resultDiv.innerHTML = '你赢了啦!'; } else { resultDiv.innerHTML = '你输了啦!'; } }local.js中调用gameOver函数 var gameOver = game.checkGameOver(); if (gameOver) { game.gameOver(false); stop(); } else { game.performNext(generateType(), generateDir()); } }

完整代码 local.js
var Local = function () { // 游戏对象 var game; // 时间间隔 200毫秒 var INTERVAL = 200; // 定时器 var timer = null; // 绑定键盘事件 // 时间计数器 var timeConut = 0; var time = 0; var bindKeyEvent = function () { document.onkeydown = function (e) { if (e.keyCode == 38) { // 向上 game.rotate(); } else if (e.keyCode == 39) { // 向右 game.right(); } else if (e.keyCode == 40) { // 向下 game.down(); } else if (e.keyCode == 37) { // 向左 game.left(); } else if (e.keyCode == 32) { // 空格键 game.fall(); } } } // 移动 var move = function () { timeFunc(); // 不能下降再调用 if (!game.down()) { // 落下的方块固定 game.fixed(); var line = game.checkClear(); if (line) { // 行数不为0,则传入addScore函数 game.addScore(line); } var gameOver = game.checkGameOver(); if (gameOver) { game.gameOver(false); stop(); } else { game.performNext(generateType(), generateDir()); } } } // 计时函数 var timeFunc = function () { timeConut = timeConut + 1; if (timeConut == 5) { timeConut = 0; time = time + 1; // 将更新的时间传入界面 game.setTime(time); } } // 随机生成下一个方块 var generateType = function () { // 随机生成0-6的整数 return Math.ceil(Math.random() * 7) - 1; } // 随机生成旋转次数 var generateDir = function () { // 随机生成0-3的整数 return Math.ceil(Math.random() * 4) - 1; }// 开始 var start = function () { var doms = { gameDiv: document.getElementById('game'), nextDiv: document.getElementById('next'), timeDiv: document.getElementById('time'), scoreDiv: document.getElementById('scpre'), resultDiv: document.getElementById('gameover') } game = new Game(); game.init(doms, generateType(), generateDir()); bindKeyEvent(); game.performNext(generateType(), generateDir()); timer = setInterval(move, INTERVAL); } // 结束,关闭计时 var stop = function () { if (timer) { clearInterval(timer); timer = null; } document.onkeydown = null; } // 导出API this.start = start; }

game.js
var Game = function () { //dom元素 var gameDiv; var nextDiv; var timeDiv; var scoreDiv; var resultDiv; // 分数 var score = 0; // 游戏矩阵 var gameData = https://www.it610.com/article/[ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ]; // 当前方块 var cur; // 下一个方块 var next; // divs var nextDivs = []; var gameDivs = []; // 初始化div var initDiv = function (container, data, divs) { for (var i = 0; i < data.length; i++) { var div = []; for (var j = 0; j < data[0].length; j++) { var newNode = document.createElement('div'); newNode.className = 'none'; newNode.style.top = (i * 20) + 'px'; newNode.style.left = (j * 20) + 'px'; // 建立一维数组 container.appendChild(newNode); div.push(newNode); } // 把一维数组放到多维数组中 divs.push(div); } }// 刷新div var refreshDiv = function (data, divs) { for (var i = 0; i < data.length; i++) { for (var j = 0; j < data[0].length; j++) { if (data[i][j] == 0) { divs[i][j].className = 'none'; } else if (data[i][j] == 1) { divs[i][j].className = 'done '; } else if (data[i][j] == 2) { divs[i][j].className = 'current'; } } } } // 检测点是否合法,即是否降落到最底部——pos为方块原点位置,x=cur.origin.x,y=cur.origin.y, var check = function (pos, x, y) { if (pos.x + x < 0) { // 超出上面 return false; } else if (pos.x + x >= gameData.length) { // 超出下面 return false; } else if (pos.y + y < 0) { // 到最左边 return false; } else if (pos.y + y >= gameData[0].length) { // 到最右边 return false; } else if (gameData[pos.x + x][pos.y + y] == 1) { // 已经有落下来的方块了 return false; } else { return true; }} // 检测数据是否合法,pos为原点,data为每次下降的方块的数据,为有方块存在的数据下降操作时做准备 var isValid = function (pos, data) { for (var i = 0; i < data.length; i++) { for (var j = 0; j < data[0].length; j++) { if (data[i][j] != 0) { if (!check(pos, i, j)) { // 不等于0且非法 return false; } } } } return true; } // 清除数据 var clearData = https://www.it610.com/article/function () { for (var i = 0; i < cur.data.length; i++) { if (check(cur.origin, i, j)) { for (var j = 0; j < cur.data[0].length; j++) { gameData[cur.origin.x + i][cur.origin.y + j] = 0; } } } } // 设置数据 var setData = function () { for (var i = 0; i < cur.data.length; i++) { for (var j = 0; j < cur.data[0].length; j++) { // 先判断是否合法 if (check(cur.origin, i, j)) { // 将cur.data[i][j]中的数据拷贝到gameData数组中 gameData[cur.origin.x + i][cur.origin.y + j] = cur.data[i][j]; } } } } // 下移设置 var down = function () { // 判断是否可以下降,方法写在square中 if (cur.canDown(isValid)) { clearData(); // cur.origin.x = cur.origin.x + 1; // var downJudge = new Square(); // cur = downJudge.down(); cur.down(); setData(); refreshDiv(gameData, gameDivs); return true; } else { // 不能再向下 return false; } } // 旋转设置 var rotate = function () { // 判断是否可以下降,方法写在square中 if (cur.canRotate(isValid)) { clearData(); cur.rotate(); setData(); refreshDiv(gameData, gameDivs); } }// 左移设置 var left = function () { // 判断是否可以,方法写在square中 if (cur.canLeft(isValid)) { clearData(); cur.left(); setData(); refreshDiv(gameData, gameDivs); } } // 右移设置 var right = function () { // 判断是否可以,方法写在square中 if (cur.canRight(isValid)) { clearData(); cur.right(); setData(); refreshDiv(gameData, gameDivs); } } // 方块移动到底部后固定住 var fixed = function () { for (var i = 0; i < cur.data.length; i++) { for (var j = 0; j < cur.data[0].length; j++) { // 判断合法性 if (check(cur.origin, i, j)) { if (gameData[cur.origin.x + i][cur.origin.y + j] == 2) { gameData[cur.origin.x + i][cur.origin.y + j] = 1; } } } } // 反馈到界面上 refreshDiv(gameData, gameDivs); } // 消行 var checkClear = function () { // 计分用,反映消行行数 var line = 0; for (var i = gameData.length - 1; i>= 0; i--) { var clear = true; for (var j = 0; j < gameData[0].length; j++) { if (gameData[i][j] != 1) { clear = false; break; } } if (clear) { line = line + 1; // 下移一行 for (var m = i; m > 0; m--) { for (var n = 0; n < gameData[0].length; n++) { gameData[m][n] = gameData[m - 1][n]; } } for (var n = 0; n < gameData[0].length; n++) { gameData[0][n] = 0; } i++; } } return line; } // 游戏结束 var checkGameOver = function () { var gameOver = false; for (var i = 0; i < gameData[0].length; i++) { if (gameData[1][i] == 1) { gameOver = true; } } return gameOver; } // 使用下一个方块 var performNext = function (type, dir) { // 下一个方块付给当前方块 cur = next; setData(); let squareDiv = new SquareFactory(); next = squareDiv.make(type, dir); refreshDiv(gameData, gameDivs); refreshDiv(next.data, nextDivs); } // 设置时间 var setTime = function (time) { timeDiv.innerHTML = time; } // 加分 var addScore = function () { var s = 0; switch (line) { // 消除一行十分 case 1: s = 10; break; case 2: s = 40; break; case 3: s = 60; break; case 4: s = 80; break; default: break; } score = score + s; scoreDiv.innerHTML = score; } // 游戏结束 var gameOver = function (win) { // 赢了 if (win) { resultDiv.innerHTML = '你赢了啦!'; } else { resultDiv.innerHTML = '你输了啦!'; } } // 初始化 doms对象包含两个内容gameDiv、nextDiv var init = function (doms, type, dir) { gameDiv = doms.gameDiv; nextDiv = doms.nextDiv; timeDiv = doms.timeDiv; scoreDiv = doms.scoreDiv; resultDiv = doms.resultDiv; let square = new SquareFactory(); next = square.make(type, dir); initDiv(gameDiv, gameData, gameDivs); initDiv(nextDiv, next.data, nextDivs); refreshDiv(next.data, nextDivs); } // 导出API,在外部local里就可以调用这个init函数了 this.init = init; this.down = down; this.left = left; this.right = right; this.rotate = rotate; this.fall = function () { // 返回false就不能再下降 while (down()); } this.fixed = fixed; this.performNext = performNext; this.check = check; this.checkClear = checkClear; this.checkGameOver = checkGameOver; this.setTime = setTime; this.addScore = addScore; this.gameOver = gameOver; }

注意 【前端学习|回归前端学习第25天-实现俄罗斯方块小游戏8(实现单机版4—设置计时、消行加分、游戏结束标志)】1.在geme.js中设计函数后,一定要在下面导出,才可以在别处调用该函数
2.添加元素到界面,要先定义一个变量,并在init函数中通过doms传入

    推荐阅读