diff --git a/index.js b/index.js index 2083e7c..17e5265 100644 --- a/index.js +++ b/index.js @@ -6,21 +6,24 @@ * 方块 * @param params */ -const block = function (params) { - //方块矩阵 - let arr = params.arr, - curLeft = params.curLeft, - curTop = params.curTop; - //下一个落下方块矩阵 - const nextArr = params.nextArr; - //方块大小 - const BLOCK_SIZE = params.BLOCK_SIZE; - //当前画布大小 - const siteSize = params.siteSize; - //历史最高得分 - const highestScore = params.highestScore; - //方块下落速度 - const delay = params.delay; +class Block { + constructor(params) { + //方块矩阵 + this.arr = params.arr; + this.curLeft = params.curLeft; + this.curTop = params.curTop; + //下一个落下方块矩阵 + this.nextArr = params.nextArr; + //方块大小 + this.BLOCK_SIZE = params.BLOCK_SIZE; + //当前画布大小 + this.siteSize = params.siteSize; + //历史最高得分 + this.highestScore = params.highestScore; + //方块下落速度 + this.delay = params.delay; + } + /** * 画当前方块 * @param i @@ -28,21 +31,22 @@ const block = function (params) { * @param className 创建方块的className * @param el 容纳方块的element */ - const draw = function (i, j, className, el) { - let left = className === 'nextModel' ? (j + 1) * BLOCK_SIZE - (__siteSize__.left + __siteSize__.width / 2 - BLOCK_SIZE) : j * BLOCK_SIZE; - let top = className === 'nextModel' ? (i + 1) * BLOCK_SIZE - siteSize.top : i * BLOCK_SIZE; + draw(i, j, className, el) { + let left = className === 'nextModel' ? (j + 1) * this.BLOCK_SIZE - (this.siteSize.left + this.siteSize.width / 2 - this.BLOCK_SIZE) : j * this.BLOCK_SIZE; + let top = className === 'nextModel' ? (i + 1) * this.BLOCK_SIZE - this.siteSize.top : i * this.BLOCK_SIZE; let model = document.createElement('div'); model.className = className; model.style.left = `${left}px`; model.style.top = `${top}px`; el.appendChild(model); }; + /** * 顺时针旋转矩阵 * @param arr 需要旋转的矩阵 * @returns {{newArr: Array, lefts: Array, tops: Array}} */ - const clockwise = function (arr) { + clockwise(arr) { let newArr = []; for (let i = 0; i < arr[0].length; i++) { let temArr = []; @@ -53,9 +57,9 @@ const block = function (params) { } let lefts = [], tops = []; - checkArrWith1(newArr, function (i, j) { - lefts.push(j * BLOCK_SIZE); - tops.push(i * BLOCK_SIZE); + this.checkArrWith1(newArr, function (i, j) { + lefts.push(j * this.BLOCK_SIZE); + tops.push(i * this.BLOCK_SIZE); }); return { newArr: newArr, @@ -63,6 +67,7 @@ const block = function (params) { tops: tops }; }; + /** * 判断数组中值为1的下标 * @param arr 需要判断的数组 @@ -70,28 +75,29 @@ const block = function (params) { * @param className 作为draw回调函数的参数 * @param el 作为draw回调函数的参数 */ - const checkArrWith1 = function (arr, callback, className, el) { + checkArrWith1(arr, callback, className, el) { for (let i = 0; i <= arr.length - 1; i++) { for (let j = 0; j <= arr[0].length - 1; j++) { if (arr[i][j] === 1) { - callback(i + curTop, j + curLeft, className, el); + callback.call(this, i + this.curTop, j + this.curLeft, className, el); } } } }; + /** * 获取边界 * @param curLeft 当前方块left * @param curTop 当前方块top * @returns {*} 返回左右下边界 */ - const getInterval = function (curLeft, curTop) { + getInterval(curLeft, curTop) { let inactiveModel = document.querySelectorAll('.inactiveModel'); if (inactiveModel.length === 0) { return { - highest: siteSize.top + siteSize.height, - leftmost: siteSize.left - BLOCK_SIZE, - rightmost: siteSize.left + siteSize.width + highest: this.siteSize.top + this.siteSize.height, + leftmost: this.siteSize.left - this.BLOCK_SIZE, + rightmost: this.siteSize.left + this.siteSize.width }; } else { let tops = [], @@ -114,19 +120,19 @@ const block = function (params) { } } if (tops.length === 0) { - highest = siteSize.top + siteSize.height; + highest = this.siteSize.top + this.siteSize.height; } else { tops = Array.from(tops, top => parseInt(top.replace('px', ''))); highest = Math.min(...tops); } if (lefts.length === 0) { - leftmost = siteSize.left - BLOCK_SIZE; + leftmost = this.siteSize.left - this.BLOCK_SIZE; } else { lefts = Array.from(lefts, left => parseInt(left.replace('px', ''))); leftmost = Math.max(...lefts); } if (rights.length === 0) { - rightmost = siteSize.left + siteSize.width + rightmost = this.siteSize.left + this.siteSize.width } else { rights = Array.from(rights, right => parseInt(right.replace('px', ''))); rightmost = Math.min(...rights); @@ -138,6 +144,7 @@ const block = function (params) { }; } }; + /** * 判断当前方块是否能移动||变形 * @param arr 将要判断的方块 @@ -146,46 +153,47 @@ const block = function (params) { * @param move * @returns */ - const canMove = function (arr, displacement = 1, deform = false, move = { + canMove(arr, displacement = 1, deform = false, move = { canMoveRight: true, canMoveDown: true, canMoveLeft: true, moveDownDivide: [] }) { - checkArrWith1(arr, function (i, j) { - let {highest, leftmost, rightmost} = getInterval(`${j * BLOCK_SIZE}px`, `${i * BLOCK_SIZE}px`); + this.checkArrWith1(arr, function (i, j) { + let {highest, leftmost, rightmost} = this.getInterval(`${j * this.BLOCK_SIZE}px`, `${i * this.BLOCK_SIZE}px`); if (deform) { - if (BLOCK_SIZE * (j + 1) > rightmost) { + if (this.BLOCK_SIZE * (j + 1) > rightmost) { move.canMoveRight = false; } - if (BLOCK_SIZE * (i + displacement) > highest) { + if (this.BLOCK_SIZE * (i + displacement) > highest) { move.canMoveDown = false; - move.moveDownDivide.push(highest - BLOCK_SIZE * (i + 1)); + move.moveDownDivide.push(highest - this.BLOCK_SIZE * (i + 1)); } - if (BLOCK_SIZE * (j - 1) < leftmost) { + if (this.BLOCK_SIZE * (j - 1) < leftmost) { move.canMoveLeft = false; } } else { - if (BLOCK_SIZE * (j + 1) >= rightmost) { + if (this.BLOCK_SIZE * (j + 1) >= rightmost) { move.canMoveRight = false; } - if (BLOCK_SIZE * (i + displacement) >= highest) { + if (this.BLOCK_SIZE * (i + displacement) >= highest) { move.canMoveDown = false; - move.moveDownDivide.push(highest - BLOCK_SIZE * (i + 1)); + move.moveDownDivide.push(highest - this.BLOCK_SIZE * (i + 1)); } - if (BLOCK_SIZE * (j - 1) <= leftmost) { + if (this.BLOCK_SIZE * (j - 1) <= leftmost) { move.canMoveLeft = false; } } }); return move; }; + /** * 消除砖块 * @param window 用于取得元素最终样式 * @returns {Array} 返回每一行的元素数组,个数,高度 */ - const eliminate = function (window) { + eliminate(window) { let res = [], inactiveModels = [...document.querySelectorAll('.inactiveModel')]; inactiveModels.sort(function (a, b) { @@ -209,193 +217,206 @@ const block = function (params) { } return res; }; + /** * 当灰色砖块高于画布高偏移量,游戏结束 * @returns {boolean} */ - const gameOver = function () { + gameOver() { const inactiveModels = document.querySelectorAll('.inactiveModel'); let tops = []; for (let v of inactiveModels) { tops.push(parseInt(window.getComputedStyle(v).top.replace('px', ''))); } - return Math.min(...tops) <= siteSize.top; + return Math.min(...tops) <= this.siteSize.top; }; - const fill = function (curTop, curLeft) { + + /** + * gameOver填充动画 + * @param curTop + * @param curLeft + */ + static fill(curTop, curLeft) { let model = document.createElement('div'); model.className = 'inactiveModel'; model.style.left = `${curLeft}px`; model.style.top = `${curTop}px`; document.body.appendChild(model); }; - //清除下一个方块 - let next = document.querySelector('#next'); - next.innerHTML = null; - //画出当前方块 - checkArrWith1(arr, draw, 'activityModel', document.body); - //画出下一个方块 - checkArrWith1(nextArr, draw, 'nextModel', next); - //记录当前方块 - let activityModels = document.querySelectorAll('.activityModel'); + /** - * 方块自由下落 - * @type {number} + * 当前掉落方块初始化 */ - const fallDown = setTimeout(function loop() { - let moveDown = canMove(arr).canMoveDown; - if (moveDown) { - for (let v of activityModels) { - v.style.top = `calc(${v.style.top} + ${BLOCK_SIZE}px)`; - } - curTop++; - setTimeout(loop, delay / window.__level__); - } else { - for (let i = 0; i < activityModels.length; i++) { - activityModels[i].className = 'inactiveModel' - } - let res = eliminate(window); - for (let i = 0; i < res.length; i++) { - let {count, models, top} = res[i]; - if (count === parseInt(siteSize.width / BLOCK_SIZE)) { - for (let j = 0; j < models.length; j++) { - document.body.removeChild(models[j]); - } - let inactiveModels = document.querySelectorAll('.inactiveModel'); - for (let v of inactiveModels) { - if (parseInt(window.getComputedStyle(v).top.replace('px', '')) < top) { - v.style.top = `calc(${window.getComputedStyle(v).top} + ${BLOCK_SIZE}px)`; - } - } - window.__score__ += window.__level__ * 100; - let score = document.querySelector('#score'); - score.innerText = window.__score__; - //level最高为4 - //升级规则为当前消除数大于等于level*10 - if (window.__score__ - (window.__level__ - 1) * (window.__level__ - 1) * 1000 >= window.__level__ * window.__level__ * 1000 && window.__level__ <= 4) { - window.__level__++; - let level = document.querySelector('#level'); - level.innerText = window.__level__; - } + init() { + //清除下一个方块 + let next = document.querySelector('#next'); + next.innerHTML = null; + //画出当前方块 + this.checkArrWith1(this.arr, this.draw, 'activityModel', document.body); + //画出下一个方块 + this.checkArrWith1(this.nextArr, this.draw, 'nextModel', next); + //记录当前方块 + let activityModels = document.querySelectorAll('.activityModel'); + /** + * 方块自由下落 + * @type {number} + */ + const fallDown = setTimeout(function loop() { + let moveDown = this.canMove(this.arr).canMoveDown; + if (moveDown) { + for (let v of activityModels) { + v.style.top = `calc(${v.style.top} + ${this.BLOCK_SIZE}px)`; } - } - if (!gameOver()) { - init(nextArr); + this.curTop++; + setTimeout(loop.bind(this), this.delay / window.__level__); } else { - console.log('Game over~'); - next.innerHTML = null; - let curTop = siteSize.height + siteSize.top - BLOCK_SIZE, - curLeft = siteSize.width + siteSize.left - BLOCK_SIZE; - let fillId = setInterval(function () { - fill(curTop, curLeft); - curLeft -= BLOCK_SIZE; - if (curLeft < siteSize.left) { - curLeft = siteSize.width + siteSize.left - BLOCK_SIZE; - curTop -= BLOCK_SIZE; - } - if (curTop < siteSize.top) { - clearInterval(fillId); - let restart = document.querySelector('.restart'); - restart.style.display = 'block'; - restart.onclick = function (event) { - event.preventDefault(); - restart.style.display = 'none'; - let inactiveModels = [...document.querySelectorAll('.inactiveModel')]; - if (inactiveModels.length > 0) { - for (let v of inactiveModels) { - document.body.removeChild(v); - } - } - if (highestScore < window.__score__) { - localStorage.setItem('highestScore', window.__score__); - let highestScoreDiv = document.querySelector('#highest-score'); - highestScoreDiv.innerText = window.__score__; + for (let i = 0; i < activityModels.length; i++) { + activityModels[i].className = 'inactiveModel' + } + let res = this.eliminate(window); + for (let i = 0; i < res.length; i++) { + let {count, models, top} = res[i]; + if (count === parseInt(this.siteSize.width / this.BLOCK_SIZE)) { + for (let j = 0; j < models.length; j++) { + document.body.removeChild(models[j]); + } + let inactiveModels = document.querySelectorAll('.inactiveModel'); + for (let v of inactiveModels) { + if (parseInt(window.getComputedStyle(v).top.replace('px', '')) < top) { + v.style.top = `calc(${window.getComputedStyle(v).top} + ${this.BLOCK_SIZE}px)`; } - window.__score__ = 0; - let score = document.querySelector('#score'); - score.innerText = window.__score__; - window.__level__ = 1; + } + window.__score__ += window.__level__ * 100; + let score = document.querySelector('#score'); + score.innerText = window.__score__; + //level最高为4 + //升级规则为当前消除数大于等于level*10 + if (window.__score__ - (window.__level__ - 1) * (window.__level__ - 1) * 1000 >= window.__level__ * window.__level__ * 1000 && window.__level__ <= 4) { + window.__level__++; let level = document.querySelector('#level'); level.innerText = window.__level__; - init(); } } - }, 30); - } - clearTimeout(fallDown); - } - }, delay / window.__level__); - /** - * 键盘事件 - * @param e - */ - document.onkeydown = function (e) { - const key = e.keyCode; - let move, - canMoveLeft, - canMoveRight, - canMoveDown, - moveDownDivide; - switch (key) { - //space - case 32: - let displacement = 2; - move = canMove(arr, displacement); - canMoveDown = move.canMoveDown; - if (canMoveDown) { - for (let v of activityModels) { - v.style.top = `calc(${v.style.top} + ${displacement} * ${BLOCK_SIZE}px)`; - } - curTop += displacement; + } + if (!this.gameOver()) { + init(this.nextArr); } else { - moveDownDivide = Math.min(...move.moveDownDivide); - if (moveDownDivide >= BLOCK_SIZE) { + console.log('Game over~'); + next.innerHTML = null; + let curTop = this.siteSize.height + this.siteSize.top - this.BLOCK_SIZE, + curLeft = this.siteSize.width + this.siteSize.left - this.BLOCK_SIZE; + let fillId = setInterval(function () { + Block.fill(curTop, curLeft); + curLeft -= this.BLOCK_SIZE; + if (curLeft < this.siteSize.left) { + curLeft = this.siteSize.width + this.siteSize.left - this.BLOCK_SIZE; + curTop -= this.BLOCK_SIZE; + } + if (curTop < this.siteSize.top) { + clearInterval(fillId); + let restart = document.querySelector('.restart'); + restart.style.display = 'block'; + restart.onclick = (e)=> { + e.preventDefault(); + restart.style.display = 'none'; + let inactiveModels = [...document.querySelectorAll('.inactiveModel')]; + if (inactiveModels.length > 0) { + for (let v of inactiveModels) { + document.body.removeChild(v); + } + } + if (this.highestScore < window.__score__) { + localStorage.setItem('highestScore', window.__score__); + let highestScoreDiv = document.querySelector('#highest-score'); + highestScoreDiv.innerText = window.__score__; + } + window.__score__ = 0; + let score = document.querySelector('#score'); + score.innerText = window.__score__; + window.__level__ = 1; + let level = document.querySelector('#level'); + level.innerText = window.__level__; + this.init(); + } + } + }.bind(this), 30); + } + clearTimeout(fallDown); + } + }.bind(this), this.delay / window.__level__); + /** + * 键盘事件 + * @param e + */ + document.onkeydown = (e)=> { + const key = e.keyCode; + let move, + canMoveLeft, + canMoveRight, + canMoveDown, + moveDownDivide; + switch (key) { + //space + case 32: + let displacement = 2; + move = this.canMove(this.arr, displacement); + canMoveDown = move.canMoveDown; + if (canMoveDown) { for (let v of activityModels) { - v.style.top = `calc(${v.style.top} + ${BLOCK_SIZE}px)`; + v.style.top = `calc(${v.style.top} + ${displacement} * ${this.BLOCK_SIZE}px)`; + } + this.curTop += displacement; + } else { + moveDownDivide = Math.min(...move.moveDownDivide); + if (moveDownDivide >= this.BLOCK_SIZE) { + for (let v of activityModels) { + v.style.top = `calc(${v.style.top} + ${this.BLOCK_SIZE}px)`; + } + this.curTop++; } - curTop++; } - } - break; - //left - case 37: - canMoveLeft = canMove(arr).canMoveLeft; - if (canMoveLeft) { - for (let v of activityModels) { - v.style.left = `calc(${v.style.left} - ${BLOCK_SIZE}px)`; + break; + //left + case 37: + canMoveLeft = this.canMove(this.arr).canMoveLeft; + if (canMoveLeft) { + for (let v of activityModels) { + v.style.left = `calc(${v.style.left} - ${this.BLOCK_SIZE}px)`; + } + this.curLeft--; } - curLeft--; - } - break; - //top - case 38: - let {newArr, lefts, tops}= clockwise(arr); - move = canMove(newArr, 1, true); - canMoveDown = move.canMoveDown; - canMoveRight = move.canMoveRight; - if (canMoveRight && canMoveDown) { - //记录转变后的矩阵 - arr = newArr; - for (let i in lefts) { - activityModels[i].style.left = `${lefts[i]}px`; - activityModels[i].style.top = `${tops[i]}px`; + break; + //top + case 38: + let {newArr, lefts, tops}= this.clockwise(this.arr); + move = this.canMove(newArr, 1, true); + canMoveDown = move.canMoveDown; + canMoveRight = move.canMoveRight; + if (canMoveRight && canMoveDown) { + //记录转变后的矩阵 + this.arr = newArr; + for (let i in lefts) { + activityModels[i].style.left = `${lefts[i]}px`; + activityModels[i].style.top = `${tops[i]}px`; + } } - } - break; - //right - case 39: - canMoveRight = canMove(arr).canMoveRight; - if (canMoveRight) { - for (let v of activityModels) { - v.style.left = `calc(${v.style.left} + ${BLOCK_SIZE}px)`; + break; + //right + case 39: + canMoveRight = this.canMove(this.arr).canMoveRight; + if (canMoveRight) { + for (let v of activityModels) { + v.style.left = `calc(${v.style.left} + ${this.BLOCK_SIZE}px)`; + } + this.curLeft++; } - curLeft++; - } - break; - default: - break; - } - }; -}; + break; + default: + break; + } + }; + } +} /** * init */ @@ -417,7 +438,8 @@ const init = function (nextArr) { highestScore: __highestScore__, delay: delay }; - block(params); + let block = new Block(params); + block.init(); }; window.onload = function () { @@ -471,15 +493,15 @@ window.onload = function () { [[0, 1, 0], [1, 1, 1]], [[1, 0], [1, 1], [1, 0]], //Z - [[1,1,0],[0,1,1]], - [[0,1],[1,1],[1,0]], - [[1,1,0],[0,1,1]], - [[0,1],[1,1],[1,0]], + [[1, 1, 0], [0, 1, 1]], + [[0, 1], [1, 1], [1, 0]], + [[1, 1, 0], [0, 1, 1]], + [[0, 1], [1, 1], [1, 0]], //倒Z - [[0,1,1],[1,1,0]], - [[1,0],[1,1,],[0,1]], - [[0,1,1],[1,1,0]], - [[1,0],[1,1,],[0,1]] + [[0, 1, 1], [1, 1, 0]], + [[1, 0], [1, 1,], [0, 1]], + [[0, 1, 1], [1, 1, 0]], + [[1, 0], [1, 1,], [0, 1]] ]; init(); };